/* ==========================================================
   Pepla WMS - unified stylesheet
   Built from the five page files with no visual change.
   Rules shared by all five pages are unscoped; every other
   rule is scoped to the pages that had it, via data-page.
   ========================================================== */

@keyframes fadeIn { from { opacity:0; transform: translateY(8px); } to { opacity:1; transform: translateY(0); } }
@keyframes spin {to{transform:rotate(360deg);}}
@keyframes pulse { 0%,100% { opacity:0.4; } 50% { opacity:0.9; } }

/* ---------- shared by all five pages ---------- */
:root {
  --bg: #0f0f1a;
  --surface: #1a1a2e;
  --surface2: #16213e;
  --border: rgba(213,169,153,0.18);
  --accent: #D5A999;
  --accent-hover: #CC9783;
  --accent-active: #BE8974;
  --accent-light: #D7BFB6;
  --text: #f0ede6;
  --text-muted: #9a9098;
  --text-placeholder: rgba(240,237,230,0.4);
  --text-disabled: rgba(240,237,230,0.3);
  --success: #4ade80;
  --error: #f87171;
  --warning: #fbbf24;
  --info: #c084fc;
  --processing: #60a5fa;
  --overlay: rgba(0,0,0,0.65);
  --disabled-bg: rgba(255,255,255,0.02);
  --disabled-border: rgba(255,255,255,0.06);
  --hover-bg: rgba(255,255,255,0.03);
  --radius: 12px;
  --radius-sm: 8px;
  --on-accent: #1a1a2e;
}
:root {
  --duration-fast: 120ms;
  --duration-base: 200ms;
  --duration-slow: 300ms;
  --ease: cubic-bezier(0.4,0,0.2,1);
}
[data-theme="dark"] {
  --bg: #0f0f1a;
  --surface: #1a1a2e;
  --surface2: #16213e;
  --border: rgba(213,169,153,0.18);
  --accent: #D5A999;
  --accent-hover: #CC9783;
  --accent-active: #BE8974;
  --accent-light: #D7BFB6;
  --text: #f0ede6;
  --text-muted: #9a9098;
  --text-placeholder: rgba(240,237,230,0.4);
  --text-disabled: rgba(240,237,230,0.3);
  --success: #4ade80;
  --error: #f87171;
  --warning: #fbbf24;
  --info: #c084fc;
  --processing: #60a5fa;
  --overlay: rgba(0,0,0,0.65);
  --disabled-bg: rgba(255,255,255,0.02);
  --disabled-border: rgba(255,255,255,0.06);
  --hover-bg: rgba(255,255,255,0.03);
  --radius: 12px;
  --radius-sm: 8px;
  --on-accent: #1a1a2e;
}
[data-theme="light"] {
  --bg: #FAFAF8;
  --surface: #FFFFFF;
  --surface2: #F5F3EF;
  --border: #E8E5DF;
  --accent: #B16043;
  --accent-hover: #9B543A;
  --accent-active: #854832;
  --accent-light: #C2795F;
  --text: #1A1A1A;
  --text-muted: #6B6560;
  --text-placeholder: rgba(26,26,26,0.35);
  --text-disabled: rgba(26,26,26,0.3);
  --success: #15803D;
  --error: #DC2626;
  --warning: #B45309;
  --info: #7C3AED;
  --processing: #2563EB;
  --overlay: rgba(0,0,0,0.4);
  --disabled-bg: rgba(0,0,0,0.02);
  --disabled-border: rgba(0,0,0,0.06);
  --hover-bg: rgba(0,0,0,0.02);
  --radius: 12px;
  --radius-sm: 8px;
  --on-accent: #FFFFFF;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
  -webkit-tap-highlight-color: transparent;
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
[data-theme="dark"] body {
  background-image: radial-gradient(ellipse at 20% 20%, rgba(192,132,252,0.06) 0%, transparent 50%), radial-gradient(ellipse at 80% 80%, rgba(213,169,153,0.07) 0%, transparent 50%);
  background-attachment: fixed;
}
svg {
  display: block;
}
.theme-toggle .tt-thumb svg {
  width: 13px;
  height: 13px;
}
[data-theme="light"] .theme-toggle .tt-thumb {
  transform: translateX(24px);
}

/* ---------- shared by dashboard / transfer / settings / login ---------- */
html:where([data-page="dashboard"], [data-page="transfer"], [data-page="settings"], [data-page="login"]) {
  height: 100%;
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"])::-webkit-scrollbar, :where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) *::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

/* ---------- shared by dashboard / transfer / settings / login ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"], html[data-page="login"]) body {
  height: 100%;
}
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"], html[data-page="login"]) body {
  background: var(--bg);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  line-height: 1.55;
  min-height: 100vh;
  transition: background var(--duration-base) var(--ease), color var(--duration-base) var(--ease);
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"])::-webkit-scrollbar-track, :where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) *::-webkit-scrollbar-track {
  background: transparent;
}
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"])::-webkit-scrollbar-thumb, :where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) *::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 8px;
  border: 2px solid var(--surface);
  background-clip: padding-box;
}
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"])::-webkit-scrollbar-thumb:hover, :where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) *::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
  border-color: var(--surface);
  background-clip: padding-box;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .icon-16 {
  width: 16px;
  height: 16px;
}
:where(html[data-shell="app"]) .icon-20 {
  width: 20px;
  height: 20px;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
/* [Uniformity, 4 Sep 2026] ONE toast component. It was 21 rules with three
   different geometries, spread over 4,800 lines of this file, and .toast-item.error
   alone was written out four times identically.

   The Scanner was never the odd one out: its layout IS the <=640px layout
   below, hardcoded, because it is a phone page. Above 640px it now joins the
   other three - the only visible change here, and Mustafa's call.

   z-index 301 is measured, not chosen. settings.html puts a confirm dialog at
   300 and its toast was already 301 to clear it; the other three sat at 201,
   BELOW their own .sheet-overlay at 220, so a toast raised while a sheet was
   open was painted behind it. 301 clears every overlay on every page. */
:where(html[data-shell="app"]) .toast-stack {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 301;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
  pointer-events: none;
}
:where(html[data-shell="app"]) .toast-item {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface2);
  border: 1px solid var(--border);
  padding: 11px 16px;
  border-radius: var(--radius-sm);
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  color: var(--text);
  box-shadow: 0 4px 16px rgba(0,0,0,0.3);
  opacity: 0;
  transform: translateX(20px);
  transition: opacity var(--duration-slow) var(--ease),transform var(--duration-slow) var(--ease);
  pointer-events: auto;
  max-width: 360px;
}
:where(html[data-shell="app"]) .toast-item.show {
  opacity: 1;
  transform: translateX(0);
}
/* No colour of its own: the icon inherits from .toast-item, so the state rules
   below carry it. Giving it one is what left the Dashboard with a green line
   beside a grey tick until 4 Sep 2026. */
:where(html[data-shell="app"]) .toast-item .toast-icon {
  flex-shrink: 0;
}
:where(html[data-shell="app"]) .toast-item.success {
  border-color: color-mix(in srgb, var(--success) 40%, transparent);
  color: var(--success);
}
:where(html[data-shell="app"]) .toast-item.error {
  border-color: color-mix(in srgb, var(--error) 40%, transparent);
  color: var(--error);
}
:where(html[data-shell="app"]) .toast-item.warn {
  border-color: color-mix(in srgb, var(--warning) 40%, transparent);
  color: var(--warning);
}
:where(html[data-shell="app"]) [data-theme="light"] .toast-item {
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
}
@media (max-width: 640px) {
  :where(html[data-shell="app"]) .toast-stack {
    top: 14px;
    left: 14px;
    right: 14px;
    bottom: auto;
    align-items: stretch;
  }
  :where(html[data-shell="app"]) .toast-item {
    max-width: none;
    transform: translateY(-10px);
  }
  :where(html[data-shell="app"]) .toast-item.show {
    transform: translateY(0);
  }
}
:where(html[data-shell="app"]) .icon-24 {
  width: 24px;
  height: 24px;
}
:where(html[data-shell="app"]) .sm-wordmark {
  font-family: 'Playfair Display',serif;
  font-weight: 700;
  font-size: 30px;
  color: #DAC7C0;
  line-height: 1;
  padding-left: 8px;
  user-select: none;
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) .app {
  display: flex;
  min-height: 100vh;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .side-menu-toggle:hover {
  color: var(--accent);
  background: var(--hover-bg);
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) .page {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .side-menu-toggle .sm-expand {
  display: none;
}

/* ---------- shared by transfer / settings ---------- */
:where(html[data-page="transfer"], html[data-page="settings"]) .page-inner {
  max-width: 920px;
  margin: 0 auto;
  width: 100%;
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .side-menu-item:hover {
  color: var(--text);
  background: var(--hover-bg);
}
:where(html[data-shell="app"]) .side-menu-item.active {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent);
}
:where(html[data-shell="app"]) .side-menu-logout {
  margin-top: 8px;
  border-top: 1px solid var(--border);
}

/* ---------- shared by settings / login ---------- */
:where(html[data-page="settings"], html[data-page="login"]) .field-input:focus {
  border-color: var(--accent);
}
:where(html[data-page="settings"], html[data-page="login"]) .field-input::placeholder {
  color: var(--text-placeholder);
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .side-menu.collapsed .sm-user {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}
:where(html[data-shell="app"]) .side-menu.collapsed .sm-user-text {
  display: none;
}
:where(html[data-shell="app"]) .side-menu-drawer .sm-avatar {
  width: 36px;
  height: 36px;
  font-size: 13px;
}
:where(html[data-shell="app"]) .side-menu-drawer .sm-user-name {
  font-size: 14px;
}
:where(html[data-shell="app"]) .side-menu-drawer .sm-user-role {
  font-size: 11px;
}
:where(html[data-shell="app"]) .side-menu-item svg {
  flex-shrink: 0;
}
:where(html[data-shell="app"]) .side-menu.collapsed {
  width: 56px;
  padding: 14px 8px;
}
:where(html[data-shell="app"]) .side-menu.collapsed .side-menu-head {
  justify-content: center;
}
:where(html[data-shell="app"]) .side-menu.collapsed .sm-wordmark {
  display: none;
}

/* ---------- shared by all five pages ---------- */
[data-theme="light"] .theme-toggle .tt-sun {
  display: block;
}
[data-theme="light"] .theme-toggle .tt-moon {
  display: none;
}

/* ---------- shared by settings / login ---------- */
:where(html[data-page="settings"], html[data-page="login"]) .pass-toggle.showing .eye {
  display: none;
}
:where(html[data-page="settings"], html[data-page="login"]) .pass-toggle.showing .eye-off {
  display: block;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .side-menu.collapsed .side-menu-toggle .sm-collapse {
  display: none;
}
:where(html[data-shell="app"]) .side-menu.collapsed .side-menu-toggle .sm-expand {
  display: block;
}
:where(html[data-shell="app"]) .side-menu.collapsed .side-menu-item {
  justify-content: center;
  padding: 10px 0;
}
:where(html[data-shell="app"]) .side-menu.collapsed .side-menu-item .smi-label {
  display: none;
}
:where(html[data-shell="app"]) .side-menu-drawer.open {
  display: block;
}
:where(html[data-shell="app"]) .side-menu-drawer .drawer-backdrop {
  position: absolute;
  inset: 0;
  background: var(--overlay);
}
@media (max-width: 640px) {
  :where(html[data-shell="app"]) .side-menu {
    display: none;
  }
  :where(html[data-shell="app"]) .menu-toggle:active {
    background: var(--hover-bg);
  }
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) .header-text h1 {
  font-family: 'Playfair Display',serif;
  font-weight: 600;
  font-size: 21px;
  line-height: 1.3;
  color: var(--text);
}
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) .header-text p {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-top: 2px;
}

/* ---------- shared by dashboard / scanner ---------- */
:where(html[data-page="dashboard"], html[data-page="scanner"]) .btn-icon:active {
  transform: scale(0.94);
}

/* ---------- shared by dashboard / transfer ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"]) .section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* ---------- shared by dashboard / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap thead th {
  background: var(--surface2);
  padding: 10px 12px;
  text-align: left;
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
:where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody tr:last-child {
  border-bottom: none;
}
:where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody tr:hover {
  background: var(--hover-bg);
}
:where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody td {
  padding: 12px;
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  color: var(--text);
  white-space: nowrap;
}

/* ---------- shared by dashboard / scanner / transfer ---------- */
:where(html[data-page="dashboard"], html[data-page="scanner"], html[data-page="transfer"]) .big-btn.danger:hover {
  background: color-mix(in srgb, var(--error) 12%, transparent);
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
@media (min-width: 768px) {
  :where(html[data-shell="app"]) .sheet-overlay {
    align-items: center;
    justify-content: center;
    padding: 24px;
  }
  :where(html[data-shell="app"]) .sheet {
    max-width: 420px;
    border-radius: 20px;
    border: 1px solid var(--border);
  }
}

/* ---------- shared by dashboard / settings ---------- */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin: 10px;
    padding: 4px 14px;
    background: var(--surface);
  }
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody tr:last-child {
    border-bottom: 1px solid var(--border);
  }
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 10px 0;
    border-top: 1px solid var(--border);
    white-space: normal;
    text-align: right;
  }
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody td::before {
    content: attr(data-label);
    font-family: 'DM Sans',sans-serif;
    font-weight: 500;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    text-align: left;
  }
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody td:first-child::before {
    content: '';
  }
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) [data-theme="light"] .card, :where(html[data-page="dashboard"]) [data-theme="light"] .transfer-card {
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
}
:where(html[data-page="dashboard"]) .page-inner {
  max-width: 1080px;
  margin: 0 auto;
  width: 100%;
  flex: 1;
  display: flex;
  flex-direction: column;
}
:where(html[data-page="dashboard"]) .btn-icon.spinning svg {
  animation: spin 0.7s linear infinite;
}
:where(html[data-page="dashboard"], html[data-page="settings"], html[data-page="transfer"]) .tab-count {
  opacity: 0.7;
  margin-left: 4px;
}
:where(html[data-page="dashboard"]) .fb-input::placeholder {
  color: var(--text-placeholder);
}
:where(html[data-page="dashboard"]) .fb-input:focus {
  outline: none;
  border-color: var(--accent);
}
:where(html[data-page="dashboard"]) #mainFilters {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: stretch;
}
:where(html[data-page="dashboard"]) .fb-opt input {
  accent-color: var(--accent);
  width: 14px;
  height: 14px;
  cursor: pointer;
  flex-shrink: 0;
}
:where(html[data-page="dashboard"]) .fb-range label {
  font-size: 10px;
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
}
:where(html[data-page="dashboard"]) .fb-range input {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  padding: 6px 8px;
  width: 100%;
}
:where(html[data-page="dashboard"]) .fb-chip-label b {
  font-weight: 600;
}
:where(html[data-page="dashboard"]) .fb-result b {
  color: var(--accent);
  font-weight: 600;
}
:where(html[data-page="dashboard"]) .fb-dow span {
  text-align: center;
  font-size: 9px;
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
}
:where(html[data-page="dashboard"]) .fb-day.blank {
  visibility: hidden;
  cursor: default;
}
:where(html[data-page="dashboard"]) .fb-day:hover:not(.blank):not(.edge) {
  background: var(--hover-bg);
}
:where(html[data-page="dashboard"]) .fb-day.today {
  border: 1.3px solid var(--accent);
}
@media (max-width: 560px) {
  :where(html[data-page="dashboard"]) .fb-cal {
    flex-direction: column;
  }
  :where(html[data-page="dashboard"]) .fb-cal-shorts {
    width: 100%;
    border-right: none;
    border-bottom: 1px solid var(--border);
    flex-direction: row;
    flex-wrap: wrap;
  }
  :where(html[data-page="dashboard"]) .fb-short {
    flex: 1 1 auto;
    text-align: center;
  }
}
:where(html[data-page="dashboard"]) #doTables {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex-shrink: 0;
}
:where(html[data-page="dashboard"]) .tc-pickers .tc-avatar:first-child {
  margin-left: 0;
}
:where(html[data-page="dashboard"]) .empty-state.error {
  border-style: solid;
  border-color: color-mix(in srgb, var(--error) 20%, transparent);
}
:where(html[data-page="dashboard"]) .grid-wrap table {
  width: 100%;
  border-collapse: collapse;
}
:where(html[data-page="dashboard"]) .grid-wrap tbody tr {
  border-bottom: 1px solid var(--border);
  transition: background var(--duration-fast) ease;
}
:where(html[data-page="dashboard"]) .grid-wrap th.col-num, :where(html[data-page="dashboard"]) .grid-wrap td.col-num {
  text-align: center;
  font-variant-numeric: tabular-nums;
}
@media (min-width: 641px) {
  :where(html[data-page="dashboard"]) .do-body .grid-wrap {
    max-height: calc(100vh - 170px);
    overflow-y: auto;
    flex-shrink: 0;
  }
  :where(html[data-page="dashboard"]) .do-body .grid-wrap thead th {
    position: sticky;
    top: 0;
    z-index: 2;
  }
}
:where(html[data-page="dashboard"]) .select-wrap:hover .sw-chevron {
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .picker-select::-ms-expand {
  display: none;
}
:where(html[data-page="dashboard"]) .picker-select:focus {
  outline: none;
  border-color: var(--accent);
}
:where(html[data-page="dashboard"]) .picker-select:disabled {
  opacity: 0.5;
  cursor: wait;
}
:where(html[data-page="dashboard"]) .select-wrap:has(.picker-select:disabled) .sw-chevron {
  opacity: 0.5;
}
@media (max-width: 640px) {
  :where(html[data-page="dashboard"]) .grid-wrap tbody td:first-child {
    border-top: none;
    font-weight: 700;
    font-size: 14px;
  }
}
:where(html[data-page="dashboard"]) .kebab-btn:active {
  transform: scale(0.94);
}
:where(html[data-page="dashboard"]) .action-btn:hover .ab-icon {
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .action-btn.danger .ab-icon {
  color: var(--error);
}
:where(html[data-page="dashboard"]) .action-btn.danger:hover {
  border-color: var(--error);
  color: var(--error);
  background: color-mix(in srgb, var(--error) 8%, transparent);
}
:where(html[data-page="dashboard"]) .action-btn.danger:hover .ab-icon {
  color: var(--error);
}
:where(html[data-page="dashboard"]) .grid-wrap th.col-act, :where(html[data-page="dashboard"]) .grid-wrap td.col-act {
  width: 44px;
  text-align: center;
}
@media (max-width: 640px) {
  :where(html[data-page="dashboard"]) .db-header {
    padding: 14px 16px;
  }
  :where(html[data-page="dashboard"]) .db-body {
    padding: 16px;
  }
  :where(html[data-page="dashboard"]) .do-header {
    padding: 14px 16px;
  }
  :where(html[data-page="dashboard"]) .do-body {
    padding: 16px 16px 40px;
  }
  :where(html[data-page="dashboard"]) .fb-search {
    max-width: none;
    flex-basis: 100%;
  }
  :where(html[data-page="dashboard"]) .fb-select-wrap {
    flex: 1;
    max-width: none;
  }
  :where(html[data-page="dashboard"]) .do-body .grid-wrap {
    flex-shrink: 0;
  }
  :where(html[data-page="dashboard"]) .btn-icon {
    min-height: 44px;
  }
  :where(html[data-page="dashboard"]) .btn-icon {
    width: 44px;
    height: 44px;
  }
  :where(html[data-page="dashboard"]) .kebab-btn {
    width: 40px;
    height: 40px;
  }
  :where(html[data-page="dashboard"]) .row-del-btn {
    width: 38px;
    height: 38px;
  }
}

/* ---------- page: scanner ---------- */
html:where([data-page="scanner"]) {
  height: 100%;
  overscroll-behavior: none;
}
html:where([data-page="scanner"]) {
  scrollbar-gutter: stable;
}
:where(html[data-page="scanner"]) body {
  height: 100%;
  overscroll-behavior: none;
}
:where(html[data-page="scanner"]) body {
  background: var(--bg);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  line-height: 1.55;
  transition: background var(--duration-base) var(--ease), color var(--duration-base) var(--ease);
}
:where(html[data-page="scanner"]) .app {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
}
:where(html[data-page="scanner"]) .page {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .side-menu {
  width: 200px;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  height: 100vh;
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  transition: width var(--duration-base) var(--ease);
}
:where(html[data-shell="app"]) .side-menu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  min-height: 32px;
}
:where(html[data-shell="app"]) .side-menu-toggle {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  flex-shrink: 0;
  transition: color var(--duration-base) ease, background var(--duration-base) ease;
}
:where(html[data-shell="app"]) .side-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  border-radius: 6px;
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 11px;
  text-decoration: none;
  transition: color var(--duration-base) ease, background var(--duration-base) ease;
  white-space: nowrap;
}
:where(html[data-shell="app"]) .sm-user {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 8px;
  border-radius: 6px;
  min-width: 0;
}
:where(html[data-shell="app"]) .sm-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  color: var(--accent);
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 11px;
  user-select: none;
}
:where(html[data-shell="app"]) .sm-user-text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
:where(html[data-shell="app"]) .sm-user-name {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-shell="app"]) .sm-user-role {
  font-family: 'DM Sans',sans-serif;
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-shell="app"]) .side-menu-drawer {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: none;
}
:where(html[data-shell="app"]) .menu-toggle {
  display: none;
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .db-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  animation: fadeIn var(--duration-slow) var(--ease);
}

/* ---------- page: scanner ---------- */
@media (max-width: 640px) {
  :where(html[data-page="scanner"]) .menu-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    background: transparent;
    border: none;
    color: var(--text);
    cursor: pointer;
    border-radius: var(--radius-sm);
  }
  :where(html[data-page="scanner"]) .sc-header {
    padding: 14px 12px;
    gap: 8px;
  }
  :where(html[data-page="scanner"]) .header-left, :where(html[data-page="scanner"]) .header-actions {
    gap: 8px;
  }
  :where(html[data-page="scanner"]) .logo-mark {
    display: none;
  }
  :where(html[data-page="scanner"]) .header-text h1 {
    font-size: 18px;
  }
  :where(html[data-page="scanner"]) .m-name {
    max-width: 96px;
  }
  :where(html[data-page="scanner"]) .btn-icon {
    width: 44px;
    height: 44px;
  }
}
:where(html[data-page="scanner"]) .theme-toggle {
  position: relative;
  width: 52px;
  height: 28px;
  border-radius: 20px;
  background: var(--surface2);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
}
:where(html[data-page="scanner"]) .screen {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
:where(html[data-page="scanner"]) .center-msg {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 32px;
  text-align: center;
}
:where(html[data-page="scanner"]) .spinner {
  width: 34px;
  height: 34px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
:where(html[data-page="scanner"]) .big-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 16px 30px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  min-height: 52px;
  transition: background var(--duration-base) ease, opacity var(--duration-base) ease;
}
:where(html[data-page="scanner"]) .big-btn:active {
  background: var(--accent-active);
}
:where(html[data-page="scanner"]) .big-btn:disabled {
  opacity: 0.55;
  cursor: wait;
}
:where(html[data-page="scanner"]) .ghost-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  padding: 14px 26px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  min-height: 48px;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}
:where(html[data-page="scanner"]) .ghost-btn:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}

/* ---------- shared by dashboard / scanner ---------- */
:where(html[data-page="dashboard"], html[data-page="scanner"]) .btn-icon:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .btn-secondary:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
:where(html[data-page="dashboard"], html[data-page="settings"], html[data-page="transfer"]) .tab-btn:hover {
  color: var(--text);
}
:where(html[data-page="dashboard"]) .fb-input:hover {
  border-color: var(--accent-hover);
}
:where(html[data-page="dashboard"]) .sort-btn:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .fb-add:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .fb-back:hover {
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .fb-opt:hover {
  background: var(--hover-bg);
}
:where(html[data-page="dashboard"]) .fb-chip-label:hover {
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
:where(html[data-page="dashboard"]) .fb-chip-x:hover {
  color: var(--error);
  opacity: 1;
}
:where(html[data-page="dashboard"]) .fb-short:hover {
  background: var(--hover-bg);
  color: var(--text);
}
:where(html[data-page="dashboard"]) .fb-nav:hover {
  color: var(--accent);
  background: var(--hover-bg);
}
:where(html[data-page="dashboard"]) .fb-clear:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .transfer-card:hover {
  border-color: var(--accent-hover);
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0,0,0,0.16);
}
:where(html[data-page="dashboard"]) .picker-select:hover {
  border-color: var(--accent-hover);
}
:where(html[data-page="dashboard"]) .ghost-btn:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}

/* ---------- page: scanner ---------- */
:where(html[data-page="scanner"]) .ghost-btn:disabled {
  opacity: 0.55;
  cursor: wait;
}
:where(html[data-page="scanner"]) .tp-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  max-width: 340px;
}
/* [Item 9 · F2b] 🔴 `color` IS NOT OPTIONAL HERE AND ITS ABSENCE WAS A LIVE
   DEFECT, not a style preference. .tp-chip is a <button>, and a button does
   NOT inherit color — the UA gives it `buttontext`, which is black. 🔬 Measured
   against the real tokens: the picker's name rendered at a contrast ratio of
   1.23:1 on the dark chip — black on rgb(26,26,46), effectively invisible —
   and 21:1 in light, which is why it survived since V25: anyone who looked at
   the supervisor's picker list was in the light theme. With the token it is
   14.59:1 dark and 17.4:1 light.
   ⚠️ .tp-count keeps its own --text-muted and is unaffected (5.54:1).
   ⚠️ The chip background is deliberately NOT changed to --surface2 for the
   chooser sheet: 🔬 surface2 against surface is 1.07:1 in dark and 1.11:1 in
   light, so it would separate nothing. The border already does that work. */
:where(html[data-page="scanner"]) .tp-chip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  cursor: pointer;
  transition: border-color var(--duration-fast) ease;
}
:where(html[data-page="scanner"]) .tp-chip:active {
  border-color: var(--accent);
}
:where(html[data-page="scanner"]) .tp-id {
  font-family: 'DM Sans',sans-serif;
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="scanner"]) .tp-count {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 4px 10px;
  border-radius: 20px;
  color: var(--text-muted);
  background: var(--disabled-bg);
  border: 1px solid var(--disabled-border);
}
:where(html[data-page="scanner"]) .tp-status {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 4px 10px;
  border-radius: 20px;
}
:where(html[data-page="scanner"]) .sc-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  flex-shrink: 0;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .logo-mark {
  border: 1px solid var(--border);
  border-radius: 8px;
  flex-shrink: 0;
  transition: border-color var(--duration-base) ease;
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .theme-toggle {
  position: relative;
  width: 52px;
  height: 28px;
  border-radius: 20px;
  background: var(--surface2);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
}

/* ---------- page: scanner ---------- */
:where(html[data-page="scanner"]) .header-left {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
:where(html[data-page="scanner"]) .header-text {
  min-width: 0;
}
:where(html[data-page="scanner"]) .header-text h1 {
  font-family: 'Playfair Display',serif;
  font-weight: 600;
  font-size: 21px;
  line-height: 1.3;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="scanner"]) .header-text p {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="scanner"]) .header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
:where(html[data-page="scanner"]) .m-name {
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 11px;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex-shrink: 1;
}
:where(html[data-page="scanner"]) .save-mini:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="scanner"]) .save-mini:disabled {
  opacity: 0.5;
  cursor: wait;
}
:where(html[data-page="scanner"]) .sku-row:last-child {
  border-bottom: none;
}
:where(html[data-page="scanner"]) .drag-handle:active {
  cursor: grabbing;
  color: var(--accent);
}
:where(html[data-page="scanner"]) .sku-row.partial .sku-dot {
  border-color: var(--warning);
  background: color-mix(in srgb, var(--warning) 45%, transparent);
}
:where(html[data-page="scanner"]) .sku-row.done .sku-dot {
  border-color: var(--success);
  background: var(--success);
}
:where(html[data-page="scanner"]) .sku-row.done .sku-fill {
  background: var(--success);
}
:where(html[data-page="scanner"]) .sku-count:active {
  background: var(--hover-bg);
  border-color: var(--text-muted);
}
:where(html[data-page="scanner"]) .sku-row.done .sku-count {
  color: var(--success);
}
:where(html[data-page="scanner"]) .sku-row.notfound .sku-count {
  color: var(--error);
}
:where(html[data-page="scanner"]) .sku-row.notfound .sku-dot {
  border-color: var(--error);
  background: color-mix(in srgb, var(--error) 55%, transparent);
}
:where(html[data-page="scanner"]) .sku-row.notfound .sku-code {
  color: var(--text-muted);
  text-decoration: line-through;
}
@media (min-width: 641px) {
  :where(html[data-page="scanner"]) .side-menu ~ .page .scan-bar {
    left: 200px;
  }
  :where(html[data-page="scanner"]) .side-menu.collapsed ~ .page .scan-bar {
    left: 56px;
  }
}
:where(html[data-page="scanner"]) .scan-btn:active {
  background: var(--accent-active);
}
:where(html[data-page="scanner"]) .manual-link:disabled {
  opacity: 0.5;
  cursor: wait;
}
:where(html[data-page="scanner"]) .pc-scan-input::placeholder {
  color: var(--text-placeholder);
}
@media (min-width: 768px) {
  :where(html[data-page="scanner"]) .scan-btn, :where(html[data-page="scanner"]) #manualEntryBtn {
    display: none;
  }
  :where(html[data-page="scanner"]) .pc-scan-dock {
    display: block;
  }
}
:where(html[data-page="scanner"]) .cam-toggle.active .ct-dot {
  background: #4ade80;
  box-shadow: 0 0 7px #4ade80;
}
:where(html[data-page="scanner"]) .cam-toggle:active {
  transform: scale(0.96);
}
:where(html[data-page="scanner"]) #camReader {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
:where(html[data-page="scanner"]) #camReader video {
  object-fit: cover;
}
:where(html[data-page="scanner"]) .manual-entry-bar input {
  flex: 1;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.15);
  color: #f0ede6;
  padding: 14px 16px;
  border-radius: 10px;
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  outline: none;
}
:where(html[data-page="scanner"]) .manual-entry-bar input::placeholder {
  color: rgba(240,237,230,0.4);
}
:where(html[data-page="scanner"]) .manual-entry-bar input:focus {
  border-color: var(--accent);
}
:where(html[data-page="scanner"]) .manual-entry-bar button {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 0 20px;
  border-radius: 10px;
  font-family: 'DM Sans',sans-serif;
  font-weight: 700;
  cursor: pointer;
}
:where(html[data-page="scanner"]) .undo-step:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="scanner"]) .undo-qty-input:focus {
  outline: none;
  border-color: var(--accent);
}
:where(html[data-page="scanner"]) .sheet-input::placeholder {
  color: var(--text-placeholder);
}
:where(html[data-page="scanner"]) .sheet-input:focus {
  border-color: var(--accent);
}

/* ---------- page: transfer ---------- */
:where(html[data-page="transfer"]) [data-theme="light"] .summary-card {
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) [data-theme="light"] .grid-wrap {
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
}

/* ---------- page: transfer ---------- */
:where(html[data-page="transfer"]) [data-theme="light"] .odoo-import-wrap, :where(html[data-page="transfer"]) [data-theme="light"] .details-wrap {
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
}
:where(html[data-page="transfer"]) .nt-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  animation: fadeIn var(--duration-slow) var(--ease);
}
:where(html[data-page="transfer"]) .nt-badge {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 11px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  padding: 5px 12px;
  border-radius: 20px;
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="transfer"]) .theme-toggle {
  position: relative;
  width: 52px;
  height: 28px;
  border-radius: 20px;
  background: var(--surface2);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
}
.ms-wrap {
  position: relative;
}
.ms-trigger:disabled {
  opacity: 0.55;
  cursor: wait;
}
.ms-wrap.open .ms-trigger {
  border-color: var(--accent);
}
.ms-wrap.open .select-chevron {
  transform: translateY(-50%) rotate(180deg);
}
.ms-wrap.open .ms-panel {
  display: block;
}
.ms-option:hover {
  background: var(--hover-bg);
}
.ms-option input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.ms-box svg {
  width: 11px;
  height: 11px;
  opacity: 0;
  transform: scale(0.6);
  transition: opacity var(--duration-fast) ease, transform var(--duration-fast) ease;
}
.ms-option.checked .ms-box {
  background: var(--accent);
  border-color: var(--accent);
}
.ms-option.checked .ms-box svg {
  opacity: 1;
  transform: scale(1);
}
:where(html[data-page="transfer"]) .field-select:focus {
  border-color: var(--accent);
}
:where(html[data-page="transfer"]) .field-select:disabled {
  opacity: 0.55;
  cursor: wait;
}
:where(html[data-page="transfer"]) .field-select option {
  background: var(--surface);
  color: var(--text);
}
:where(html[data-page="transfer"]) .odoo-input::placeholder {
  color: var(--text-placeholder);
}
:where(html[data-page="transfer"]) .odoo-input:focus {
  border-color: var(--accent);
}
:where(html[data-page="transfer"]) .odoo-import-btn:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
:where(html[data-page="transfer"]) .odoo-import-btn:disabled {
  opacity: 0.55;
  cursor: wait;
}
:where(html[data-page="transfer"]) table {
  width: 100%;
  border-collapse: collapse;
}
:where(html[data-page="transfer"]) thead th {
  background: var(--surface2);
  padding: 10px 12px;
  text-align: left;
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) thead th.col-qty {
  width: 140px;
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) thead th.col-del {
  width: 44px;
}
/* [specs/006] ADD SKU, ON THE DETAIL TABLE.
   A split button at the right-hand end of the filter bar: the main half opens a
   draft row, the caret opens the file import. Built from .fb-add, the bar's own
   button, rather than invented beside it - the two halves differ only in the
   corners they round, so they read as one control. */
:where(html[data-page="dashboard"]) .add-sku-anchor {
  margin-left: auto;
}
:where(html[data-page="dashboard"]) .split-btn {
  display: inline-flex;
  align-items: stretch;
}
:where(html[data-page="dashboard"]) .split-btn .add-sku-btn {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
:where(html[data-page="dashboard"]) .split-btn .add-sku-caret {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-left: none;
  padding-left: 8px;
  padding-right: 8px;
}
/* The menu hangs UNDER the button and is aligned to its right edge, so it opens
   into the page rather than off it: the button sits at the far right of the bar
   (Mustafa, 2026-09-16 - it was drifting out to the right and reading as a
   stray box). Its width is the item's, not the anchor's. */
/* `.fb-pop.add-sku-menu`, not `.add-sku-menu`: the base .fb-pop is written
   further down this file and would otherwise win on source order and drag the
   menu back to left: 0 (Mustafa, 2026-09-16 - it kept opening rightward). */
:where(html[data-page="dashboard"]) .fb-pop.add-sku-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  left: auto;
  /* .fb-pop is 260px wide and anchored left, which on a button at the far right
     of the bar pushed the menu past the edge of the page and raised a sideways
     scrollbar (Mustafa, 2026-09-16). One item, so it takes the item's width and
     hangs from the button's right edge. */
  width: max-content;
  min-width: 0;
  max-width: min(260px, calc(100vw - 48px));
  z-index: 60;
  text-align: left;
}

/* The draft row is the one row in the table nobody has stored yet, and it says
   so quietly: the page's own accent tint, and cells that look like the stored
   cells above them rather than like a form. */
:where(html[data-page="dashboard"]) .add-draft-row {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
/* [Mustafa, 2026-09-16] EACH CELL IS THE WIDTH OF ITS OWN COLUMN, not the width
   of the table cell it sits in: a full-width input left the number hard against
   the left edge while every stored number below it was centred, and the picker's
   own chevron ended up beside the + button two columns away. So each input is
   sized and aligned like the column it belongs to. */
:where(html[data-page="dashboard"]) .add-draft-row .cell-input {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  padding: 7px 9px;
  outline: none;
}
:where(html[data-page="dashboard"]) .add-draft-row .cell-input:focus {
  border-color: var(--accent);
}
/* Centred, because every stored number in this column is centred by
   .grid-wrap td.col-num and a right-aligned draft did not line up with the
   column it was joining (Mustafa, 2026-09-16). */
:where(html[data-page="dashboard"]) .add-draft-row td.col-num .cell-input {
  text-align: center;
  font-variant-numeric: tabular-nums;
}
/* The picker column holds a name, so its select is only as wide as it needs to
   be - and its chevron then sits beside the name instead of a column away. */
:where(html[data-page="dashboard"]) .add-draft-row select.cell-input {
  width: auto;
  max-width: 100%;
  min-width: 120px;
}
/* The two row controls sit in the delete column, in the order they are read:
   commit, then abandon. Same size as the trash they replace. */
:where(html[data-page="dashboard"]) .add-draft-row td.col-act {
  white-space: nowrap;
}
:where(html[data-page="dashboard"]) .row-add-btn,
:where(html[data-page="dashboard"]) .row-cancel-btn {
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 4px;
  line-height: 0;
}
:where(html[data-page="dashboard"]) .row-add-btn {
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .row-cancel-btn {
  color: var(--text-muted);
}
:where(html[data-page="dashboard"]) .row-add-btn:hover,
:where(html[data-page="dashboard"]) .row-cancel-btn:hover {
  color: var(--text);
}

:where(html[data-page="transfer"]) tbody tr {
  border-bottom: 1px solid var(--border);
}
:where(html[data-page="transfer"]) tbody tr:last-child {
  border-bottom: none;
}
:where(html[data-page="transfer"]) tbody tr:hover {
  background: var(--hover-bg);
}
/* [Item 36] A line whose duplicate was merged away and whose quantity is now
   owed. --error rather than a new colour: rule 2 of the non-negotiables keeps
   meaning in the semantic tokens, and --error is redefined per theme so the
   same declaration reads correctly in both. Mixed toward transparent so the
   cell text keeps its own contrast instead of fighting a solid fill.
   The :hover pair below is not optional - it carries identical specificity to
   the rule above it, so without it hovering the row would clear the paint. */
:where(html[data-page="transfer"]) tbody tr.row-needs-qty {
  background: color-mix(in srgb, var(--error) 14%, transparent);
}
:where(html[data-page="transfer"]) tbody tr.row-needs-qty:hover {
  background: color-mix(in srgb, var(--error) 22%, transparent);
}
:where(html[data-page="transfer"]) tbody td {
  padding: 0;
  border-right: 1px solid var(--border);
}
:where(html[data-page="transfer"]) tbody td:last-child {
  border-right: none;
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .cell-input:focus {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .cell-input::placeholder {
  color: var(--text-placeholder);
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .del-row-btn:hover {
  color: var(--error);
  background: color-mix(in srgb, var(--error) 10%, transparent);
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .add-row-btn:hover, :where(html[data-page="transfer"], html[data-page="dashboard"]) .excel-btn:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .excel-btn:disabled {
  opacity: 0.55;
  cursor: wait;
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .excel-btn svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}
:where(html[data-page="transfer"]) .create-btn:hover {
  background: var(--accent-hover);
}

/* ---------- shared by dashboard / scanner / transfer ---------- */
:where(html[data-page="dashboard"], html[data-page="scanner"], html[data-page="transfer"]) .big-btn:hover {
  background: var(--accent-hover);
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .kebab-btn:hover {
  border-color: var(--border);
  color: var(--accent);
  background: var(--hover-bg);
}
:where(html[data-page="dashboard"]) .action-btn:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .row-del-btn:hover {
  color: var(--error);
  border-color: color-mix(in srgb, var(--error) 30%, transparent);
}

/* ---------- page: transfer ---------- */
:where(html[data-page="transfer"]) .create-btn:active {
  background: var(--accent-active);
}
:where(html[data-page="transfer"]) .create-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
:where(html[data-page="transfer"]) .ghost-btn:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
@media (max-width: 640px) {
  :where(html[data-page="transfer"]) .menu-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    background: transparent;
    border: none;
    color: var(--text);
    cursor: pointer;
    border-radius: var(--radius-sm);
  }
  :where(html[data-page="transfer"]) .nt-header {
    padding: 14px 16px;
  }
  :where(html[data-page="transfer"]) .nt-body {
    padding: 20px 16px 100px;
  }
  :where(html[data-page="transfer"]) .submit-bar {
    padding: 16px;
  }
  :where(html[data-page="transfer"]) .create-btn {
    width: 100%;
  }
  :where(html[data-page="transfer"]) .summary-bar, :where(html[data-page="transfer"]) .details-wrap {
    flex-direction: column;
  }
  :where(html[data-page="transfer"], html[data-page="dashboard"]) .grid-footer {
    flex-direction: column;
    gap: 8px;
    align-items: stretch;
  }
  :where(html[data-page="transfer"], html[data-page="dashboard"]) .grid-footer .add-row-btn, :where(html[data-page="transfer"], html[data-page="dashboard"]) .grid-footer .excel-btn {
    width: 100%;
    justify-content: center;
  }
  :where(html[data-page="transfer"]) .odoo-import-wrap {
    flex-direction: column;
  }
  :where(html[data-page="transfer"]) .odoo-import-btn {
    justify-content: center;
  }
  :where(html[data-page="transfer"]) thead {
    display: none;
  }
  :where(html[data-page="transfer"]) table, :where(html[data-page="transfer"]) tbody {
    display: block;
    width: 100%;
  }
  :where(html[data-page="transfer"]) tbody tr {
    display: block;
    width: 100%;
  }
  :where(html[data-page="transfer"]) tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin: 10px;
    padding: 6px 14px 10px;
    background: var(--surface);
  }
  :where(html[data-page="transfer"]) tbody td {
    display: block;
    width: 100%;
  }
  :where(html[data-page="transfer"]) tbody td {
    border-right: none;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 0;
    border-top: 1px solid var(--border);
  }
  :where(html[data-page="transfer"]) tbody tr:last-child {
    border-bottom: 1px solid var(--border);
  }
  :where(html[data-page="transfer"]) tbody td:first-child {
    border-top: none;
  }
  :where(html[data-page="transfer"]) tbody td::before {
    content: attr(data-label);
    flex-shrink: 0;
    width: 52px;
    font-family: 'DM Sans',sans-serif;
    font-weight: 500;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
  }
  :where(html[data-page="transfer"]) tbody td:last-child::before {
    content: '';
    width: auto;
  }
  :where(html[data-page="transfer"], html[data-page="dashboard"]) .cell-input {
    background: var(--surface2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
  }
  :where(html[data-page="transfer"], html[data-page="dashboard"]) .del-row-btn {
    width: auto;
    margin-left: auto;
    padding: 8px 14px;
  }
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) [data-theme="light"] .confirm-box {
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .side-menu-drawer .drawer-panel {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 65%;
  max-width: 280px;
  background: var(--surface2);
  box-shadow: 6px 0 20px rgba(0,0,0,0.4);
  padding: 20px 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
:where(html[data-shell="app"]) .side-menu-drawer .side-menu-item {
  font-size: 13px;
  padding: 12px 10px;
  min-height: 44px;
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .st-header {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  animation: fadeIn var(--duration-slow) var(--ease);
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) .header-left, :where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) .header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* ---------- shared by dashboard / scanner ---------- */
:where(html[data-page="dashboard"], html[data-page="scanner"]) .btn-icon {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease, transform var(--duration-fast) var(--ease);
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .btn-secondary {
  height: 40px;
  padding: 0 18px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 13px;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  color: var(--accent);
  transition: border-color var(--duration-base) ease, background var(--duration-base) ease;
}
/* Style Guide 5 - .btn-danger. Defined in the guide since it was written and
   implemented here for the first time by Item 11a. Same box as .btn-secondary
   on this page so the two sit level in the Action Bar; only the colour differs,
   and it is --error rather than --accent because the meaning is semantic, not
   brand (Style Guide 19). */
:where(html[data-page="dashboard"]) .btn-danger {
  height: 40px;
  padding: 0 18px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 13px;
  border: 1px solid color-mix(in srgb, var(--error) 30%, transparent);
  background: color-mix(in srgb, var(--error) 6%, transparent);
  color: var(--error);
  transition: border-color var(--duration-base) ease, background var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .btn-danger:hover {
  border-color: color-mix(in srgb, var(--error) 50%, transparent);
  background: color-mix(in srgb, var(--error) 12%, transparent);
}
:where(html[data-page="dashboard"]) .db-body {
  flex: 1;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
:where(html[data-page="dashboard"], html[data-page="settings"], html[data-page="transfer"]) .tabs {
  display: flex;
  gap: 18px;
  border-bottom: 1px solid var(--border);
}
:where(html[data-page="dashboard"], html[data-page="settings"], html[data-page="transfer"]) .tab-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 13px;
  padding-bottom: 12px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--duration-base) ease, border-color var(--duration-base) ease;
  min-height: 44px;
  display: flex;
  align-items: center;
}
:where(html[data-page="dashboard"]) .filter-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
:where(html[data-page="dashboard"]) .fb-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1;
  min-width: 190px;
  max-width: 320px;
}
:where(html[data-page="dashboard"]) .fb-search-icon {
  position: absolute;
  left: 10px;
  display: flex;
  pointer-events: none;
  color: var(--text-muted);
}
:where(html[data-page="dashboard"]) .fb-input {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  padding: 6px 10px 6px 32px;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .fb-select-wrap {
  max-width: 170px;
}
:where(html[data-page="dashboard"]) .fb-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
:where(html[data-page="dashboard"]) .fb-anchor {
  position: relative;
  display: inline-flex;
}
/* [Item 31] The sort control. It replaced a <select>, and it deliberately keeps
   that control's surface, border and height so the filter row does not change
   shape - only its behaviour did. Style Guide 5: small = 32px, dense desktop. */
:where(html[data-page="dashboard"]) .sort-btn {
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 11px;
  padding: 7px 12px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  max-width: 200px;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .sort-btn-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The arrow is the control's whole answer to "which way", so it is the one part
   that carries the accent - and tabular-nums keeps it from nudging the label
   sideways as it swaps between the two glyphs. */
:where(html[data-page="dashboard"]) .sort-btn-arrow {
  color: var(--accent);
  font-size: 13px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="dashboard"]) .sort-pop {
  width: min(220px, calc(100vw - 48px));
}
:where(html[data-page="dashboard"]) .sort-opt.is-active {
  color: var(--accent);
  font-weight: 600;
}
:where(html[data-page="dashboard"]) .sort-opt-arrow {
  color: var(--accent);
  font-size: 13px;
  line-height: 1;
  min-width: 10px;
  text-align: right;
}

:where(html[data-page="dashboard"]) .fb-add {
  background: transparent;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 11px;
  padding: 7px 12px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}
/* A popover is positioned against `.fb-anchor`, which wraps a single BUTTON. On
   a phone that button sits far enough to the right that a 260px panel starts
   inside the screen and ends outside it - `width: min(260px, 100vw - 48px)`
   caps how WIDE the panel gets and says nothing about where it starts, so the
   list ran off the edge and had to be scrolled sideways to be read.

   Below 640px the anchor goes `static`, which hands the popover to the BAR as
   its containing block; left:0 and right:0 then span the bar exactly. It is
   done this way rather than by right-aligning the panel because right-aligning
   only moves the problem to whichever button sits nearest the other edge - this
   holds for every button in the bar, including ones added later.

   Both bars are covered: the transfer list uses `.fb-row` and the detail sheet
   uses `.filter-bar`. They are two different class names for the same row, and
   fixing only the one in the screenshot would have left the other broken. */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"]) .fb-row,
  :where(html[data-page="dashboard"]) .filter-bar {
    position: relative;
  }
  :where(html[data-page="dashboard"]) .fb-anchor {
    position: static;
  }
  :where(html[data-page="dashboard"]) .fb-pop,
  :where(html[data-page="dashboard"]) .fb-pop.is-cal {
    left: 0;
    right: 0;
    width: auto;
  }
}
:where(html[data-page="dashboard"]) .fb-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 60;
  width: min(260px, calc(100vw - 48px));
  max-height: 320px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 10px 28px rgba(0,0,0,0.18);
  padding: 6px;
}
:where(html[data-page="dashboard"]) .fb-pop-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px 8px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}
:where(html[data-page="dashboard"]) .fb-back {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px 4px;
  font-size: 15px;
  line-height: 1;
  border-radius: 4px;
}
:where(html[data-page="dashboard"]) .fb-pop-title {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 12px;
  color: var(--text);
}
:where(html[data-page="dashboard"]) .fb-opt {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  background: none;
  border: none;
  padding: 9px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text);
  min-height: 36px;
}
:where(html[data-page="dashboard"]) .fb-opt-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
:where(html[data-page="dashboard"]) .fb-opt-chevron {
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1;
}
:where(html[data-page="dashboard"]) .fb-empty {
  padding: 12px 8px;
  font-size: 11px;
  color: var(--text-muted);
  text-align: center;
}
:where(html[data-page="dashboard"]) .fb-range {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;
}
:where(html[data-page="dashboard"]) .fb-chips {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
:where(html[data-page="dashboard"]) .fb-chip {
  display: inline-flex;
  align-items: center;
  gap: 0;
  min-height: 30px;
  overflow: hidden;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid var(--accent);
  border-radius: 20px;
}
:where(html[data-page="dashboard"]) .fb-chip-label {
  background: none;
  border: none;
  color: var(--accent);
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  padding: 6px 4px 6px 12px;
  cursor: pointer;
  max-width: 230px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
:where(html[data-page="dashboard"]) .fb-chip-x {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  opacity: 0.75;
  padding: 6px 10px 6px 6px;
  font-size: 13px;
  line-height: 1;
}
:where(html[data-page="dashboard"]) .fb-result {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--text-muted);
}
:where(html[data-page="dashboard"]) .fb-opt-val {
  color: var(--accent);
  font-size: 11px;
  flex-shrink: 0;
  max-width: 110px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The SKU count beside each value in the detail filter popover.
   --text-muted and NOT --accent: a count is data, and the accent carries brand
   and emphasis only. 11px and the same token as .fb-result, which is the other
   count already on this screen, so the two read as one idea.
   tabular-nums keeps 9 and 11 the same width, so the numbers cannot nudge the
   labels sideways as filters change. .fb-opt-name holds flex:1, so the count
   needs no layout of its own - it lands at the right edge on its own. */
:where(html[data-page="dashboard"]) .fb-opt-count {
  color: var(--text-muted);
  font-size: 11px;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="dashboard"]) .fb-cal {
  display: flex;
  align-items: stretch;
}
:where(html[data-page="dashboard"]) .fb-cal-shorts {
  width: 130px;
  flex-shrink: 0;
  border-right: 1px solid var(--border);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
:where(html[data-page="dashboard"]) .fb-short {
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  font-family: 'DM Sans',sans-serif;
  font-size: 10.5px;
  color: var(--text-muted);
  padding: 8px 12px;
  border-radius: 6px;
  min-height: 32px;
  transition: background var(--duration-fast) ease, color var(--duration-fast) ease;
}
:where(html[data-page="dashboard"]) .fb-cal-grid {
  flex: 1;
  min-width: 0;
  padding: 10px 12px 12px;
}
:where(html[data-page="dashboard"]) .fb-cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
:where(html[data-page="dashboard"]) .fb-cal-title {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="dashboard"]) .fb-nav {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  padding: 4px 8px;
  font-size: 14px;
  line-height: 1;
  border-radius: 6px;
}
:where(html[data-page="dashboard"]) .fb-dow {
  display: grid;
  grid-template-columns: repeat(7,1fr);
  gap: 2px;
}
:where(html[data-page="dashboard"]) .fb-dow {
  margin-bottom: 4px;
}
:where(html[data-page="dashboard"]) .fb-days {
  display: grid;
  grid-template-columns: repeat(7,1fr);
  gap: 2px;
}
:where(html[data-page="dashboard"]) .fb-day {
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  border-radius: 50%;
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--text);
}
:where(html[data-page="dashboard"]) .fb-cal-foot {
  padding: 8px 12px;
  border-top: 1px solid var(--border);
  font-family: 'DM Sans',sans-serif;
  font-size: 10px;
  color: var(--text-muted);
}
:where(html[data-page="dashboard"]) .fb-clear {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 11px;
  padding: 7px 12px;
  cursor: pointer;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .do-filter-bar {
  flex-shrink: 0;
  margin-bottom: 4px;
}
:where(html[data-page="dashboard"]) .cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
  animation: fadeIn var(--duration-slow) var(--ease);
}
:where(html[data-page="dashboard"]) .transfer-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  cursor: pointer;
  transition: transform var(--duration-base) var(--ease), border-color var(--duration-base) ease, box-shadow var(--duration-base) ease;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
:where(html[data-page="dashboard"]) .tc-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
:where(html[data-page="dashboard"]) .tc-id {
  font-family: 'DM Sans',sans-serif;
  font-weight: 700;
  font-size: 18px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  /* The safety net, not the mechanism. shortTransferId() in common.js is what
     makes every id of today fit at 18px; these two lines decide what a LONGER
     name invented in future does instead - it gets cut with an ellipsis rather
     than painted on top of the status pill, which is what used to happen and
     was invisible until somebody looked at a narrow card. */
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="dashboard"]) .status-pill {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 5px 12px;
  border-radius: 20px;
  flex-shrink: 0;
}
:where(html[data-page="dashboard"]) .tc-progress-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
:where(html[data-page="dashboard"]) .tc-progress-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px 14px;
  flex-wrap: wrap;
}
:where(html[data-page="dashboard"]) .tc-stat {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}
:where(html[data-page="dashboard"]) .tc-progress-label {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
}
:where(html[data-page="dashboard"]) .tc-progress-value {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text);
}
/* [Item 16 follow-up] The bar and its percentage share one row. The number is
   what makes two cards comparable exactly - `12 / 40` against `7 / 25` is a sum
   somebody has to do in their head, and the bar answers it only roughly.
   tabular-nums so the digits do not change width from card to card and move the
   end of every bar with them. */
:where(html[data-page="dashboard"]) .tc-progress-bar {
  display: flex;
  align-items: center;
  gap: 10px;
}
:where(html[data-page="dashboard"]) .tc-progress-bar .tc-progress-track {
  flex: 1;
  min-width: 0;
}
:where(html[data-page="dashboard"]) .tc-progress-pct {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  min-width: 32px;
  text-align: right;
  flex-shrink: 0;
}
:where(html[data-page="dashboard"]) .tc-progress-track {
  height: 6px;
  background: var(--surface2);
  border-radius: 4px;
  overflow: hidden;
}
:where(html[data-page="dashboard"]) .tc-progress-fill {
  height: 100%;
  background: linear-gradient(90deg,var(--accent-hover),var(--accent));
  border-radius: 4px;
  transition: width var(--duration-slow) var(--ease);
}
/* [Mustafa] THE DATE SITS AT THE FOOT OF EVERY CARD, NOT UNDER WHATEVER
   HAPPENS TO BE ABOVE IT. The grid stretches every card in a row to the
   tallest, but nothing inside a .transfer-card grows, so a card with less in
   it just stops early and its date rides 14px high. An open room is exactly
   that card: 768 leaves the progress bar OFF it, and the bar plus its gap is
   those 14px. margin-top:auto eats the slack wherever the slack comes from -
   this cause and any future one - instead of reserving a bar-shaped hole that
   only ever fixes the one case somebody noticed. */
:where(html[data-page="dashboard"]) .tc-meta-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: auto;
}
:where(html[data-page="dashboard"]) .tc-pickers {
  display: flex;
  align-items: center;
}
:where(html[data-page="dashboard"]) .tc-avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--surface2);
  border: 2px solid var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'DM Sans',sans-serif;
  font-size: 9px;
  font-weight: 600;
  color: var(--text-muted);
  margin-left: -8px;
}
/* [Item 16] Up to three things sit here now - the Odoo reference, the Shopify
   number and the date - so the spacing became a gap. It used to be a literal
   &nbsp; in the markup, which can only ever separate two, and which leaves a
   stray space behind when the chip it followed is not rendered. */
:where(html[data-page="dashboard"]) .tc-date {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* The longest reference in the data is MOUNT/INT/00042 (15 chars). With a
     Shopify chip and a full date beside it, a narrow card can run out of room,
     and `white-space: nowrap` above would push the date outside the card. The
     items wrap to a second line instead - each one still unbroken, because the
     nowrap applies to their text, not to this row. Costs nothing on a card
     that fits. */
  flex-wrap: wrap;
  justify-content: flex-end;
}
:where(html[data-page="dashboard"]) .empty-state {
  grid-column: 1/-1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 48px 20px;
  text-align: center;
  border-radius: var(--radius);
  border: 1px dashed var(--border);
}
:where(html[data-page="dashboard"]) .empty-icon {
  color: var(--text-muted);
  opacity: 0.4;
}
:where(html[data-page="dashboard"]) .empty-icon-badge {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--error) 10%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--error);
}
:where(html[data-page="dashboard"]) .empty-title {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}
:where(html[data-page="dashboard"]) .empty-sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
}
:where(html[data-page="dashboard"]) .skeleton-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
:where(html[data-page="dashboard"]) .skeleton-line {
  height: 12px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  animation: pulse 1.4s ease-in-out infinite;
}
:where(html[data-page="dashboard"]) .detail-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 100;
  display: none;
  flex-direction: column;
}
:where(html[data-page="dashboard"]) .do-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  flex-shrink: 0;
}
:where(html[data-page="dashboard"]) .do-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px 24px 48px;
  max-width: 1440px;
  margin: 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
:where(html[data-page="dashboard"]) .do-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 60px 20px;
}
:where(html[data-page="dashboard"]) .spinner {
  width: 30px;
  height: 30px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}
:where(html[data-page="dashboard"]) .status-label {
  font-weight: 600;
}

/* ---------- page: scanner ---------- */
:where(html[data-page="scanner"]) .m-progress-wrap {
  padding: 14px 18px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
:where(html[data-page="scanner"]) .m-progress-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}
:where(html[data-page="scanner"]) .m-progress-right {
  display: flex;
  align-items: center;
  gap: 12px;
}
:where(html[data-page="scanner"]) .save-mini {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 11px;
  padding: 6px 14px;
  border-radius: 7px;
  cursor: pointer;
  min-height: 32px;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}
:where(html[data-page="scanner"]) .m-progress-label {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
}
:where(html[data-page="scanner"]) .m-progress-count {
  font-family: 'DM Sans',sans-serif;
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="scanner"]) .m-progress-nums {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.15;
}
:where(html[data-page="scanner"]) .m-progress-unit {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
:where(html[data-page="scanner"]) .m-progress-pcs {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  margin-top: 1px;
}
:where(html[data-page="scanner"]) .m-progress-track {
  height: 8px;
  background: var(--surface2);
  border-radius: 5px;
  overflow: hidden;
}
:where(html[data-page="scanner"]) .m-progress-fill {
  height: 100%;
  background: linear-gradient(90deg,var(--accent-hover),var(--accent));
  border-radius: 5px;
  transition: width 0.4s ease;
}
:where(html[data-page="scanner"]) .m-list {
  flex: 1;
  overflow-y: auto;
  padding: 12px 14px 140px;
}
:where(html[data-page="scanner"]) .sku-list-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}
:where(html[data-page="scanner"]) .sku-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  transition: background var(--duration-fast) ease;
  touch-action: pan-y;
}
:where(html[data-page="scanner"]) .drag-handle {
  flex-shrink: 0;
  color: var(--text-muted);
  font-size: 17px;
  line-height: 1;
  padding: 6px 4px;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
:where(html[data-page="scanner"]) .sku-dot {
  flex-shrink: 0;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 2px solid var(--text-muted);
  background: transparent;
}
:where(html[data-page="scanner"]) .sku-info {
  flex: 1;
  min-width: 0;
}
:where(html[data-page="scanner"]) .sku-code {
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 14px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.02em;
}
:where(html[data-page="scanner"]) .sku-track {
  height: 5px;
  background: var(--surface2);
  border-radius: 4px;
  overflow: hidden;
  margin-top: 8px;
}
:where(html[data-page="scanner"]) .sku-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 4px;
  transition: width var(--duration-slow) ease;
}
:where(html[data-page="scanner"]) .sku-count {
  font-family: 'DM Sans',sans-serif;
  font-size: 16px;
  font-weight: 700;
  color: var(--text-muted);
  flex-shrink: 0;
  min-width: 56px;
  min-height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background var(--duration-fast) ease, border-color var(--duration-fast) ease;
}
:where(html[data-page="scanner"]) .nf-tag {
  display: inline-block;
  margin-top: 6px;
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--error);
}
:where(html[data-page="scanner"]) .nf-badge {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--error) 10%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--error);
}
:where(html[data-page="scanner"]) .scan-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 14px 18px 22px;
  background: linear-gradient(to top, var(--bg) 65%, transparent);
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
}
:where(html[data-page="scanner"]) .scan-btn {
  width: 100%;
  max-width: 420px;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 19px;
  border-radius: 16px;
  font-family: 'DM Sans',sans-serif;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  box-shadow: 0 6px 24px color-mix(in srgb, var(--accent) 30%, transparent);
  transition: background var(--duration-base) ease;
}
:where(html[data-page="scanner"]) .manual-link {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
  padding: 6px;
}
:where(html[data-page="scanner"]) .pc-scan-dock {
  display: none;
  width: 100%;
  max-width: 420px;
}
:where(html[data-page="scanner"]) .pc-scan-input {
  width: 100%;
  background: var(--surface);
  border: 2px solid var(--accent);
  color: var(--text);
  padding: 16px 18px;
  border-radius: 14px;
  font-family: 'DM Sans',sans-serif;
  font-size: 15px;
  outline: none;
  text-align: center;
  box-shadow: 0 6px 24px color-mix(in srgb, var(--accent) 15%, transparent);
}
:where(html[data-page="scanner"]) .modal-overlay {
  position: fixed;
  inset: 0;
  background: #000;
  z-index: 100;
  display: none;
  flex-direction: column;
}
:where(html[data-page="scanner"]) .cam-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px;
}
:where(html[data-page="scanner"]) .cam-title {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 11px;
  color: #9a9098;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
:where(html[data-page="scanner"]) .cam-close {
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.15);
  color: #f0ede6;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
:where(html[data-page="scanner"]) .cam-header-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
:where(html[data-page="scanner"]) .cam-toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 13px;
  border-radius: 10px;
  cursor: pointer;
  background: rgba(255,255,255,0.08);
  border: 1px solid rgba(255,255,255,0.15);
  color: #9a9098;
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--duration-base) ease,color var(--duration-base) ease,border-color var(--duration-base) ease;
}
:where(html[data-page="scanner"]) .photo-capture-link {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: #9a9098;
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
  padding: 6px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
:where(html[data-page="scanner"]) .manual-entry-bar {
  padding: 16px 18px 26px;
  display: flex;
  gap: 10px;
}
:where(html[data-page="scanner"]) .flash {
  position: fixed;
  inset: 0;
  z-index: 150;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s;
}

/* ---------- page: transfer ---------- */
:where(html[data-page="transfer"]) .nt-body {
  flex: 1;
  padding: 28px 24px 100px;
  display: flex;
  flex-direction: column;
  gap: 26px;
}
:where(html[data-page="transfer"]) .section-label {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  display: flex;
  align-items: center;
  gap: 8px;
}
:where(html[data-page="transfer"]) .summary-bar {
  display: flex;
  gap: 10px;
}
:where(html[data-page="transfer"]) .summary-card {
  flex: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 20px;
}
:where(html[data-page="transfer"]) .summary-label {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: 6px;
}
:where(html[data-page="transfer"]) .summary-value {
  font-family: 'DM Sans',sans-serif;
  font-size: 26px;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.ms-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  text-align: left;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 12px 38px 12px 14px;
  border-radius: var(--radius-sm);
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  min-height: 44px;
  cursor: pointer;
  transition: border-color var(--duration-base) ease;
}
.ms-value {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ms-panel {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  z-index: 60;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0,0,0,0.28);
  max-height: 264px;
  overflow-y: auto;
  padding: 6px;
}

.ms-inline {
  display: block;
  position: static;
  box-shadow: none;
  margin-top: 4px;
  width: 100%;
  align-self: stretch;
  text-align: left;
}
.ms-option {
  display: flex;
  align-items: center;
  text-align: left;
  gap: 10px;
  padding: 9px 10px;
  border-radius: 7px;
  cursor: pointer;
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  color: var(--text);
  transition: background var(--duration-fast) ease;
}
.ms-box {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  background: var(--surface2);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--on-accent);
  transition: background var(--duration-base) ease, border-color var(--duration-base) ease;
}
.ms-order {
  flex-shrink: 0;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 6px;
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
}
.ms-name {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ms-empty {
  padding: 12px 10px;
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
}
:where(html[data-page="transfer"]) .details-wrap {
  display: flex;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
}
:where(html[data-page="transfer"]) .field-reveal {
  animation: fadeIn var(--duration-slow) var(--ease);
}
:where(html[data-page="transfer"]) .field {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
:where(html[data-page="transfer"]) .field-label {
  font-family: 'DM Sans',sans-serif;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
}
:where(html[data-page="transfer"]) .select-wrap {
  position: relative;
}
:where(html[data-page="transfer"]) .field-select {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 12px 38px 12px 14px;
  border-radius: var(--radius-sm);
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  min-height: 44px;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  outline: none;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="transfer"], html[data-page="settings"]) .select-chevron {
  position: absolute;
  right: 13px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--text-muted);
  pointer-events: none;
}
:where(html[data-page="transfer"]) .odoo-import-wrap {
  display: flex;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
}
:where(html[data-page="transfer"]) .odoo-input {
  flex: 1;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  outline: none;
  min-width: 0;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="transfer"]) .odoo-import-btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  color: var(--accent);
  padding: 0 20px;
  border-radius: var(--radius-sm);
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  min-height: 44px;
  transition: border-color var(--duration-base) ease, background var(--duration-base) ease;
}

/* ---------- shared by dashboard / transfer ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"]) .grid-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface);
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .status-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: middle;
}
:where(html[data-page="dashboard"]) .section-label {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent);
  margin: 16px 0 4px;
  display: flex;
  align-items: center;
  gap: 8px;
}
:where(html[data-page="dashboard"]) .unknown-barcode {
  color: var(--error);
  font-weight: 600;
}
:where(html[data-page="dashboard"]) .select-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  max-width: 160px;
  width: 100%;
}
:where(html[data-page="dashboard"]) .picker-select {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  cursor: pointer;
  transition: border-color var(--duration-base) ease;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 100%;
  padding: 6px 30px 6px 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="dashboard"]) .sheet-overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  z-index: 220;
  display: none;
  align-items: flex-end;
}

/* ---------- page: transfer ---------- */
:where(html[data-page="transfer"], html[data-page="dashboard"]) .cell-input {
  width: 100%;
  background: transparent;
  border: none;
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  padding: 10px 12px;
  outline: none;
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .del-row-btn {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 8px;
  border-radius: 4px;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color var(--duration-fast) ease, background var(--duration-fast) ease;
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .grid-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  background: var(--surface2);
  border-top: 1px solid var(--border);
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .add-row-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  padding: 7px 14px;
  border-radius: 7px;
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 12px;
  cursor: pointer;
  min-height: 36px;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}
:where(html[data-page="transfer"], html[data-page="dashboard"]) .excel-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  padding: 7px 14px;
  border-radius: 7px;
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 12px;
  cursor: pointer;
  min-height: 36px;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}
:where(html[data-page="transfer"]) .submit-bar {
  position: sticky;
  bottom: 0;
  background: linear-gradient(to top, var(--bg) 60%, transparent);
  padding: 20px 24px 24px;
  display: flex;
  justify-content: flex-end;
}
:where(html[data-page="transfer"]) .create-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 14px 32px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  min-height: 48px;
  transition: background var(--duration-base) ease, opacity var(--duration-base) ease;
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .theme-toggle {
  position: relative;
  width: 52px;
  height: 28px;
  border-radius: 20px;
  background: var(--surface2);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
}
:where(html[data-page="settings"]) .st-body {
  flex: 1;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
:where(html[data-page="settings"]) .panel-toolbar {
  display: flex;
  justify-content: flex-end;
}
:where(html[data-page="settings"]) .add-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 11px 18px;
  border-radius: var(--radius-sm);
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  min-height: 44px;
  transition: background var(--duration-base) ease;
}
:where(html[data-page="settings"]) .add-btn:hover {
  background: var(--accent-hover);
}
:where(html[data-page="settings"]) .add-btn:active {
  background: var(--accent-active);
}
:where(html[data-page="settings"]) .grid-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--surface);
}
:where(html[data-page="settings"]) .grid-wrap table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
}
:where(html[data-page="settings"]) .grid-wrap tbody tr {
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background var(--duration-fast) ease;
}
:where(html[data-page="settings"]) .name-cell {
  font-weight: 600;
}
:where(html[data-page="settings"]) .pass-dots {
  color: var(--text-muted);
  letter-spacing: 2px;
}
:where(html[data-page="settings"]) .role-tag {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 4px 10px;
  border-radius: 20px;
}
:where(html[data-page="settings"]) .perm-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 11px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  padding: 5px 12px;
  border-radius: 20px;
  cursor: pointer;
  min-height: 30px;
  transition: border-color var(--duration-base) ease, background var(--duration-base) ease;
}
:where(html[data-page="settings"]) .perm-pill:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
:where(html[data-page="settings"]) .perm-pill.disabled:hover {
  border-color: var(--disabled-border);
  background: var(--disabled-bg);
}
:where(html[data-page="settings"]) tbody tr.locked {
  cursor: default;
}
:where(html[data-page="settings"]) tbody tr.locked td {
  opacity: 0.45;
}
:where(html[data-page="settings"]) tbody tr.locked:hover {
  background: transparent;
}
:where(html[data-page="settings"]) tbody tr.locked td:last-child {
  opacity: 1;
}
:where(html[data-page="settings"]) tbody tr.locked td:last-child .perm-pill.disabled {
  opacity: 0.45;
}
:where(html[data-page="settings"]) .lock-badge {
  display: inline-flex;
  align-items: center;
  color: var(--text-muted);
  margin-left: 7px;
  vertical-align: -2px;
}
:where(html[data-page="settings"]) .lock-badge svg {
  width: 13px;
  height: 13px;
}
:where(html[data-page="settings"]) .role-chip.disabled:hover {
  border-color: var(--border);
}
:where(html[data-page="settings"]) .perm-pill svg {
  width: 12px;
  height: 12px;
}
:where(html[data-page="settings"]) .empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 60px 20px;
  text-align: center;
}
:where(html[data-page="settings"]) .form-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 100;
  display: none;
  flex-direction: column;
}
:where(html[data-page="settings"]) .fo-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 22px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  flex-shrink: 0;
}
:where(html[data-page="settings"]) .fo-title {
  font-family: 'Playfair Display',serif;
  font-size: 20px;
  font-weight: 600;
}
:where(html[data-page="settings"], html[data-page="transfer"]) .fo-close {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}
:where(html[data-page="settings"], html[data-page="transfer"]) .fo-close:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}

/* ---------- shared by settings / login ---------- */
:where(html[data-page="settings"], html[data-page="login"]) .pass-toggle:hover {
  color: var(--accent);
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .fo-body {
  flex: 1;
  overflow-y: auto;
  padding: 24px 22px 60px;
  max-width: 440px;
  margin: 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
:where(html[data-page="settings"]) .role-chip:hover {
  border-color: var(--accent-hover);
}
:where(html[data-page="settings"]) .save-btn:hover {
  background: var(--accent-hover);
}
:where(html[data-page="settings"]) .save-btn:disabled {
  opacity: 0.45;
  cursor: wait;
}
:where(html[data-page="settings"]) .delete-btn:hover {
  background: color-mix(in srgb, var(--error) 12%, transparent);
}
:where(html[data-page="settings"]) .delete-btn:disabled {
  opacity: 0.45;
  cursor: wait;
}
:where(html[data-page="settings"]) .ghost-btn:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
:where(html[data-page="settings"]) .perm-option.parent:not(.checked) .perm-count {
  color: var(--text-muted);
}
:where(html[data-page="settings"]) .perm-chevron:hover {
  color: var(--accent);
}
:where(html[data-page="settings"]) .perm-chevron svg {
  width: 16px;
  height: 16px;
}
:where(html[data-page="settings"]) .perm-chevron.open {
  transform: rotate(180deg);
}
:where(html[data-page="settings"]) .perm-option.child .perm-option-label {
  font-size: 13px;
  color: var(--text-muted);
}
:where(html[data-page="settings"]) .perm-option.child.checked .perm-option-label {
  color: var(--text);
}
:where(html[data-page="settings"]) .perm-option:hover {
  border-color: var(--accent-hover);
}
:where(html[data-page="settings"]) .perm-option input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
:where(html[data-page="settings"]) .perm-option-check svg {
  width: 12px;
  height: 12px;
  opacity: 0;
  transition: opacity var(--duration-fast) ease;
}
:where(html[data-page="settings"]) .perm-option.checked .perm-option-check {
  background: var(--accent);
  border-color: var(--accent);
}
:where(html[data-page="settings"]) .perm-option.checked .perm-option-check svg {
  opacity: 1;
}
:where(html[data-page="settings"]) .perm-option.partial .perm-option-check {
  background: var(--accent);
  border-color: var(--accent);
}
:where(html[data-page="settings"]) .perm-option.partial .perm-option-check .pc-tick {
  display: none;
}
:where(html[data-page="settings"]) .perm-option.partial .perm-option-check .pc-dash {
  display: block;
  opacity: 1;
}
@media (min-width: 768px) {
  :where(html[data-page="settings"]) .confirm-overlay {
    align-items: center;
    justify-content: center;
    padding: 24px;
  }
  :where(html[data-page="settings"]) .confirm-box {
    max-width: 420px;
    border-radius: 20px;
    border: 1px solid var(--border);
  }
}
:where(html[data-page="settings"]) .confirm-ok:hover {
  background: color-mix(in srgb, var(--error) 12%, transparent);
}
:where(html[data-page="settings"]) .confirm-cancel:hover {
  border-color: var(--accent-hover);
  color: var(--accent);
}
@media (max-width: 640px) {
  :where(html[data-page="settings"]) .menu-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    background: transparent;
    border: none;
    color: var(--text);
    cursor: pointer;
    border-radius: var(--radius-sm);
  }
}

/* ---------- page: dashboard ---------- */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"]) .menu-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    background: transparent;
    border: none;
    color: var(--text);
    cursor: pointer;
    border-radius: var(--radius-sm);
  }
}

/* ---------- page: settings ---------- */
@media (max-width: 640px) {
  :where(html[data-page="settings"]) .st-header {
    padding: 14px 16px;
  }
  :where(html[data-page="settings"]) .st-body {
    padding: 16px;
  }
  :where(html[data-page="settings"]) .fo-body {
    padding: 18px 16px 50px;
  }
  :where(html[data-page="settings"]) .grid-wrap {
    overflow-x: visible;
  }
  :where(html[data-page="settings"]) .grid-wrap table {
    min-width: 0;
  }
  :where(html[data-page="settings"]) .grid-wrap table {
    display: block;
    width: 100%;
  }
}

/* ---------- shared by dashboard / settings ---------- */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap thead {
    display: none;
  }
}

/* ---------- page: dashboard ---------- */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"]) .grid-wrap table {
    display: block;
    width: 100%;
  }
}

/* ---------- shared by dashboard / settings ---------- */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tbody, :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap td {
    display: block;
    width: 100%;
  }
  :where(html[data-page="dashboard"], html[data-page="settings"]) .grid-wrap tr {
    display: block;
  }
}

/* ---------- page: settings ---------- */
@media (max-width: 640px) {
  :where(html[data-page="settings"]) .grid-wrap tbody td:first-child {
    border-top: none;
    font-size: 14px;
  }
}

/* ---------- page: login ---------- */
:where(html[data-page="login"]) [data-theme="light"] .login-card {
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
}

/* ---------- shared by all five pages ---------- */
.theme-toggle .tt-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: linear-gradient(135deg,var(--accent-hover) 0%,var(--accent) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--on-accent);
  transition: transform var(--duration-base) var(--ease);
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}
.theme-toggle .tt-sun {
  display: none;
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"], html[data-page="settings"], html[data-page="transfer"]) .tab-btn.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
:where(html[data-page="dashboard"]) .fb-pop[hidden], :where(html[data-page="dashboard"]) .fb-chips[hidden], :where(html[data-page="dashboard"]) .fb-result[hidden] {
  display: none;
}
:where(html[data-page="dashboard"]) .fb-pop.is-cal {
  width: min(380px, calc(100vw - 32px));
  padding: 0;
  max-height: none;
}
:where(html[data-page="dashboard"]) .fb-short.active {
  background: rgba(213,169,153,0.10);
  color: var(--accent);
  font-weight: 600;
}
:where(html[data-page="dashboard"]) .fb-nav.next {
  color: var(--accent);
}
:where(html[data-page="dashboard"]) .fb-day.in-range {
  background: rgba(213,169,153,0.10);
  border-radius: 6px;
}
:where(html[data-page="dashboard"]) .fb-day.edge {
  background: linear-gradient(135deg, var(--accent-hover), var(--accent));
  color: var(--on-accent);
  font-weight: 700;
  border-radius: 50%;
}
:where(html[data-page="dashboard"]) .status-pill.neutral {
  color: var(--text-muted);
  background: var(--disabled-bg);
  border: 1px solid var(--disabled-border);
}
:where(html[data-page="dashboard"]) .status-pill.processing {
  color: var(--processing);
  background: color-mix(in srgb, var(--processing) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--processing) 20%, transparent);
}
:where(html[data-page="dashboard"]) .status-pill.success {
  color: var(--success);
  background: color-mix(in srgb, var(--success) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 20%, transparent);
}
:where(html[data-page="dashboard"]) .status-pill.cancelled {
  color: var(--error);
  background: color-mix(in srgb, var(--error) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--error) 20%, transparent);
}
:where(html[data-page="dashboard"]) .detail-overlay.open {
  display: flex;
}
:where(html[data-page="dashboard"]) .do-header-left .do-id {
  font-family: 'DM Sans',sans-serif;
  font-weight: 700;
  font-size: 18px;
  color: var(--text);
}
:where(html[data-page="dashboard"]) .do-header-left .do-sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}
:where(html[data-page="dashboard"]) .status-dot.done {
  background: var(--success);
}
:where(html[data-page="dashboard"]) .status-dot.partial {
  background: var(--warning);
}
:where(html[data-page="dashboard"]) .status-dot.pending {
  background: var(--text-muted);
}
:where(html[data-page="dashboard"]) .status-dot.notfound {
  background: var(--error);
}
/* [Item 33] The fifth status. --info is the only semantic token still free in
   this table: --error is Not Found, --warning is Partial, --success is Done and
   --text-muted is Pending. Style Guide 9 - a status colour stays semantic and
   never borrows --accent. It cannot reuse Partial's amber either: Partial and
   Not Scanned DO appear together on a closed transfer. */
:where(html[data-page="dashboard"]) .status-dot.notscanned {
  background: var(--info);
}
:where(html[data-page="dashboard"]) .status-label.done {
  color: var(--success);
}
:where(html[data-page="dashboard"]) .status-label.partial {
  color: var(--warning);
}
:where(html[data-page="dashboard"]) .status-label.pending {
  color: var(--text-muted);
  font-weight: 400;
}
:where(html[data-page="dashboard"]) .status-label.notfound {
  color: var(--error);
}
:where(html[data-page="dashboard"]) .status-label.notscanned {
  color: var(--info);
}
/* [Item 9 \u00b7 Decision 682] The SIXTH label in this table, and the last semantic
   token that was still free INSIDE it: --error is Not Found, --warning is
   Partial, --success is Done, --text-muted is Pending and --info is Not
   Scanned. --processing was used only by the card's `In Progress` pill, never
   here, and its meaning is exactly right — a count that is under way.
   🔴 --info was the obvious reuse and it would have been a collision: Cancel
   does NOT convert `Counting` the way Complete does, so a cancelled stocktake
   carries `Counting` rows beside `Not Scanned` ones. 🔬 Measured before
   choosing: ESHOP-STK-003 is Cancelled and holds 2 of each. Style Guide §9 —
   a status colour stays semantic and never borrows --accent. */
:where(html[data-page="dashboard"]) .status-dot.counting {
  background: var(--processing);
}
:where(html[data-page="dashboard"]) .status-label.counting {
  color: var(--processing);
}
/* [Item 9 \u00b7 Decision 729] The variance. Its own class rather than borrowing
   .status-label.notfound or .su-flag: both of those name something else, and a
   class borrowed for its colour drags its meaning along with it.
   A count that MATCHES Odoo is muted rather than green — it is the absence of
   news, and painting it as an achievement would make a table of zeroes shout. */
:where(html[data-page="dashboard"]) .stk-diff {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="dashboard"]) .stk-diff.short {
  color: var(--error);
}
:where(html[data-page="dashboard"]) .stk-diff.over {
  color: var(--warning);
}
:where(html[data-page="dashboard"]) .stk-diff.level {
  color: var(--text-muted);
}
/* [Item 15] The Shopify shortfall number in the detail table.
   Its OWN class rather than borrowing .status-label.notfound: that name is the
   Scanner's "not on the shelf", which is a different fact, and Decision 175
   rejected the word "Missing" for exactly that collision. A class borrowed for
   its colour drags its meaning along with it (see the class="locked" defect). */
:where(html[data-page="dashboard"]) .su-flag {
  color: var(--error);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ---------- hover tooltip (Style Guide 16 / 22) ----------
   The Style Guide's tooltip carries a label for an icon-only button at 10px.
   This variant carries something a person READS - a stock figure on the
   Dashboard, a sentence explaining a permission in Settings - so it sits at
   11px; everything else - the --bg bubble, the 6px radius, the triangle - is
   that component unchanged.

   [Item 63] It was called .odoo-tip when the Dashboard was its only caller.
   Settings now uses the same component, and a second COPY of it would drift
   from this one within a session or two, so the name was generalised rather
   than duplicated. The Dashboard's behaviour did not change by a pixel.

   It is fixed and lives on <body> because '.grid-wrap' is 'overflow: hidden'
   and scrolls on desktop: anchored inside a row it would be clipped by its own
   table. The cursor is the only hint that a cell has something to say, and
   both it and the bubble exist ONLY where there is a real mouse. */
@media (hover: hover) and (pointer: fine) {
  /* [Mustafa, after using it] The dotted underline is gone: on a column of SKUs
     it read as noise rather than as an affordance. The cursor is kept - it costs
     nothing visually and still answers "is there something here?". */
  :where(html[data-page="dashboard"], html[data-page="settings"]) .tip {
    cursor: help;
  }
  /* [Item 63] The dotted underline was BACK on Settings for one version and is
     now gone from there too (Mustafa, after using it). The argument for keeping
     it was that the 25 permission notes are otherwise undiscoverable, and that
     argument was put and lost: the dots read as noise on a list of labels the
     same way they read as noise on a column of SKUs. Both pages now carry the
     cursor and nothing else, which is also the first time this component looks
     identical on both of them. */
}
:where(html[data-page="dashboard"], html[data-page="settings"]) .tip-bubble {
  position: fixed;
  z-index: 3000;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 5px 9px;
  font-family: 'DM Sans', sans-serif;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0,0,0,0.35);
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease;
}
:where(html[data-page="dashboard"], html[data-page="settings"]) .tip-bubble.show { opacity: 1; }
/* [Item 63] A stock figure never wraps; a sentence must. Settings only, so the
   Dashboard keeps the single-line bubble it was designed with. */
:where(html[data-page="settings"]) .tip-bubble {
  white-space: normal;
  max-width: 260px;
  line-height: 1.5;
  font-weight: 500;
  text-align: left;
}
:where(html[data-page="dashboard"], html[data-page="settings"]) .tip-bubble::after {
  content: '';
  position: absolute;
  left: 50%;
  margin-left: -5px;
  border: 5px solid transparent;
  border-top-color: var(--border);
  top: 100%;
}
:where(html[data-page="dashboard"], html[data-page="settings"]) .tip-bubble.below::after {
  top: auto;
  bottom: 100%;
  border-top-color: transparent;
  border-bottom-color: var(--border);
}
/* [Item 15 · Decision 168] The card flag: a red dot with NO count. The card
   says "this one needs a look"; the number lives in the detail table, where
   there is room to say which SKU and by how much.
   7px matches the compact status dot the Style Guide mandates for dense lists,
   and the colour is semantic --error - accent is never used for status. */
:where(html[data-page="dashboard"]) .tc-flag {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--error);
  margin-right: 7px;
  vertical-align: middle;
}
:where(html[data-page="dashboard"]) .select-wrap .sw-chevron {
  position: absolute;
  right: 9px;
  display: flex;
  pointer-events: none;
  color: var(--text-muted);
  transition: color var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .sheet .title {
  font-family: 'Playfair Display',serif;
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="dashboard"]) .sheet .sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
}

/* ---------- page: scanner ---------- */
:where(html[data-page="scanner"]) .screen.active {
  display: flex;
}
:where(html[data-page="scanner"]) .center-msg .icon {
  color: var(--text-muted);
  opacity: 0.45;
}
:where(html[data-page="scanner"]) .center-msg .title {
  font-family: 'Playfair Display',serif;
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="scanner"]) .center-msg .sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
  max-width: 280px;
  line-height: 1.6;
}
:where(html[data-page="scanner"]) .tp-status.in-progress {
  color: var(--processing);
  background: color-mix(in srgb, var(--processing) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--processing) 20%, transparent);
}
:where(html[data-page="scanner"]) .tp-status.pending {
  color: var(--text-muted);
  background: var(--disabled-bg);
  border: 1px solid var(--disabled-border);
}
:where(html[data-page="scanner"]) .sku-row.done {
  background: color-mix(in srgb, var(--success) 5%, transparent);
}
:where(html[data-page="scanner"]) .sku-row.dragging {
  position: relative;
  z-index: 5;
  background: var(--surface2);
  box-shadow: 0 10px 28px rgba(0,0,0,0.35);
  border-radius: 10px;
}
:where(html[data-page="scanner"]) .sku-row.notfound {
  background: color-mix(in srgb, var(--error) 4%, transparent);
}
:where(html[data-page="scanner"]) .modal-overlay.open {
  display: flex;
}
:where(html[data-page="scanner"]) .flash.show {
  opacity: 1;
}

/* ---------- page: transfer ---------- */
.ms-value.is-placeholder {
  color: var(--text-placeholder);
}
.ms-wrap .select-chevron {
  transition: transform var(--duration-base) ease;
}
:where(html[data-page="transfer"]) .field-select.is-placeholder {
  color: var(--text-placeholder);
}
:where(html[data-page="transfer"]) .sheet .title {
  font-family: 'Playfair Display',serif;
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="transfer"]) .sheet .sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
}
:where(html[data-page="transfer"]) .sheet-badge.danger {
  background: color-mix(in srgb, var(--error) 10%, transparent);
  color: var(--error);
}

/* ---------- shared by dashboard / scanner / transfer ---------- */
:where(html[data-page="dashboard"], html[data-page="scanner"], html[data-page="transfer"]) .big-btn.danger {
  background: color-mix(in srgb, var(--error) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--error) 30%, transparent);
  color: var(--error);
}

/* ---------- page: scanner ---------- */
:where(html[data-page="scanner"]) .cam-toggle .ct-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #9a9098;
  flex-shrink: 0;
  transition: background var(--duration-base) ease,box-shadow var(--duration-base) ease;
}
:where(html[data-page="scanner"]) .cam-toggle.active {
  background: color-mix(in srgb, #4ade80 22%, transparent);
  border-color: #4ade80;
  color: #f0ede6;
}
:where(html[data-page="scanner"]) .flash.success {
  background: color-mix(in srgb, var(--success) 28%, transparent);
}
:where(html[data-page="scanner"]) .flash.error {
  background: color-mix(in srgb, var(--error) 28%, transparent);
}
:where(html[data-page="scanner"]) .flash.warn {
  background: color-mix(in srgb, var(--warning) 28%, transparent);
}
:where(html[data-page="scanner"]) .sheet .sheet-icon {
  color: var(--success);
}
:where(html[data-page="scanner"]) .sheet .title {
  font-family: 'Playfair Display',serif;
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="scanner"]) .sheet .sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
}
/* [Item 7] Odoo free-stock warning inside the Not Found sheet. The twin of the
   dashboard's .sheet-error, in --warning rather than --error: the picker is not
   being told he did something wrong, he is being told to look again before he
   commits. Semantic colour, never a tinted accent (Style Guide S19).
   `text-align: left` is not optional - .sheet is a CENTRED flex column, so a
   block dropped into it inherits centring and reads as a banner instead of a
   note. No max-height or scroll: this is one short line, by construction. */
:where(html[data-page="scanner"]) .sheet-warn {
  font-family: 'DM Sans',sans-serif;
  color: var(--warning);
  background: color-mix(in srgb, var(--warning) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--warning) 25%, transparent);
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  width: 100%;
  text-align: left;
  /* The picker reads this in about half a second, so the NUMBER is the largest
     thing in the row and the words after it only say where it came from. flex +
     baseline keeps the 18px figure and the 12px label sitting on one line. */
  display: flex;
  align-items: baseline;
  gap: 9px;
}
:where(html[data-page="scanner"]) .sheet-warn .sw-icon {
  width: 18px;
  height: 18px;
  flex: none;
  /* Baseline alignment would hang an icon below the text it sits beside, so it is
     nudged back onto the optical line rather than being aligned as a glyph. */
  align-self: center;
}
:where(html[data-page="scanner"]) .sheet-warn .sw-num {
  font-size: 19px;
  font-weight: 600;
  line-height: 1;
}
:where(html[data-page="scanner"]) .sheet-warn .sw-label {
  font-size: 12px;
  font-weight: 500;
  line-height: 1.6;
}

/* ---------- page: settings ---------- */
/* The four hardcoded role colours that stood here - .role-tag.admin, .manager,
   .assistant and .picker - were moved into `roles.color` on 20 Aug 2026 and
   seeded with the very values they held, so those four look unchanged. They are
   gone from here rather than left as dead rules, because a stylesheet that
   still names roles is a second answer to a question the database now owns.
   See .role-tag[data-colored] at the end of this file. */
:where(html[data-page="settings"]) .perm-pill.none {
  color: var(--text-muted);
  background: var(--disabled-bg);
  border-color: var(--disabled-border);
}
:where(html[data-page="settings"]) .perm-pill.disabled {
  color: var(--text-muted);
  background: var(--disabled-bg);
  border-color: var(--disabled-border);
  cursor: default;
}
:where(html[data-page="settings"]) .role-chip.disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
:where(html[data-page="settings"]) .empty-state .sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
}
:where(html[data-page="settings"]) .form-overlay.open {
  display: flex;
}

/* ---------- shared by settings / login ---------- */
:where(html[data-page="settings"], html[data-page="login"]) .pass-toggle .eye-off {
  display: none;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .sheet-overlay.open {
  display: flex;
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .action-btn .ab-icon {
  display: flex;
  flex-shrink: 0;
  color: var(--text-muted);
  transition: color var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .action-btn.danger {
  color: var(--error);
  border-color: color-mix(in srgb, var(--error) 28%, transparent);
}
/* [Item 16] A push that succeeded but went short is amber, not red - the
   transfer DOES exist on Shopify. Style Guide 9: the semantic tokens stay
   semantic, so this is --warning and not a tinted accent. */
:where(html[data-page="dashboard"]) .sheet-badge.warning {
  background: color-mix(in srgb, var(--warning) 12%, transparent);
  color: var(--warning);
}
:where(html[data-page="dashboard"]) .sheet-badge.neutral {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .role-chip.checked {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent) inset;
}
:where(html[data-page="settings"]) .sheet .title {
  font-family: 'Playfair Display',serif;
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="settings"]) .sheet .sub {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
}
:where(html[data-page="settings"]) .perm-children.open {
  display: flex;
}
:where(html[data-page="settings"]) .perm-children.locked {
  opacity: 0.4;
  pointer-events: none;
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .perm-option.child {
  min-height: 42px;
  padding: 10px 13px;
  background: transparent;
}
:where(html[data-page="settings"]) .perm-option.all-row {
  background: transparent;
  border-style: dashed;
}
:where(html[data-page="settings"]) .perm-option.checked {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .perm-option-check .pc-dash {
  display: none;
}
:where(html[data-page="settings"]) .confirm-overlay.open {
  display: flex;
}

/* ---------- page: login ---------- */
:where(html[data-page="login"]) .corner-actions {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 50;
}
:where(html[data-page="login"]) .theme-toggle {
  position: relative;
  width: 52px;
  height: 28px;
  border-radius: 20px;
  background: var(--surface2);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
}

/* ---------- shared by settings / login ---------- */
:where(html[data-page="settings"], html[data-page="login"]) .pass-field-wrap {
  position: relative;
}

/* ---------- page: login ---------- */
:where(html[data-page="login"]) .login-wrap {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 20px;
}
:where(html[data-page="login"]) .login-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 36px 28px 32px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  animation: fadeIn var(--duration-slow) var(--ease);
}
:where(html[data-page="login"]) .login-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}

/* ---------- shared by settings / login ---------- */
:where(html[data-page="settings"], html[data-page="login"]) .field-label {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  margin-bottom: 7px;
  display: block;
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .field-input {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="settings"]) .field-error {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--error);
  margin-top: 6px;
  min-height: 14px;
}

/* ---------- page: login ---------- */
:where(html[data-page="login"]) .login-brand .logo-mark {
  border: 1px solid var(--border);
  border-radius: 12px;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="login"]) .login-brand .wordmark {
  font-family: 'Playfair Display',serif;
  font-weight: 700;
  font-size: 30px;
  color: #DAC7C0;
  line-height: 1;
  user-select: none;
}
:where(html[data-page="login"]) .login-brand .tagline {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-muted);
}
:where(html[data-page="login"]) .field-input {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  outline: none;
  transition: border-color var(--duration-base) ease;
}

/* ---------- shared by settings / login ---------- */
:where(html[data-page="settings"], html[data-page="login"]) .pass-toggle {
  position: absolute;
  right: 6px;
  top: 6px;
  bottom: 6px;
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 10px;
  display: flex;
  align-items: center;
  transition: color var(--duration-base) ease;
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .role-group {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px;
}
:where(html[data-page="settings"]) .role-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 11px 10px;
  cursor: pointer;
  user-select: none;
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 13px;
  color: var(--text-muted);
  min-height: 44px;
  transition: border-color var(--duration-fast) ease, background var(--duration-fast) ease, color var(--duration-fast) ease;
}
:where(html[data-page="settings"]) .fo-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 6px;
}
:where(html[data-page="settings"]) .save-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 14px 20px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  min-height: 50px;
  transition: background var(--duration-base) ease, opacity var(--duration-base) ease;
}
:where(html[data-page="settings"]) .delete-btn {
  background: color-mix(in srgb, var(--error) 6%, transparent);
  color: var(--error);
  border: 1px solid color-mix(in srgb, var(--error) 30%, transparent);
  padding: 13px 20px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  min-height: 48px;
  transition: background var(--duration-base) ease;
}

/* ---------- page: login ---------- */
:where(html[data-page="login"]) .pass-field-wrap .field-input {
  padding-right: 44px;
}
:where(html[data-page="login"]) .pass-toggle svg {
  width: 18px;
  height: 18px;
}
:where(html[data-page="login"]) .login-error {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--error);
  text-align: center;
  line-height: 1.5;
  min-height: 18px;
}
:where(html[data-page="login"]) .login-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 14px 20px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  min-height: 50px;
  width: 100%;
  transition: background var(--duration-base) ease, opacity var(--duration-base) ease;
}

/* ---------- shared by settings / login ---------- */

/* ---------- shared by scanner / transfer / settings ---------- */
:where(html[data-page="scanner"], html[data-page="transfer"], html[data-page="settings"]) .sheet-overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  z-index: 220;
  display: none;
  align-items: flex-end;
}

/* ---------- shared by dashboard / scanner / transfer ---------- */
:where(html[data-page="dashboard"], html[data-page="scanner"], html[data-page="transfer"]) .sheet {
  width: 100%;
  background: var(--surface);
  border-radius: 20px 20px 0 0;
  padding: 28px 24px 32px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
  text-align: center;
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .sheet {
  width: 100%;
  background: var(--surface);
  border-radius: 20px 20px 0 0;
  padding: 28px 24px 32px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-align: center;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
:where(html[data-shell="app"]) .sheet-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  margin-top: 8px;
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .sheet-badge {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--error) 10%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--error);
}
:where(html[data-page="dashboard"]) .tc-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

/* ---------- page: scanner ---------- */
:where(html[data-page="scanner"]) .undo-qty-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: 14px 0 4px;
}
:where(html[data-page="scanner"]) .undo-step {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface2);
  color: var(--text);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--duration-fast) ease,color var(--duration-fast) ease;
}
:where(html[data-page="scanner"]) .undo-qty-input {
  width: 76px;
  text-align: center;
  padding: 9px 4px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-family: 'DM Sans',sans-serif;
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="scanner"]) .sheet-input {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 14px 16px;
  border-radius: 10px;
  font-family: 'DM Sans',sans-serif;
  font-size: 15px;
  outline: none;
  text-align: center;
}
/* [Item 9 \u00b7 Decision 698] THE SAME COMPONENT, NOT A SECOND ONE. Every value
   above is repeated here rather than merged into one selector for a reason
   Item 72 measured: 81% of this stylesheet names exactly one page, and the two
   inputs differ in the two things that matter.
   🔴 `text-align: center` is right for the Scanner, where the field holds ONE
   barcode typed by a picker, and wrong here, where it holds a pasted COLUMN of
   SKUs — centred text makes a list unreadable. And a textarea needs a
   resize rule, which the Scanner's <input> has no use for. */
:where(html[data-page="dashboard"]) .sheet-input {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 12px 14px;
  border-radius: 10px;
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  outline: none;
  text-align: left;
  resize: vertical;
  min-height: 92px;
}
:where(html[data-page="dashboard"]) .sheet-input:focus {
  border-color: var(--accent);
}
/* [Mustafa - Add SKU autocomplete] Modelled on .fb-pop and .fb-opt, which are
   this page's popover and option row, rather than invented next to them.
   It opens UPWARD: the action sheet is anchored to the bottom of the viewport,
   so a list dropped below the box would run off the screen and cover the Add
   button on the way. .sheet centres its children and centres their text, so
   both are undone here - a list of ids reads from the left. */
:where(html[data-page="dashboard"]) .sku-sug-wrap {
  position: relative;
  width: 100%;
}
/* [specs/006] IT ESCAPES THE TABLE. The draft row lives inside `.do-body
   .grid-wrap`, which scrolls (`overflow-y: auto`) - and an absolutely
   positioned list inside a scrolling box is CLIPPED by it, so a list opened
   downward simply vanished (Mustafa, 2026-09-16). `fixed` takes it out of that
   box entirely; renderSkuSuggest sets top/left/width from the cell's own
   rectangle, and flips it above the cell when the window has no room below. */
:where(html[data-page="dashboard"]) .sku-sug {
  position: fixed;
  z-index: 240;
  max-height: 260px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,0.18);
  padding: 4px;
  text-align: left;
}
:where(html[data-page="dashboard"]) .sku-sug-item {
  padding: 9px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="dashboard"]) .sku-sug-item b {
  color: var(--accent);
  font-weight: 700;
}
:where(html[data-page="dashboard"]) .sku-sug-item:hover,
:where(html[data-page="dashboard"]) .sku-sug-item.active {
  background: var(--hover-bg);
}
:where(html[data-page="dashboard"]) .sku-sug-more {
  padding: 8px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  color: var(--text-muted);
}

/* ---------- page: transfer ---------- */
:where(html[data-page="transfer"]) .sheet-badge {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--info) 10%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--info);
}

/* ---------- shared by dashboard / transfer ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"]) .big-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  padding: 15px 30px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  min-height: 50px;
  transition: background var(--duration-base) ease;
}
:where(html[data-page="dashboard"], html[data-page="transfer"]) .big-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* ---------- shared by dashboard / transfer / settings ---------- */
:where(html[data-page="dashboard"], html[data-page="transfer"], html[data-page="settings"]) .ghost-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  padding: 13px 26px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  min-height: 46px;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}

/* ---------- page: dashboard ---------- */
:where(html[data-page="dashboard"]) .kebab-btn {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--duration-base) ease,color var(--duration-base) ease,background var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .do-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* [v64] THE LIST SCROLLS, NOT THE SHEET. A sheet has a badge, a title, a line
   of explanation and a Close button around its list; letting the whole sheet
   grow pushes all four off the screen and clips the last row, which is exactly
   what seven pickers did. Capping the LIST keeps every one of them in place and
   makes the list the only thing that moves.

   min(52vh, 430px) and the 2px gutter are copied from .perm-options in
   settings, which solved this same problem - one number for both, not two that
   drift. 52vh leaves room for the badge, title, sub and Close on a phone, where
   the sheet is anchored to the bottom edge and has the least space.

   NOTE the companion rule further down: .sheet-list is in the
   overscroll-behavior: contain list. Without it a list scrolled to its end
   hands the wheel to the page behind the overlay - the documented Manage Role
   bug, reproduced exactly. */
:where(html[data-page="dashboard"]) .sheet-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  margin-top: 4px;
  max-height: min(52vh, 430px);
  overflow-y: auto;
  padding-right: 2px;
}
:where(html[data-page="dashboard"]) .action-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 13px 16px;
  border-radius: var(--radius);
  min-height: 50px;
  font-family: 'DM Sans',sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--duration-base) ease,color var(--duration-base) ease,background var(--duration-base) ease;
}
:where(html[data-page="dashboard"]) .sheet-note {
  font-family: 'DM Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size: 12px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  padding: 6px 12px;
  border-radius: 20px;
  word-break: break-all;
}
:where(html[data-page="dashboard"]) .sheet-error {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--error);
  line-height: 1.6;
  background: color-mix(in srgb, var(--error) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--error) 25%, transparent);
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  width: 100%;
  text-align: left;
  word-break: break-word;
  max-height: 220px;
  overflow-y: auto;
  user-select: text;
}
/* [Item 16] The shared `.grid-wrap` table, inside a sheet. Two things the
   sheet does not give it: the sheet is a CENTRED flex column, so a table
   dropped in inherits `text-align: center` while `.grid-wrap thead th` stays
   left - and Style Guide 10 requires a header and the cells under it to share
   one alignment. And the sheet does not scroll a child for it, so the table
   needs its own ceiling or a long shortfall pushes Close off the screen.
   The sticky header is the same treatment `.do-body .grid-wrap` already gets. */
:where(html[data-page="dashboard"]) .sheet-table {
  width: 100%;
  text-align: left;
  /* Raised with the card layout below: a card is taller than the table row it
     replaced, and 320px showed barely more than one of them. */
  max-height: min(52vh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* [Shopify shortfall] THE SHEET IS 420px WIDE AT EVERY SCREEN SIZE, so the card
   shape the rest of this page adopts below 640px has to apply here with no
   media query at all - the viewport is not what constrains this table.

   Measured on the four columns it draws: SKU ~120px ("BC3-Black&Beige-OS"),
   Required ~62px, Available ~68px, Status ~75px, plus eight cell paddings at
   12px = 96px. That is ~421px of content inside ~370px of usable sheet, and the
   column that falls off the right edge is Status - the one column that says WHY
   the row is in the list at all.

   This is the SAME defect Item 22 measured in the shortfall EMAIL and fixed the
   same way (192px of stacked padding on a 360px phone). The email became cards;
   this popup was left behind with the original table. Both now draw one card per
   SKU - which is what the code building this table already promises: the screen
   and the mail must never describe one event differently.

   .sheet-table appears on exactly one element in the whole app, so none of this
   reaches another table. */
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table thead {
  display: none;
}
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table table,
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody,
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table tr,
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table td {
  display: block;
  width: 100%;
}
/* No horizontal margin: inside a 420px sheet every pixel of width is the
   content's, which is the whole reason this rule exists. */
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody tr {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin: 10px 0;
  padding: 4px 14px;
  background: var(--surface);
}
/* These cells are flex containers, so `text-align` does not place their
   contents - flex distribution does. The label is pushed left by its own
   `margin-right: auto` below, and everything after it packs together on the
   right. `space-between` was wrong here: the Status cell holds THREE boxes
   (label, dot, word) and spread them evenly across the row, leaving the dot
   marooned in the middle instead of sitting against the word it belongs to. */
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody td {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 0;
  border-top: 1px solid var(--border);
  white-space: normal;
}
/* The SKU owns the card's first line and carries no label beside it - it NAMES
   the card rather than being one of its facts. Same shape as the email's card.
   Its ::before is removed outright, not just emptied: an empty box still takes
   part in the flex line and its auto margin would push the SKU to the right. */
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody td:first-child {
  border-top: none;
  font-weight: 600;
  overflow-wrap: anywhere;
}
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody td::before {
  content: attr(data-label);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  flex-shrink: 0;
  /* This is what splits the row: label hard left, every remaining box hard
     right and adjacent to its neighbour. */
  margin-right: auto;
}
:where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody td:first-child::before {
  display: none;
}

/* [Shopify shortfall] ON A DESKTOP IT GOES BACK TO BEING A TABLE (Mustafa).
   The cards above are what a 420px sheet can hold; they are not a preference.
   Given room, four short columns are easier to compare down the page than four
   stacked cards, so on a real screen this ONE dialog is widened to 600px and
   the table returns.

   Deliberately NOT the same shape as the shortfall email, and that is Mustafa's
   call: a desktop screen and a phone mail are different places to read, so they
   need not look alike. What must NOT diverge is the WORDING - the same four
   columns and the same two Status words ('Low Stock' / 'Not Found') - and that
   is untouched here. Only the arrangement differs.

   `:has()` rather than a class toggled from JS: the sheet's content is written
   with innerHTML, so a class would have to be added by one caller and cleared by
   every other one, and the first caller that forgot would leave the next dialog
   600px wide. This reacts to what is actually inside and needs no bookkeeping.

   Fits with room to spare: ~550px usable inside the 600px sheet against SKU
   120px + Required 62px + Available 68px + Status 75px + eight 8px paddings
   = ~389px. */
@media (min-width: 768px) {
  :where(html[data-page="dashboard"]) .sheet:has(.sheet-table) {
    max-width: 600px;
  }
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table thead {
    display: table-header-group;
  }
  /* Restored with the header: it was pointless while thead was hidden. */
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: 10px 8px;
  }
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table table {
    display: table;
    width: 100%;
  }
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody {
    display: table-row-group;
    width: auto;
  }
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table tr {
    display: table-row;
    width: auto;
  }
  /* The card chrome is undone rather than overridden piecemeal - a leftover
     radius or background on a table row reads as a rendering fault. */
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody tr {
    border: 0;
    border-radius: 0;
    margin: 0;
    padding: 0;
    background: none;
  }
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody td {
    display: table-cell;
    width: auto;
    padding: 10px 8px;
    border-top: 1px solid var(--border);
    vertical-align: middle;
    white-space: nowrap;
  }
  /* The SKU is the only value long enough to need a second line. */
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody td:first-child {
    font-weight: 500;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  /* The column headers say it now, so the per-cell labels would say it twice. */
  :where(html[data-page="dashboard"]) .grid-wrap.sheet-table tbody td::before {
    display: none;
  }
}
:where(html[data-page="dashboard"]) .sheet-working {
  display: flex;
  justify-content: center;
  padding: 6px 0 2px;
}
/* [Item 31] The id and its direction, stacked. min-width:0 lets the column
   shrink inside .tc-top instead of shouldering the status pill off the card. */
:where(html[data-page="dashboard"]) .tc-head {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
/* Outbound / Inbound, written the way the database stores it - no uppercasing,
   so it reads as a word under the id rather than a second label competing with
   the status pill.

   The colours are the two the card does not already use: its status pill spends
   --success on Completed, --error on Cancelled, --processing on In Progress and
   --text-muted on Pending. Purple and amber are what is left, and reusing any of
   the other four would put one hue on the same card meaning two things.
   Deliberately NOT green or red: a direction is neither good nor bad. */
:where(html[data-page="dashboard"]) .tc-dir {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}
:where(html[data-page="dashboard"]) .tc-dir.out {
  color: var(--info);
}
:where(html[data-page="dashboard"]) .tc-dir.in {
  color: var(--warning);
}
/* [Item 9 \u00b7 Decision 680] The word "Stocktake" stands where a transfer's
   direction stands, because it answers the same question: what KIND of job is
   this. --processing is the same token the `Counting` row uses in the detail
   table, so one colour carries one meaning across the whole feature — blue is
   a count in progress, wherever it appears. */
:where(html[data-page="dashboard"]) .tc-dir.stk {
  color: var(--processing);
}
:where(html[data-page="dashboard"]) .odoo-ref,
:where(html[data-page="dashboard"]) .shopify-ref {
  font-family: 'DM Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size: 10px;
  border: 1px solid transparent;
  padding: 2px 8px;
  border-radius: 20px;
  white-space: nowrap;
}
/* Each chip wears its own system's brand colour, so which is which is read at
   a glance instead of by parsing the value.

   THE BRAND HEX IS NOT USED FOR THE TEXT, and that is measured, not cautious:
   against the card surface #714B67 scores 2.36 on the dark theme and #5E8E3E
   scores 3.88 on the light one - both under the 4.5 a 10px label needs, and the
   purple is effectively unreadable. Mixing 40% toward --text clears both themes
   with ONE declaration, because --text itself flips with the theme: the colour
   lightens on dark and darkens on light. Measured after the mix: 7.46 / 7.11 for
   Shopify and 5.52 / 10.69 for Odoo. This is the same treatment, for the same
   reason, that roles.color already gets in settings.

   The BORDER keeps the raw brand hex. A border carries no contrast requirement,
   so the true colour stays on the screen while only the text is lifted. */
:where(html[data-page="dashboard"]) .odoo-ref {
  color: color-mix(in srgb, #714B67 60%, var(--text));
  border-color: color-mix(in srgb, #714B67 55%, transparent);
}
:where(html[data-page="dashboard"]) .shopify-ref {
  color: color-mix(in srgb, #5E8E3E 60%, var(--text));
  border-color: color-mix(in srgb, #5E8E3E 55%, transparent);
}
/* [Reference links] EITHER chip becomes an <a> when Settings > General holds
   that system's transfer URL and the transfer has something to build one
   from - a GID for Shopify, a numeric picking id for Odoo. Colour, border
   and shape are all inherited from the rule above; this variant adds ONLY
   what being a link means, so the linked and unlinked chips cannot drift
   apart into two different-looking things. */
:where(html[data-page="dashboard"]) a.odoo-ref,
:where(html[data-page="dashboard"]) a.shopify-ref {
  text-decoration: none;
  cursor: pointer;
}
/* The <span> this replaces was not reachable by keyboard at all; an <a> is, so
   it needs a visible focus state. Nothing else on this page defines one, so it
   is stated here rather than inherited from a shared rule that does not exist. */
:where(html[data-page="dashboard"]) a.odoo-ref:focus-visible,
:where(html[data-page="dashboard"]) a.shopify-ref:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* [Reference chips] BOTH chips lift on hover (Mustafa). The movement belongs to
   the shared chip shape, not to the link variant - the Odoo chip gets it too,
   and gets it before it has anywhere to go.

   `transform` works here only because .tc-date is inline-flex, which blockifies
   its children; on a plain inline <span> it would be silently ignored.

   Gated on (hover: hover): this Dashboard is mostly read on a phone, where a
   tap would otherwise leave a chip stuck in its hovered state with nothing to
   clear it. */
@media (hover: hover) {
  :where(html[data-page="dashboard"]) .odoo-ref,
  :where(html[data-page="dashboard"]) .shopify-ref {
    transition: transform var(--duration-base) cubic-bezier(0.4,0,0.2,1),
                color var(--duration-base) cubic-bezier(0.4,0,0.2,1),
                border-color var(--duration-base) cubic-bezier(0.4,0,0.2,1);
  }
  :where(html[data-page="dashboard"]) .odoo-ref:hover,
  :where(html[data-page="dashboard"]) .shopify-ref:hover {
    transform: translateY(-2px);
  }
  /* Only the LINKED chip also brightens. The lift says "alive"; the colour
     shift says "this one goes somewhere" - which, since Item 52, the Odoo
     chip can say too, so it gets the same treatment in its own brand hex.
     Moving FURTHER toward var(--text) can only raise contrast above the resting
     value the Style Guide already measured, so it needs no measurement of its own. */
  :where(html[data-page="dashboard"]) a.shopify-ref:hover {
    color: color-mix(in srgb, #5E8E3E 35%, var(--text));
    border-color: #5E8E3E;
  }
  :where(html[data-page="dashboard"]) a.odoo-ref:hover {
    color: color-mix(in srgb, #714B67 35%, var(--text));
    border-color: #714B67;
  }
}
@media (prefers-reduced-motion: reduce) {
  :where(html[data-page="dashboard"]) .odoo-ref,
  :where(html[data-page="dashboard"]) .shopify-ref { transition: none; }
  :where(html[data-page="dashboard"]) .odoo-ref:hover,
  :where(html[data-page="dashboard"]) .shopify-ref:hover { transform: none; }
}

/* [General layout] The General tab is ONE record, drawn as setting/value pairs
   down the page instead of across it. Only that table carries .ref-vertical. */
/* THE PADDING is the whole reason the first attempt looked broken: the value
   cell inherits `padding: 12px` from the shared `tbody td` rule, but a <th>
   matches no rule on this page and kept the browser's own near-zero padding.
   The label ended up jammed into the top-left corner of its cell while the
   value sat 12px in and vertically centred - two cells of the same row that
   looked like they belonged to different rows.
   Same padding, same font size, same vertical-align on BOTH, or they drift. */
:where(html[data-page="settings"]) .grid-wrap table.ref-vertical th.ref-key {
  padding: 12px;
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-muted);
  text-align: left;
  white-space: nowrap;
  width: 210px;
  vertical-align: top;
}
/* The Shopify URL is ~55 characters and must be allowed to wrap; every other
   cell on this screen sets nowrap, which would push it out of the card.
   `anywhere` and not `break-all`: it breaks only when a line genuinely cannot
   fit, instead of chopping every value at the right edge regardless. */
:where(html[data-page="settings"]) .grid-wrap table.ref-vertical td.ref-val {
  line-height: 1.5;
  vertical-align: top;
  white-space: normal;
  overflow-wrap: anywhere;
}
/* Each pair is one line of a list, so the divider belongs between the PAIRS and
   never between a label and its own value. */
:where(html[data-page="settings"]) .grid-wrap table.ref-vertical tbody tr {
  border-bottom: 1px solid var(--border);
}
:where(html[data-page="settings"]) .grid-wrap table.ref-vertical tbody tr:last-child {
  border-bottom: none;
}
/* The narrow-screen rules turn every cell into a stacked label/value pair via
   ::before. This table IS that pair already, so it opts out and simply keeps
   its two columns, with the key column giving up its fixed width. */
@media (max-width: 767px) {
  :where(html[data-page="settings"]) .grid-wrap table.ref-vertical tbody tr {
    display: table-row;
  }
  :where(html[data-page="settings"]) .grid-wrap table.ref-vertical tbody th.ref-key,
  :where(html[data-page="settings"]) .grid-wrap table.ref-vertical tbody td.ref-val {
    display: table-cell;
    text-align: left;
  }
  :where(html[data-page="settings"]) .grid-wrap table.ref-vertical tbody td::before {
    content: '';
  }
  :where(html[data-page="settings"]) .grid-wrap table.ref-vertical th.ref-key {
    width: 40%;
    white-space: normal;
  }
}
:where(html[data-page="dashboard"]) .row-del-btn {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color var(--duration-base) ease,border-color var(--duration-base) ease;
}

/* ---------- page: settings ---------- */
:where(html[data-page="settings"]) .perm-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
  max-height: min(52vh, 430px);
  overflow-y: auto;
  padding-right: 2px;
}
:where(html[data-page="settings"]) .perm-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
:where(html[data-page="settings"]) .perm-hit {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}
:where(html[data-page="settings"]) .perm-count {
  margin-left: auto;
  font-family: 'DM Mono',monospace;
  font-size: 11px;
  color: var(--accent);
  letter-spacing: 0.04em;
  flex-shrink: 0;
}
:where(html[data-page="settings"]) .perm-chevron {
  flex-shrink: 0;
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  width: 32px;
  height: 32px;
  margin: -6px -6px -6px 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--duration-fast) ease, color var(--duration-fast) ease;
}
:where(html[data-page="settings"]) .perm-children {
  display: none;
  flex-direction: column;
  gap: 6px;
  padding-left: 18px;
}
:where(html[data-page="settings"]) .perm-option {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 13px 14px;
  cursor: pointer;
  user-select: none;
  text-align: left;
  min-height: 48px;
  transition: border-color var(--duration-fast) ease, background var(--duration-fast) ease;
}
:where(html[data-page="settings"]) .perm-option-check {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--on-accent);
  transition: background var(--duration-fast) ease, border-color var(--duration-fast) ease;
}
:where(html[data-page="settings"]) .perm-option-label {
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 14px;
  color: var(--text);
}
:where(html[data-page="settings"]) .confirm-overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay);
  z-index: 300;
  display: none;
  align-items: flex-end;
}
:where(html[data-page="settings"]) .confirm-box {
  background: var(--surface);
  border-radius: 20px 20px 0 0;
  padding: 28px 24px 32px;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
  text-align: center;
}
:where(html[data-page="settings"]) .confirm-badge {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--error) 10%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--error);
}
:where(html[data-page="settings"]) .confirm-title {
  font-family: 'Playfair Display',serif;
  font-size: 20px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="settings"]) .confirm-message {
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
}
:where(html[data-page="settings"]) .confirm-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  margin-top: 8px;
}
:where(html[data-page="settings"]) .confirm-ok {
  background: color-mix(in srgb, var(--error) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--error) 30%, transparent);
  color: var(--error);
  padding: 15px 30px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  min-height: 50px;
  transition: background var(--duration-base) ease;
}
:where(html[data-page="settings"]) .confirm-cancel {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  padding: 13px 26px;
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 13px;
  cursor: pointer;
  min-height: 46px;
  transition: border-color var(--duration-base) ease, color var(--duration-base) ease;
}

/* ---------- page: login ---------- */
:where(html[data-page="login"]) .login-btn:hover {
  background: var(--accent-hover);
}
:where(html[data-page="login"]) .login-btn:active {
  background: var(--accent-active);
}
:where(html[data-page="login"]) .login-btn:disabled {
  opacity: 0.45;
  cursor: wait;
}
@media (max-width: 640px) {
  :where(html[data-page="login"]) .login-card {
    padding: 30px 22px 26px;
    border: none;
    background: transparent;
  }
  :where(html[data-page="login"]) [data-theme="light"] .login-card {
    box-shadow: none;
  }
}

/* ==========================================================
   ORDER FIX - @media rules that were emitted BEFORE the base
   rule they must override, so they never applied. Re-stated
   here, scoped per page, to restore the original behaviour.
   Purely additive: every byte above this line is unchanged.
   ========================================================== */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"]) .btn-icon {
    height: 44px;
    width: 44px;
  }
  :where(html[data-page="dashboard"]) .db-body {
    padding: 16px;
  }
  :where(html[data-page="dashboard"]) .db-header {
    padding: 14px 16px;
  }
  :where(html[data-page="dashboard"]) .do-body {
    padding: 16px 16px 40px;
  }
  :where(html[data-page="dashboard"]) .do-header {
    padding: 14px 16px;
  }
  :where(html[data-page="dashboard"]) .fb-search {
    max-width: none;
  }
  :where(html[data-page="dashboard"]) .fb-select-wrap {
    max-width: none;
  }
  :where(html[data-page="dashboard"]) .kebab-btn {
    height: 40px;
    width: 40px;
  }
  :where(html[data-page="dashboard"]) .row-del-btn {
    height: 38px;
    width: 38px;
  }
  :where(html[data-page="dashboard"], html[data-page="scanner"], html[data-page="settings"], html[data-page="transfer"]) .side-menu {
    display: none;
  }
  :where(html[data-page="transfer"], html[data-page="dashboard"]) .cell-input {
    background: var(--surface2);
    border: 1px solid var(--border);
  }
  :where(html[data-page="transfer"], html[data-page="dashboard"]) .del-row-btn {
    padding: 8px 14px;
    width: auto;
  }
  :where(html[data-page="transfer"], html[data-page="dashboard"]) .grid-footer {
    align-items: stretch;
  }
  :where(html[data-page="transfer"]) .nt-body {
    padding: 20px 16px 100px;
  }
  :where(html[data-page="transfer"]) .submit-bar {
    padding: 16px;
  }
}
@media (max-width: 560px) {
  :where(html[data-page="dashboard"]) .fb-cal-shorts {
    border-right: none;
    flex-direction: row;
    width: 100%;
  }
  :where(html[data-page="dashboard"]) .fb-short {
    text-align: center;
  }
}
@media (min-width: 768px) {
  :where(html[data-page="dashboard"], html[data-page="scanner"], html[data-page="settings"], html[data-page="transfer"]) .sheet {
    border-radius: 20px;
  }
  :where(html[data-page="dashboard"], html[data-page="scanner"], html[data-page="settings"], html[data-page="transfer"]) .sheet-overlay {
    align-items: center;
  }
  :where(html[data-page="scanner"]) .pc-scan-dock {
    display: block;
  }
  :where(html[data-page="scanner"]) .scan-btn {
    display: none;
  }
  :where(html[data-page="settings"]) .confirm-box {
    border-radius: 20px;
  }
  :where(html[data-page="settings"]) .confirm-overlay {
    align-items: center;
  }
}

/* ---------- page: dashboard — bulk SKU reassignment (roadmap item 4A) ---------- */
:where(html[data-page="dashboard"]) .sku-pick {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
}
:where(html[data-page="dashboard"]) .sku-pick input {
  accent-color: var(--accent);
  width: 14px;
  height: 14px;
  margin: 0;
  cursor: pointer;
  flex-shrink: 0;
}
/* Floats above the rows instead of sitting past the end of a long table: on a
   246-piece transfer the static bar was unreachable without scrolling to the
   bottom. Sticky keeps it in view inside whichever element is scrolling -
   .do-body below 641px, .grid-wrap above it. fit-content keeps it a centred
   pill rather than a full-width strip. z-index clears the sticky thead (2). */
:where(html[data-page="dashboard"]) .bulk-bar {
  position: sticky;
  bottom: 16px;
  z-index: 5;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  width: fit-content;
  max-width: 100%;
  margin: 12px auto 0;
  padding: 10px 14px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px var(--overlay);
}
/* display:flex above would otherwise defeat the hidden attribute. */
:where(html[data-page="dashboard"]) .bulk-bar[hidden] {
  display: none;
}
/* [Item 12] The Action Bar's own Select all is a DUPLICATE of the checkbox in
   the table header, which exists only above 640px - below that the whole thead
   is display:none (see the rule further down) and this button is the only way
   to select everything. So it is shown exactly where the header is not. */
@media (min-width: 641px) {
  :where(html[data-page="dashboard"]) .bb-selectall {
    display: none;
  }
}
:where(html[data-page="dashboard"]) .bb-count {
  font-family: 'DM Sans',sans-serif;
  font-weight: 600;
  font-size: 12px;
  color: var(--accent);
  white-space: nowrap;
}

/* ---------- page: dashboard ---------- */
@media (max-width: 640px) {
  :where(html[data-page="dashboard"]) .bulk-bar {
    bottom: 10px;
    margin: 10px auto 0;
  }
}

/* [v64] The two `.bulk-bar .select-wrap` width rules that stood here - the
   mobile override and Item 11b's 260px desktop cap - were removed with the
   <select> itself. The Action Bar holds no input any more, so there is no
   width left to tune. Item 11b is dissolved, not reverted: the truncation it
   fixed cannot occur in a sheet, where every name is a full-width row. */

/* ---------- page: settings ---------- */
/* Item 17 batch A. The Role control is a native <select>: it gives the phone its
   own picker for free, stays keyboard- and screen-reader-correct, and grows with
   the roles table instead of with this stylesheet. */
:where(html[data-page="settings"]) .role-select-wrap {
  position: relative;
}
:where(html[data-page="settings"]) .role-select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 40px;
  cursor: pointer;
  min-height: 44px;
}
:where(html[data-page="settings"]) .role-select-chevron {
  position: absolute;
  right: 14px;
  top: 50%;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  color: var(--accent);
  pointer-events: none;
}
:where(html[data-page="settings"]) .role-select option {
  background: var(--surface);
  color: var(--text);
}
:where(html[data-page="settings"]) .field-input:disabled {
  background: var(--disabled-bg);
  border-color: var(--disabled-border);
  color: var(--text-disabled);
  cursor: not-allowed;
}
:where(html[data-page="settings"]) .role-select:disabled {
  cursor: not-allowed;
}
:where(html[data-page="settings"]) .fo-note {
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-muted);
  background: var(--disabled-bg);
  border: 1px solid var(--disabled-border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}
/* Neutral fallback for every role whose colour is not set - which is now a real
   stored answer rather than an accident of which names a stylesheet happened to
   know. A role that HAS a colour overrides this through .role-tag[data-colored]
   at the end of this file.

   The .role-tag.branch-manager rule that sat here went with the other four: it
   existed only to undo a collision between 'Branch Manager' lowercased and the
   Manager colour, and with no name-keyed classes left there is nothing to
   collide. */
:where(html[data-page="settings"]) .role-tag {
  color: var(--text-muted);
  background: var(--hover-bg);
  border: 1px solid var(--border);
}
/* ---------- page: settings — Reference Data tabs (Item 13) ---------- */
:where(html[data-page="settings"]) .tab-panel {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
:where(html[data-page="settings"]) .tab-panel[hidden] {
  display: none;
}
:where(html[data-page="settings"]) #panelRef tbody tr {
  cursor: default;
}
:where(html[data-page="settings"]) #panelRef tbody tr:hover {
  background: transparent;
}
/* A row is only pointer-and-tint when it actually opens - the cursor is the
   one honest signal that something will happen on click. */
:where(html[data-page="settings"]) #panelRef tbody tr.ref-open {
  cursor: pointer;
}
:where(html[data-page="settings"]) #panelRef tbody tr.ref-open:hover {
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}
:where(html[data-page="settings"]) .ref-blank {
  color: var(--text-muted);
}
/* [Item 52] The substitutable part of a template setting. --accent and NOT
   --error: a slot is not a fault, and rule 2 of the non-negotiables keeps
   the semantic colours for meaning. Emphasis is exactly what --accent is
   for. Monospace and a faint tint so it reads as a token rather than as a
   word somebody happened to bracket.

   The stack is written out because this stylesheet defines no --mono token,
   and it is the Style Guide's stack rather than this file's older
   'DM Mono',... spelling: DM Mono is not in the page's font link and never
   was, so every chip already falls through to exactly these. */
:where(html[data-page="settings"]) .ref-slot {
  font-family: ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 4px;
  padding: 0 4px;
  white-space: nowrap;
}
@media (max-width: 640px) {
  /* A reference table is a grid of FIELDS - every column is a named value and
     none of them is the row's identity. The shared card rule above drops the
     label on the first cell because there it IS the identity (a person's name);
     here it is `Style ID` or `Brand Name`, and without its label the value
     reads as an orphan on the card. */
  :where(html[data-page="settings"]) #panelRef .grid-wrap tbody td:first-child::before {
    content: attr(data-label);
  }
}

/* ---------- page: settings — the row form is a WINDOW, not a page ----------
   `.form-overlay` paints itself with `var(--bg)` across the whole viewport, so
   on a desktop screen it reads as "the page went grey" and there is no visible
   outside — even though tapping outside DOES close it. This gives it the same
   treatment `.sheet-overlay` already gets at this breakpoint (line ~398): the
   page stays visible and dimmed behind, and the form becomes a bounded card.
   Below 768px it is left exactly as it was — full screen is the right shape
   for a thumb, and Style Guide §11 asks for it. */
@media (min-width: 768px) {
  :where(html[data-page="settings"]) .form-overlay {
    background: var(--overlay);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    align-items: center;
    justify-content: center;
    padding: 24px;
  }
  :where(html[data-page="settings"]) .fo-header {
    width: 100%;
    max-width: 440px;
    border: 1px solid var(--border);
    border-bottom: none;
    border-radius: 20px 20px 0 0;
  }
  :where(html[data-page="settings"]) .fo-body {
    flex: 0 1 auto;
    max-height: min(72vh, 660px);
    padding: 24px 22px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-top: none;
    border-radius: 0 0 20px 20px;
  }
}

/* ---------- component: colour field (swatch + hex code) ----------
   A native `input[type=color]` for the palette, sitting beside the text box
   that carries the code. The text box is the field that gets saved; the swatch
   is a way of filling it in. Both are the standard input height so the pair
   reads as one control. */
:where(html[data-page="settings"]) .color-field {
  display: flex;
  align-items: center;
  gap: 10px;
}
:where(html[data-page="settings"]) .color-field .field-input {
  flex: 1;
  font-family: 'DM Sans',sans-serif;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
:where(html[data-page="settings"]) .color-swatch {
  width: 46px;
  height: 46px;
  flex-shrink: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: transparent;
  cursor: pointer;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="settings"]) .color-swatch:hover {
  border-color: var(--accent-hover);
}
:where(html[data-page="settings"]) .color-swatch:disabled {
  border-color: var(--disabled-border);
  cursor: not-allowed;
  opacity: 0.6;
}
/* The browser wraps the colour in two shadow elements of its own; without this
   the swatch shows as a small square floating inside a grey box. */
:where(html[data-page="settings"]) .color-swatch::-webkit-color-swatch-wrapper {
  padding: 3px;
}
:where(html[data-page="settings"]) .color-swatch::-webkit-color-swatch {
  border: none;
  border-radius: 5px;
}
:where(html[data-page="settings"]) .color-swatch::-moz-color-swatch {
  border: none;
  border-radius: 5px;
}

/* ---------- shared by dashboard / scanner / transfer / settings ---------- */
/* 🔴 A SHEET SHORTER THAN ITS OWN max-height HAS NOTHING TO SCROLL, so the
   wheel travels straight past it to the page underneath and the list behind
   the popup moves instead. That is what happened on Manage Role: six roles
   never reach the 92vh ceiling, so the sheet is not a scrolling thing at all
   and every scroll went to the Users table behind it.

   The bug has two halves and needs both rules:
     · the page itself is frozen for as long as any overlay is open, which
       covers the backdrop and every sheet too short to scroll;
     · `overscroll-behavior: contain` stops a sheet that IS long enough from
       handing the scroll onward once it reaches its own end.

   `overflow: hidden` on the root keeps the scroll offset, so the page is
   exactly where it was when the overlay closes - a lock that scrolls the page
   to the top on open is a worse bug than the one being fixed. */
html:where([data-shell="app"]):has(.sheet-overlay.open, .form-overlay.open, .confirm-overlay.open, .modal-overlay.open, .detail-overlay.open, .side-menu-drawer.open) {
  overflow: hidden;
}

/* Inert on anything that is not a scroll container, so this is safe to state
   once for every panel that can scroll rather than hunting them one by one. */
:where(html[data-shell="app"]) .sheet,
:where(html[data-shell="app"]) .sheet-list,
:where(html[data-shell="app"]) .fo-body,
:where(html[data-shell="app"]) .perm-options,
:where(html[data-shell="app"]) .side-menu-drawer {
  overscroll-behavior: contain;
}

/* ---------- page: settings — the role chip's colour (20 Aug 2026) ---------- */
/* 🔴 A ROLE'S COLOUR IS STORED, NOT WRITTEN HERE. It used to be a CSS class per
   role NAME, which by definition could only ever colour the names that existed
   the day the stylesheet was written: 'Branch Manager' and 'Sales' had gone
   uncoloured since the day they were created and nothing said why. The colour
   now comes from `roles.color` and arrives as an inline --role-color on the
   chip itself.

   🔴 THE TEXT COLOUR IS MIXED TOWARD --text, NOT USED RAW. One stored hex has
   to sit on a near-black page AND a near-white one, and a hex that reads well
   on either is close to invisible on the other. Mixing 70% of the chosen
   colour with the theme's own text colour keeps the hue recognisable while the
   contrast follows the theme. The 10% / 20% fills are the exact values the
   four hardcoded roles used, so those four look as they always did.

   The neutral .role-tag base above still applies to any role with no colour;
   this rule only engages when the chip carries data-colored, which the page
   only writes for a complete #rrggbb. */
:where(html[data-page="settings"]) .role-tag[data-colored] {
  color: color-mix(in srgb, var(--role-color) 70%, var(--text));
  background: color-mix(in srgb, var(--role-color) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--role-color) 20%, transparent);
}

/* The swatch beside a role in the Manage Role sheet. A role with no colour set
   shows the neutral ring rather than a black dot — "not set" is not a colour,
   and drawing it as one would be a lie about what is stored. */
:where(html[data-page="settings"]) .role-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1px solid var(--border);
  background: var(--hover-bg);
}
:where(html[data-page="settings"]) .role-dot[data-colored] {
  background: var(--role-color);
  border-color: color-mix(in srgb, var(--role-color) 45%, transparent);
}

/* ---------- page: settings — the Refresh control in a form header ---------- */
/* It sits beside the close button rather than under either list, because one
   press refreshes BOTH the Odoo lists at once. `margin-left:auto` is what puts
   it there: the header is `justify-content: space-between`, so a third child
   would otherwise be spread to the middle instead of grouped with the close
   control on the right. */
:where(html[data-page="settings"]) .fo-refresh {
  margin-left: auto;
  margin-right: 10px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 34px;
  padding: 0 12px;
  border: 1px solid rgba(213,169,153,0.3);
  background: rgba(213,169,153,0.06);
  color: var(--accent);
  border-radius: var(--radius-sm);
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color var(--duration-fast) ease, background var(--duration-fast) ease;
}
:where(html[data-page="settings"]) .fo-refresh:hover:not(:disabled) {
  border-color: rgba(213,169,153,0.5);
  background: rgba(213,169,153,0.12);
}
:where(html[data-page="settings"]) .fo-refresh:disabled {
  color: var(--text-disabled);
  border-color: var(--disabled-border);
  background: var(--disabled-bg);
  cursor: not-allowed;
}
/* On a narrow screen the title, the button and the close control share one
   line; dropping the word keeps the icon reachable without wrapping. */
@media (max-width: 420px) {
  :where(html[data-page="settings"]) .fo-refresh {
    padding: 0 10px;
    margin-right: 6px;
  }
  :where(html[data-page="settings"]) .fo-refresh span {
    display: none;
  }
}

/* ---------- page: transfer — the Stocktake tab (Item 9 · Decision 657) ----------
   Every value here is taken from the tokens and from the components this file
   already defines. The checkbox is `.ms-box`, unchanged and un-copied; only the
   rows around it are new, because `.ms-option`'s own rules (the hidden input,
   the checked state) are scoped to `.ms-option` and do not reach a new label. */
:where(html[data-page="transfer"]) .tab-panel {
  display: flex;
  flex-direction: column;
  gap: 26px;
}
:where(html[data-page="transfer"]) .tab-panel[hidden] {
  display: none;
}

/* --- how the work is divided --- */
:where(html[data-page="transfer"]) .stk-modes {
  display: flex;
  gap: 10px;
}
:where(html[data-page="transfer"]) .stk-mode {
  flex: 1;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color var(--duration-base) ease, background var(--duration-base) ease;
}
:where(html[data-page="transfer"]) .stk-mode input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
:where(html[data-page="transfer"]) .stk-mode .ms-box {
  border-radius: 50%;
  margin-top: 2px;
}
:where(html[data-page="transfer"]) .stk-mode.checked {
  border-color: var(--accent);
}
:where(html[data-page="transfer"]) .stk-mode.checked .ms-box {
  background: var(--accent);
  border-color: var(--accent);
}
:where(html[data-page="transfer"]) .stk-mode.checked .ms-box svg {
  opacity: 1;
  transform: scale(1);
}
:where(html[data-page="transfer"]) .stk-mode-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: 'DM Sans',sans-serif;
}
:where(html[data-page="transfer"]) .stk-mode-text b {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="transfer"]) .stk-mode-text span {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.5;
}

/* --- the style picker --- */
:where(html[data-page="transfer"]) .stk-picker {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
:where(html[data-page="transfer"]) .stk-tools {
  display: flex;
  gap: 10px;
  align-items: center;
}
:where(html[data-page="transfer"]) .stk-search {
  flex: 1;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 14px;
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  color: var(--text);
  outline: none;
  transition: border-color var(--duration-base) ease;
}
:where(html[data-page="transfer"]) .stk-search:focus {
  border-color: var(--accent);
}
:where(html[data-page="transfer"]) .stk-search::placeholder {
  color: var(--text-placeholder);
}
:where(html[data-page="transfer"]) .stk-zone-wrap {
  width: 150px;
  flex-shrink: 0;
}
:where(html[data-page="transfer"]) .stk-selectall {
  flex-shrink: 0;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 16px;
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  transition: border-color var(--duration-base) ease, background var(--duration-base) ease;
}
:where(html[data-page="transfer"]) .stk-selectall:hover:not(:disabled) {
  border-color: var(--accent-hover);
  background: var(--hover-bg);
}
:where(html[data-page="transfer"]) .stk-selectall:disabled {
  color: var(--text-disabled);
  border-color: var(--disabled-border);
  cursor: not-allowed;
}

:where(html[data-page="transfer"]) .stk-list {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  max-height: 380px;
  overflow-y: auto;
  padding: 6px;
}
:where(html[data-page="transfer"]) .stk-row {
  display: flex;
  align-items: center;
  gap: 8px;
  border-radius: 7px;
  transition: background var(--duration-fast) ease;
}
:where(html[data-page="transfer"]) .stk-row:hover {
  background: var(--hover-bg);
}
:where(html[data-page="transfer"]) .stk-row-main {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  cursor: pointer;
  font-family: 'DM Sans',sans-serif;
  font-size: 13px;
  color: var(--text);
}
:where(html[data-page="transfer"]) .stk-row input,
:where(html[data-page="transfer"]) .stk-design-head input,
:where(html[data-page="transfer"]) .stk-size input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
:where(html[data-page="transfer"]) .stk-row.checked .ms-box,
:where(html[data-page="transfer"]) .stk-design-head.checked .ms-box,
:where(html[data-page="transfer"]) .stk-size.checked .ms-box {
  background: var(--accent);
  border-color: var(--accent);
}
:where(html[data-page="transfer"]) .stk-row.checked .ms-box svg,
:where(html[data-page="transfer"]) .stk-design-head.checked .ms-box svg,
:where(html[data-page="transfer"]) .stk-size.checked .ms-box svg {
  opacity: 1;
  transform: scale(1);
}
/* The partial mark. 🟢 The same idea as `settings.html`'s permission tree: a
   parent that is neither empty nor full shows a bar, never a tick, so "some of
   this" can never be misread as "all of this". */
:where(html[data-page="transfer"]) .stk-row.partial .ms-box,
:where(html[data-page="transfer"]) .stk-design-head.partial .ms-box {
  border-color: var(--accent);
  position: relative;
}
:where(html[data-page="transfer"]) .stk-row.partial .ms-box::after,
:where(html[data-page="transfer"]) .stk-design-head.partial .ms-box::after {
  content: '';
  /* 🔴 Out of the flow, or it queues beside the tick. The tick is invisible
     while the row is partial but it is still laid out, and 11px + 9px does not
     fit in an 18px box - which is what pushed the bar off centre. */
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 9px;
  height: 2px;
  border-radius: 1px;
  background: var(--accent);
}
:where(html[data-page="transfer"]) .stk-row-name {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="transfer"]) .stk-row-zone {
  flex: 1;
  font-size: 11px;
  color: var(--text-muted);
}
:where(html[data-page="transfer"]) .stk-row-count {
  flex-shrink: 0;
  font-size: 11px;
  color: var(--text-muted);
}
:where(html[data-page="transfer"]) .stk-customise {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 10px 12px;
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  white-space: nowrap;
}
:where(html[data-page="transfer"]) .stk-customise:hover {
  color: var(--accent-hover);
}

/* --- the chips: a partial selection can never hide --- */
:where(html[data-page="transfer"]) .stk-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
:where(html[data-page="transfer"]) .stk-chip {
  display: inline-flex;
  align-items: stretch;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
:where(html[data-page="transfer"]) .stk-chip-label {
  background: none;
  border: none;
  padding: 6px 4px 6px 10px;
  font-family: 'DM Sans',sans-serif;
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
:where(html[data-page="transfer"]) .stk-chip-x {
  background: none;
  border: none;
  padding: 6px 10px 6px 6px;
  font-size: 14px;
  line-height: 1;
  color: var(--accent);
  cursor: pointer;
}
:where(html[data-page="transfer"]) .stk-chip-label:hover,
:where(html[data-page="transfer"]) .stk-chip-x:hover {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
}

/* --- the open room --- */
:where(html[data-page="transfer"]) .stk-openroom {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px 16px;
  background: color-mix(in srgb, var(--info) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--info) 35%, transparent);
  border-radius: var(--radius);
  font-family: 'DM Sans',sans-serif;
}
:where(html[data-page="transfer"]) .stk-openroom b {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
}
:where(html[data-page="transfer"]) .stk-openroom span {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.6;
}

/* 🔴 AN AUTHOR `display` BEATS THE BROWSER'S OWN `[hidden] { display: none }`
   - not on specificity, but because author styles outrank the UA sheet. So
   `el.hidden = true` was being set correctly on both of these and neither
   ever disappeared. The page already had the cure on `.tab-panel[hidden]`;
   these are the only other two, counted rather than remembered. */
:where(html[data-page="transfer"]) .stk-chips[hidden],
:where(html[data-page="transfer"]) .stk-modes[hidden],
:where(html[data-page="transfer"]) .stk-openroom[hidden] {
  display: none;
}

/* --- the Customise sheet --- */
:where(html[data-page="transfer"]) .stk-sheet {
  max-width: 560px;
  /* the corner the ✕ is placed against */
  position: relative;
}
/* The sheet centres its children, so the exit is taken out of the flow and
   pinned instead - in the flow it would sit above the title and push it. */
:where(html[data-page="transfer"]) .stk-sheet-close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 34px;
  height: 34px;
}
:where(html[data-page="transfer"]) .stk-designs {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 46vh;
  overflow-y: auto;
  margin: 4px 0 14px;
  text-align: left;
}
:where(html[data-page="transfer"]) .stk-design {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  /* [V44] THE DEFECT. `overflow` other than visible sets a flex item's
     automatic minimum size to 0, and an item in a column box then shrinks to
     it instead of letting the box scroll. 🔬 Measured in a real browser on
     this stylesheet: a row needing 159px was drawn at 8px, which is why the
     sheet looked empty on a style with many designs. */
  flex-shrink: 0;
}
:where(html[data-page="transfer"]) .stk-design-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--surface2);
  font-family: 'DM Sans',sans-serif;
  font-size: 12px;
  color: var(--text);
}
/* [V44] The head does two different things now, so it carries two targets: the
   label picks the design, the chevron opens it. One control doing both would
   make "let me look inside" indistinguishable from "count all of it". */
:where(html[data-page="transfer"]) .stk-design-pick {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}
:where(html[data-page="transfer"]) .stk-design-toggle {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: none;
  border: none;
  border-radius: 6px;
  color: var(--text-muted);
  cursor: pointer;
  transition: background var(--duration-fast) ease, color var(--duration-fast) ease;
}
:where(html[data-page="transfer"]) .stk-design-toggle:hover {
  background: var(--hover-bg);
  color: var(--text);
}
:where(html[data-page="transfer"]) .stk-design-toggle svg {
  width: 16px;
  height: 16px;
  transition: transform var(--duration-base) var(--ease);
}
:where(html[data-page="transfer"]) .stk-design-toggle.is-open svg {
  transform: rotate(180deg);
}
/* 🔴 The sheet is a column flex box with `align-items: center`, so a child is
   as wide as its CONTENT unless it says otherwise. Collapsed rows are short,
   which made the whole list sit in a narrow ribbon down the middle of a 560px
   sheet and clipped the search placeholder. Both stretch. */
:where(html[data-page="transfer"]) .stk-cust-tools,
:where(html[data-page="transfer"]) .stk-designs {
  align-self: stretch;
}
:where(html[data-page="transfer"]) .stk-cust-tools {
  margin: 10px 0 4px;
}
:where(html[data-page="transfer"]) .stk-design-name {
  flex: 1;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="transfer"]) .stk-design-count {
  flex-shrink: 0;
  font-size: 11px;
  color: var(--text-muted);
}
:where(html[data-page="transfer"]) .stk-sizes {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 8px;
}
:where(html[data-page="transfer"]) .stk-size {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 7px;
  cursor: pointer;
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  font-size: 11px;
  color: var(--text-muted);
  transition: background var(--duration-fast) ease, border-color var(--duration-fast) ease, color var(--duration-fast) ease;
}
/* A counted size is filled and readable; an uncounted one is an outline. The
   difference has to survive being read at arm's length. */
:where(html[data-page="transfer"]) .stk-size.checked {
  border-color: var(--accent);
  background: var(--surface2);
  color: var(--text);
}
:where(html[data-page="transfer"]) .stk-size:hover {
  background: var(--hover-bg);
}
:where(html[data-page="transfer"]) .stk-size-name {
  white-space: nowrap;
}

@media (max-width: 640px) {
  :where(html[data-page="transfer"]) .stk-modes,
  :where(html[data-page="transfer"]) .stk-tools {
    flex-direction: column;
    align-items: stretch;
  }
  :where(html[data-page="transfer"]) .stk-zone-wrap {
    width: 100%;
  }
  :where(html[data-page="transfer"]) .stk-row-zone {
    display: none;
  }
}

/* ===== [Item 9 · Decisions 677 · 689] SCANNER — the stocktake list =====
   One row per DESIGN, its sizes beneath. Built on `.sku-row` rather than
   beside it, so the padding, the border, the dot colours and the dragging and
   done/notfound states are the SAME component the transfer list uses — a
   stocktake is a mode of this screen, not a second screen (689). */
:where(html[data-page="scanner"]) .sku-row.stk-grp {
  padding: 0;
}
:where(html[data-page="scanner"]) .stk-grp-head {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  min-height: 44px;
  background: transparent;
  border: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
:where(html[data-page="scanner"]) .stk-grp-head:active {
  background: var(--hover-bg);
}
:where(html[data-page="scanner"]) .stk-chev {
  flex-shrink: 0;
  width: 12px;
  text-align: center;
  font-size: 18px;
  line-height: 1;
  color: var(--text-muted);
  transition: transform var(--duration-fast) ease;
}
:where(html[data-page="scanner"]) .stk-chev.open {
  transform: rotate(90deg);
}
:where(html[data-page="scanner"]) .stk-grp-name {
  flex: 1;
  min-width: 0;
  font-family: 'DM Sans',sans-serif;
  font-weight: 500;
  font-size: 14px;
  color: var(--text);
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="scanner"]) .stk-grp-total {
  flex-shrink: 0;
  min-width: 34px;
  text-align: right;
  font-family: 'DM Sans',sans-serif;
  font-weight: 700;
  font-size: 16px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
:where(html[data-page="scanner"]) .sku-row.stk-grp.partial .stk-grp-total {
  color: var(--warning);
}
:where(html[data-page="scanner"]) .sku-row.stk-size-row {
  padding-left: 42px;
  background: var(--surface2);
}
:where(html[data-page="scanner"]) .stk-size-label {
  flex: 1;
  min-width: 0;
  font-family: 'DM Sans',sans-serif;
  font-weight: 400;
  font-size: 13px;
  color: var(--text-muted);
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
:where(html[data-page="scanner"]) .stk-size-row.counted .stk-size-label {
  color: var(--text);
  font-weight: 500;
}
:where(html[data-page="scanner"]) .stk-size-row.counted .sku-count {
  color: var(--warning);
  border-color: color-mix(in srgb, var(--warning) 40%, var(--border));
}

/* ==========================================================================
   [Item 77] LAST IN THE FILE, ON PURPOSE - DO NOT MOVE THIS BLOCK UP.
   Page rules give :disabled their own opacity at the SAME specificity
   (.big-btn 0.35, .create-btn 0.35, .save-mini 0.5, .odoo-import-btn 0.55),
   so whichever comes last wins. In V48, when this block sat higher, the
   confirm sheet's Yes button rendered at 0.35. Being last - plus !important on
   opacity, measured necessary on the login page - is what makes every waiting
   button fade by the same amount on all five pages.
   NO data-page prefix, deliberately: this is the one component that must look
   the same everywhere (Item 72).
   ========================================================================== */
/* [Item 77 - Mustafa, 2026-09-13] PATTERN A: THE WORDS STAY.
   A waiting button keeps its words; the spinner takes the leading icon's place,
   or sits just before the words when there is no icon. setBtnLoading in
   common.js locks the button's size, hides the icon (keeping its space) and
   writes where the spinner goes into --wss-spin-x / --wss-spin-y. Without those
   the spinner falls back to the centre.
   The spinner is drawn in currentColor. V48's pattern hid the words by making
   the text transparent, so the spinner could not inherit and needed a hand-kept
   list of accent-filled classes (1.80:1 and 1.12:1 were measured before that
   list existed). The words are visible now, so the spinner in the same ink is
   exactly as legible as the words on every surface and in both themes. */
.is-loading {
  pointer-events: none;
  cursor: default;
  opacity: 0.65 !important;
  transition: none !important;
}
.is-loading::after {
  content: "";
  position: absolute;
  left: var(--wss-spin-x, 50%);
  top: var(--wss-spin-y, 50%);
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  box-sizing: border-box;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  pointer-events: none;
  animation: spin 0.7s linear infinite;
}
/* visibility, not display: the icon keeps its space, so nothing moves. */
.wss-icon-hidden {
  visibility: hidden !important;
}
