/* Shared components (Living Blueprint) (Review/2026-10-03/ui-deep-dive BRIEF.md 2.6-2.11): every value is a token from wms-tokens.css.
   Linked at the end of every page's <head> (after the page's own styles), so a component class wins over a page's bare element
   rules (button, input …); the two global fixes at the top use :where() and so never outrank a page rule.
   Behaviour (toasts, the confirm/prompt dialog, the background "still" switch) is static/wms-ui.js. */

/* ---------- global contrast fixes (zero specificity) ---------- */
/* Field borders: every field drawn with the hairline token gets the field token instead (3:1 for UI, WCAG 1.4.11); a custom
   property set on the field itself is what its own border reads, so transparent or other borders stay as they are. */
:where(input:not([type=checkbox],[type=radio],[type=range],[type=color],[type=file],[type=button],[type=submit],[type=reset],[type=image],[type=hidden]),select,textarea) {
  --line:var(--line-field); }
/* Placeholders: never the browser's grey (2.35:1); never mistaken for a value. */
:where(input,textarea)::placeholder { color:var(--text-faint); opacity:1; }
.wms-sr { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
/* Phones turned: iPhone Safari would enlarge the text, so the page laid out for the type scale no longer fits (as terms.html). */
html { -webkit-text-size-adjust:100%; text-size-adjust:100%; }

/* ---------- buttons (2.11) ---------- */
.wms-btn { position:relative; display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-2); min-height:var(--btn-h);
  margin:0; padding:0 var(--sp-4); border:1px solid var(--line-field); border-radius:var(--r-0); background:transparent; color:var(--text);
  font:600 var(--fs-body)/1.2 var(--fb); letter-spacing:0; text-transform:none; text-decoration:none; white-space:nowrap; cursor:pointer;
  overflow:hidden; touch-action:manipulation; -webkit-tap-highlight-color:transparent;
  transition:background-color var(--dur-out) ease,border-color var(--dur-out) ease,color var(--dur-out) ease,translate var(--dur-press) var(--ease-out); }
@media (hover:hover) and (pointer:fine) {
  .wms-btn:hover { background:var(--hov); border-color:var(--blue); transition-duration:0s,0s,0s,var(--dur-press); } }
.wms-btn:active:not(:disabled,[aria-disabled="true"]) { translate:0 1px; }
.wms-btn:focus-visible { outline:var(--focus-ring); outline-offset:var(--focus-offset); }
.wms-btn-primary { background:var(--blue); border-color:var(--blue); color:var(--onblue); box-shadow:var(--key); }
@media (hover:hover) and (pointer:fine) { .wms-btn-primary:hover { background:var(--blue-hi); border-color:var(--blue-hi); } }
.wms-btn-primary:active:not(:disabled,[aria-disabled="true"]) { box-shadow:var(--key-pressed); }
.wms-btn-ghost { border-color:transparent; color:var(--dim); }
@media (hover:hover) and (pointer:fine) { .wms-btn-ghost:hover { color:var(--text); border-color:transparent; } }
.wms-btn-danger { background:var(--danger-fill); border-color:var(--danger-fill); color:var(--on-danger); box-shadow:var(--key); }
@media (hover:hover) and (pointer:fine) { .wms-btn-danger:hover { background:var(--danger-fill); border-color:var(--danger); } }
.wms-btn-danger-ghost { border-color:var(--danger); color:var(--danger); }
.wms-btn-hero { min-height:var(--touch-primary); font:600 15px/1 var(--fh); letter-spacing:.1em; text-transform:uppercase; }
.wms-btn-compact { min-height:var(--btn-h-compact); padding:0 var(--sp-3); font-size:var(--fs-small); }
/* Disabled: a dashed outline and the faint label, never 45 % opacity; say why next to it (aria-describedby). */
.wms-btn:disabled, .wms-btn[aria-disabled="true"] { background:transparent; border-color:var(--line-field); border-style:dashed;
  color:var(--text-faint); box-shadow:none; cursor:not-allowed; opacity:1; }
/* Busy: the label says what is happening ("Signing in…"); the key keeps its colour; a 2 px bar runs along the bottom edge. */
.wms-btn[aria-busy="true"] { cursor:progress; }
.wms-btn[aria-busy="true"]::after { content:""; position:absolute; left:0; right:0; bottom:0; height:2px; background:currentColor;
  opacity:.7; transform-origin:left; animation:wms-busy var(--dur-busy) var(--ease-in-out) infinite; }
@keyframes wms-busy { 0% { transform:scaleX(0); } 60% { transform:scaleX(1); opacity:.7; } 100% { transform:scaleX(1); opacity:0; } }
@media (pointer:coarse), (max-width:849px) { .wms-btn { min-height:var(--touch); } .wms-btn-primary, .wms-btn-hero { min-height:var(--touch-primary); } }

/* ---------- fields (2.11) ---------- */
.wms-stack { display:flex; flex-direction:column; gap:var(--sp-4); }   /* fields in a column; grids use their own gap */
.wms-field { display:flex; flex-direction:column; gap:6px; min-width:0; margin:0; }
.wms-label { display:block; margin:0; font:600 var(--fs-caption)/1.3 var(--fb); letter-spacing:var(--track-caption); text-transform:uppercase; color:var(--dim); }
.wms-help { margin:0; font-size:var(--fs-small); line-height:1.45; color:var(--dim); }
.wms-input { box-sizing:border-box; width:100%; min-height:var(--field-h); margin:0; padding:0 var(--sp-3); border:1px solid var(--line-field);
  border-radius:var(--r-0); background:var(--panel2); color:var(--text); font:400 var(--fs-body)/1.4 var(--fb); letter-spacing:0; text-transform:none; }
textarea.wms-input { padding:var(--sp-2) var(--sp-3); }
.wms-input:focus { outline:none; border-color:var(--blue); box-shadow:inset 0 0 0 1px var(--blue); }
.wms-input:focus-visible { outline:var(--focus-ring); outline-offset:var(--focus-offset); }
.wms-input[aria-invalid="true"] { border-color:var(--danger); box-shadow:0 0 0 1px var(--danger); }
/* every one-line select on every page: a chevron drawn from the tokens, never the browser's grey arrow (review look: Stock, Locations,
   Item Sheet, Stats, Set Builder and Settings still had it). Specificity 0,1,1 on purpose: it outranks a page's bare `select` or
   `input, select` rule (their background colour and padding stay theirs); a page rule that styles a select by id or by a longer
   selector sets background-color (not the background shorthand) and leaves room on the right (padding-right: --sp-8). */
select:not([multiple],[size]), input.wms-pick-input { padding-right:var(--sp-8); appearance:none; -webkit-appearance:none; cursor:pointer; text-overflow:ellipsis;
  background-image:linear-gradient(45deg,transparent 50%,var(--dim) 50%),linear-gradient(135deg,var(--dim) 50%,transparent 50%);
  background-position:calc(100% - 17px) 50%,calc(100% - 12px) 50%; background-size:5px 5px; background-repeat:no-repeat; }
select.wms-input { padding-right:var(--sp-8); }
/* a searchable item field (WMS.itemPicker, wms-ui.js): the page's own text field with the select chevron, over its <select>, which stays
   in place unseen (its value, checks and focus); the list is fixed over the page or the window (no scroll box clips it, it covers the
   window's footer), drawn as the Vendor list (inventory.css .inv-combo-list): rows of photo, name, SKU in the mono face and the window's
   own number; the highlighted row in the accent with the section's bar, actions (+ New item…, Leave out) in blue under a rule, the count note under the list */
.wms-pick { position:relative; display:block; min-width:0; }
input.wms-pick-input { width:100%; cursor:text; }
/* touch screens: 16 px at least, or iPhone Safari zooms into the field on focus and stays zoomed (a floor, as the reduced-motion overrides) */
@media (pointer:coarse) { input.wms-pick-input { font-size:max(var(--fs-body-l),1em) !important; } }
.wms-pick > .wms-pick-native { position:absolute; inset:0; width:100%; height:100%; margin:0; opacity:0; pointer-events:none; }
.wms-pick-pop { position:fixed; z-index:var(--z-pop); display:flex; flex-direction:column; box-sizing:border-box; margin:0; padding:0;
  border:1px solid var(--line-field); border-radius:var(--r-0); background:var(--surface-2); box-shadow:var(--elev-3); color:var(--text);
  font:400 var(--fs-body)/1.4 var(--fb); letter-spacing:0; text-align:left; text-transform:none; }
.wms-pick-list { position:relative; flex:0 1 auto; min-height:0; margin:0; padding:0; list-style:none; overflow-y:auto; overscroll-behavior:contain;
  scrollbar-width:thin; scrollbar-color:var(--scroll-thumb) transparent; }
.wms-pick-opt { display:flex; align-items:center; gap:var(--sp-3); min-height:var(--btn-h); margin:0; padding:var(--sp-1) var(--sp-3); cursor:pointer; }
/* an action (+ New item…, Leave out) stays in sight at the list's foot while the matches scroll above it */
.wms-pick-opt.is-action { position:sticky; bottom:0; background:var(--surface-2); color:var(--blue); font-weight:600; }
.wms-pick-opt[aria-selected="true"] { background:var(--accent-bg); box-shadow:inset 2px 0 0 var(--section); }   /* the current-row bar */
@media (hover:hover) and (pointer:fine) { .wms-pick-opt:not([aria-selected="true"]):hover { background:var(--hov); } }
@media (pointer:coarse) { .wms-pick-opt { min-height:var(--touch); } }
.wms-pick-text { display:flex; flex-direction:column; flex:1; min-width:0; overflow-wrap:anywhere; }
.wms-pick-name { font-weight:500; }
.wms-pick-sku { font:400 var(--fs-mono)/1.3 var(--mono); color:var(--dim); }
.wms-pick-meta { flex:none; margin-left:auto; font-size:var(--fs-small); font-variant-numeric:tabular-nums; white-space:nowrap; color:var(--dim); }
.wms-pick-opt:not(.is-action) + .is-action { border-top:1px solid var(--line); }
.wms-pick-note { margin:0; padding:var(--sp-2) var(--sp-3); border-top:1px solid var(--hair); font-size:var(--fs-small); color:var(--dim); }
.wms-pick-note:empty { display:none; }
@media (prefers-reduced-motion:no-preference) {
  .wms-pick-pop { transition:opacity var(--dur-fast) var(--ease-out); }
  @starting-style { .wms-pick-pop { opacity:0; } }
}
/* why a key or a control is off: a dim line with an (i), linked by aria-describedby (brief 2.11; Labels' Print keys and Settings) */
.wms-why { display:flex; align-items:flex-start; gap:6px; margin:0; font-size:var(--fs-small); line-height:1.45; color:var(--dim); }
.wms-why:empty { display:none; }
.wms-why::before { content:"i" / ""; flex:none; display:grid; place-items:center; width:16px; height:16px; margin-top:1px; border:1px solid currentColor;
  border-radius:var(--r-dot); font:600 var(--fs-caption)/1 var(--fb); }
.wms-field-error { display:flex; align-items:flex-start; gap:6px; margin:0; font-size:var(--fs-small); line-height:1.45; color:var(--danger); }
.wms-field-error:empty { display:none; }
.wms-field-error::before { content:"!" / ""; flex:none; display:grid; place-items:center; width:16px; height:16px; margin-top:1px; border-radius:var(--r-dot);
  background:var(--danger); color:var(--panel); font:700 var(--fs-caption)/1 var(--fb); }
.wms-check { display:flex; align-items:center; gap:var(--sp-3); min-height:var(--touch); margin:0; cursor:pointer;
  font:400 var(--fs-body)/1.4 var(--fb); letter-spacing:0; text-transform:none; color:var(--text); }
.wms-check input { width:20px; height:20px; margin:0; flex:none; accent-color:var(--blue); }
@media (pointer:coarse) { .wms-input { min-height:var(--touch); font-size:var(--fs-body-l); } }

/* ---------- cards and the blueprint corner marks (2.5: crosses on hero and section frames only) ---------- */
.wms-card { position:relative; padding:var(--sp-6); border:1px solid var(--line); background:var(--surface-1); box-shadow:var(--e1); }
.wms-marked::before, .wms-marked::after { content:""; position:absolute; left:-6px; right:-6px; height:11px; pointer-events:none;
  background-image:var(--plus),var(--plus); background-repeat:no-repeat; background-position:left top,right top; }
.wms-marked::before { top:-6px; }
.wms-marked::after { bottom:-6px; }

/* the 2 px blue rule a sheet card is drafted with (sign-in, Admin PIN): it draws in once from the left */
.wms-card-rule { position:absolute; left:-1px; right:-1px; top:-1px; height:2px; background:var(--blue); transform-origin:left;
  animation:wms-rule-in var(--dur-rule) var(--ease-out) both; }
@keyframes wms-rule-in { from { transform:scaleX(0); } }

/* ---------- pills, chips, dots (2.11) ---------- */
.wms-pill { display:inline-flex; align-items:center; gap:6px; min-height:24px; padding:0 9px; font:600 var(--fs-caption)/1 var(--fb); white-space:nowrap;
  background:color-mix(in srgb,var(--text) 7%,transparent); color:var(--dim); }
.wms-pill::before { content:""; width:6px; height:6px; border-radius:var(--r-dot); background:currentColor; flex:none; }
.wms-pill.ok { background:var(--ok-bg); color:var(--success); }
.wms-pill.warn { background:var(--warn-bg); color:var(--warning); }
.wms-pill.bad { background:var(--bad-bg); color:var(--danger); }
.wms-pill.info { background:var(--accent-bg); color:var(--info); }
.wms-chip { display:inline-flex; align-items:center; gap:var(--sp-2); min-height:32px; padding:0 var(--sp-3); border:1px solid var(--line);
  background:transparent; color:var(--dim); font:400 var(--fs-small)/1 var(--fb); white-space:nowrap; }
.wms-chip b { font-weight:600; color:var(--text); }
button.wms-chip { cursor:pointer; }
.wms-chip[aria-pressed="true"] { background:var(--accent-bg); border-color:var(--blue); color:var(--text); }
.wms-dot { display:inline-block; width:8px; height:8px; border-radius:var(--r-dot); background:currentColor; flex:none; }

/* ---------- page header parts (2.11: crumb · title · sync chip · actions · station · initials) ---------- */
.wms-crumb { font:600 var(--fs-caption)/1 var(--fb); letter-spacing:var(--track-caption); text-transform:uppercase; color:var(--section); }
.wms-crumb span { color:var(--dim); }
.wms-sync { min-width:0; max-width:100%; color:var(--dim); }
.wms-sync > :not(.wms-dot, button) { min-width:0; overflow:hidden; text-overflow:ellipsis; }   /* a narrow header shortens the words */
.wms-sync > button { flex:none; }
.wms-sync .wms-dot { color:var(--success); }
.wms-sync[data-state="busy"] .wms-dot { color:var(--info); }
.wms-sync[data-state="stale"] { color:var(--warning); border-color:color-mix(in srgb,var(--warning) 50%,var(--line)); background:var(--warn-bg); }
/* the page's own header actions (its sync chip, Refresh, its + key), right of the title, ruled off from the station and initials
   (one place on every page that has them: Inventory, Today's Surprise Sets, the Calendar; stage-2 review) */
.wms-head-actions { display:flex; align-items:center; gap:var(--sp-3); margin-left:auto; min-width:0; }
.wms-head-actions::after { content:""; flex:none; width:1px; height:24px; margin-left:var(--sp-1); background:var(--line); }
/* phones: the page's keys have a line of their own (the station chip is in the Account window), so the divider separates nothing (B2-6) */
@media (max-width:600px) { .wms-head-actions::after { display:none; } }
.wms-head-actions .wms-sync { min-height:40px; }
.wms-sync[data-state="stale"] .wms-dot { color:var(--warning); }
/* phones: the sync chip shows only when the page could not refresh (every page; the time it would show does not fit a phone header) */
@media (max-width:600px) { .wms-sync:not([data-state="stale"]) { display:none; } }
.wms-avatar { display:inline-grid; place-items:center; width:40px; height:40px; flex:none; padding:0; border:1px solid var(--line-field);
  border-radius:var(--r-0); background:var(--panel2); color:var(--text); font:600 15px/1 var(--fh); letter-spacing:.06em; cursor:pointer; }
@media (pointer:coarse) { .wms-avatar { width:var(--touch); height:var(--touch); } }

/* ---------- progress (2.11): a 4 px track, the fill scales (transform) over --dur-count ---------- */
.wms-progress { position:relative; height:4px; overflow:hidden; background:color-mix(in srgb,var(--text) 12%,transparent); }
.wms-progress > i { position:absolute; inset:0; transform-origin:left; transform:scaleX(var(--p,0)); background:var(--info);
  transition:transform var(--dur-count) var(--ease-out); }
.wms-progress.ok > i { background:var(--success); }

/* ---------- loading (2.11): skeleton blocks with the final geometry; shown after 300 ms, a calm .6-1 pulse ---------- */
.wms-skel { display:inline-block; width:var(--w,100%); max-width:100%; height:var(--h,1em); vertical-align:middle; border-radius:var(--r-0);
  background:color-mix(in srgb,var(--text) 10%,transparent);
  animation:wms-skel-in 0s linear var(--skel-delay) both,wms-skel-pulse var(--dur-highlight) var(--ease-in-out) var(--skel-delay) infinite alternate; }
@keyframes wms-skel-in { from { visibility:hidden; } }
@keyframes wms-skel-pulse { from { opacity:1; } to { opacity:.6; } }

/* ---------- toasts (2.11): bottom-right, at most 3, rise 8 px and fade in ---------- */
.wms-toasts { position:fixed; right:calc(var(--gutter) + var(--safe-right)); bottom:calc(var(--gutter) + var(--wms-dock));   /* above the phone tab bar */ z-index:var(--z-toast); display:flex; flex-direction:column; align-items:flex-end;
  gap:var(--sp-2); width:min(420px,calc(100vw - 2 * var(--gutter))); pointer-events:none; }
.wms-toast { display:flex; align-items:flex-start; gap:var(--sp-3); width:100%; padding:var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4);
  border:1px solid var(--line); border-left:3px solid var(--success); background:var(--panel2); color:var(--text); box-shadow:var(--elev-3);
  font:400 var(--fs-body)/1.45 var(--fb); pointer-events:auto;
  transition:opacity var(--dur-base) var(--ease-out),translate var(--dur-base) var(--ease-out); }
@starting-style { .wms-toast { opacity:0; translate:0 8px; } }
.wms-toast.is-info { border-left-color:var(--info); }
.wms-toast.is-error { border-left-color:var(--danger); }
.wms-toast.is-leaving { opacity:0; translate:0 8px; }
.wms-toast-text { flex:1; min-width:0; padding-top:5px; overflow-wrap:anywhere; }
.wms-toast .wms-btn { flex:none; }
.wms-toast-x { min-height:32px; width:32px; padding:0; font-size:18px; }
@media (pointer:coarse) { .wms-toast-x { width:var(--touch); min-height:var(--touch); } }
@media (max-width:600px) { .wms-toasts { left:var(--gutter); right:var(--gutter); width:auto; align-items:stretch; } }

/* ---------- dialog (2.11): S/M/L, anchored at 8vh so it never re-centres as it grows ---------- */
dialog.wms-dialog { box-sizing:border-box; width:min(var(--dialog-s),calc(var(--safe-width) - 2 * var(--sp-4))); max-height:calc(100dvh - 16vh); margin:8vh auto auto;
  padding:0; border:1px solid var(--line); border-radius:var(--r-0); background:var(--panel); color:var(--text); box-shadow:var(--elev-3);
  font:400 var(--fs-body)/1.5 var(--fb); }
dialog.wms-dialog[open] { display:flex; flex-direction:column; }
dialog.wms-dialog[data-size="m"] { width:min(var(--dialog-m),calc(var(--safe-width) - 2 * var(--sp-4))); }
dialog.wms-dialog[data-size="l"] { width:min(var(--dialog-l),calc(var(--safe-width) - 2 * var(--sp-4))); }
.wms-dialog-head { display:flex; align-items:center; gap:var(--sp-3); min-height:56px; padding:0 var(--sp-3) 0 var(--sp-6); border-bottom:1px solid var(--line); flex:none; }
.wms-dialog-head h2 { flex:1; margin:0; font:600 var(--fs-h2)/1.1 var(--fh); letter-spacing:var(--track-head-md); text-transform:uppercase; overflow-wrap:anywhere; }
.wms-dialog-head h2:focus { outline:none; }
/* The window's × (owner 2026-10-05: "Please add a square around the X"): ONE square key in every window's header — this dialog, the
   inventory window and its photo view, and every page's own window carry .wms-btn .wms-dialog-x, and no page styles it. The system's
   key: the 1 px field-line border, square corners, the hover and the focus ring; 40 px square, 44 px on touch. Each window names it
   "Close" / "关闭" in the page language. Written for a window (dialog, role="dialog") so it outranks a page's own button rules. */
:is(dialog,[role="dialog"]) .wms-dialog-x { flex:none; width:var(--btn-h); min-width:var(--btn-h); height:var(--btn-h); min-height:var(--btn-h); padding:0;
  border:1px solid var(--line-field); border-radius:var(--r-0); background:transparent; color:var(--text); font:400 var(--fs-h2)/1 var(--fb); }
@media (hover:hover) and (pointer:fine) { :is(dialog,[role="dialog"]) .wms-dialog-x:hover:not(:disabled) { background:var(--hover); border-color:var(--blue); } }
:is(dialog,[role="dialog"]) .wms-dialog-x:focus-visible { outline:var(--focus-ring); outline-offset:var(--focus-offset); }
:is(dialog,[role="dialog"]) .wms-dialog-x:disabled { border-style:dashed; color:var(--text-faint); cursor:not-allowed; }
@media (pointer:coarse) { :is(dialog,[role="dialog"]) .wms-dialog-x { width:var(--touch); min-width:var(--touch); height:var(--touch); min-height:var(--touch); } }
/* basis auto, never flex:1 (a 0% basis): iPhone Safari sizes an auto-height window from that basis and cut the More sheet, Account
   and every confirm to their header (owner 2026-10-14, phone upright). min-height:0 keeps a window taller than the screen scrolling. */
.wms-dialog-body { flex:1 1 auto; min-height:0; overflow-y:auto; padding:var(--sp-5) var(--sp-6); overflow-wrap:anywhere; }
.wms-dialog-body p + p { margin-top:var(--sp-2); }
.wms-dialog-body ul { margin:var(--sp-2) 0 0; padding-left:var(--sp-5); }
.wms-dialog-foot { display:flex; justify-content:flex-end; flex-wrap:wrap; gap:var(--sp-3); padding:var(--sp-4) var(--sp-6); border-top:1px solid var(--line); flex:none; }
@media (max-width:600px) {
  /* the sheet's surface runs under the home indicator; its keys stay above it (every phone sheet does the same) */
  dialog.wms-dialog, dialog.wms-dialog[data-size] { width:100vw; max-width:none; max-height:100dvh; margin:auto 0 0; padding-bottom:var(--safe-bottom); }
  .wms-dialog-foot .wms-btn { flex:1; }
}
/* phones: the sheet rises from the bottom edge and goes back down (--ease-drawer, 280 ms); with reduced motion it only fades
   (navigation.css's shared dialog rule) */
@media (max-width:600px) and (prefers-reduced-motion:no-preference) {
  dialog.wms-dialog { transition-duration:var(--dur-slow); transition-timing-function:var(--ease-drawer); }
  dialog.wms-dialog:not([open]) { opacity:1; translate:0 100%; scale:1; }
  @starting-style { dialog.wms-dialog[open] { opacity:1; translate:0 100%; scale:1; } }
}
:lang(zh) .wms-dialog-head h2, :lang(zh) .wms-label, :lang(zh) .wms-crumb { letter-spacing:0; text-transform:none; }
:lang(zh) .wms-label, :lang(zh) .wms-crumb { font-size:var(--fs-small); }
:lang(zh) .wms-btn-hero { letter-spacing:0; }

/* ---------- shared by every area (moved here from wms-ui-system.css in the stage-2 review: one number strip, one failure line, one empty
   state; Inventory, Surprise Sets and the system pages all use them) ---------- */
.wms-cap { margin:0; font:600 var(--fs-caption)/1.3 var(--fb); letter-spacing:var(--track-caption); text-transform:uppercase; color:var(--dim); }
.wms-num { font:600 var(--fs-num-l)/1 var(--fh); letter-spacing:var(--track-display); font-variant-numeric:tabular-nums; }
.wms-strip { position:relative; display:grid; grid-template-columns:repeat(var(--n,3),minmax(0,1fr)); border:1px solid var(--line);
  background:var(--surface-1); box-shadow:var(--e1); }
.wms-stat { min-width:0; padding:var(--sp-3) var(--sp-6) var(--sp-4); }
.wms-stat + .wms-stat { border-left:1px solid var(--line); }
.wms-stat .wms-num { display:flex; align-items:baseline; gap:var(--sp-2); min-height:40px; margin:var(--sp-2) 0 0; }
.wms-stat .wms-num small { color:var(--dim); font:400 var(--fs-small)/1 var(--fb); letter-spacing:0; }
.wms-stat > .wms-cap { display:block; }
.wms-stat .hint { display:block; margin:var(--sp-1) 0 0; color:var(--dim); font-size:var(--fs-small); line-height:1.45; }

.wms-alert { --c:var(--warning); display:flex; align-items:center; flex-wrap:wrap; gap:var(--sp-2) var(--sp-3); margin:0; padding:var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-4);
  min-height:var(--touch); border:1px solid color-mix(in srgb,var(--c) 45%,var(--line)); border-left:3px solid var(--c);
  background:var(--surface-1); color:var(--text); font-size:var(--fs-body); line-height:1.45; }
.wms-alert::before { content:"!" / ""; flex:none; display:grid; place-items:center; width:20px; height:20px; border-radius:var(--r-dot);
  background:var(--c); color:var(--surface-1); font:700 var(--fs-caption)/1 var(--fb); }
.wms-alert.bad { --c:var(--danger); }
.wms-alert > :first-child { flex:1 1 220px; min-width:0; }
.wms-alert[hidden] { display:none; }

.wms-empty { display:grid; grid-template-columns:minmax(0,240px) minmax(0,440px); justify-content:center; align-items:center; gap:var(--sp-6) var(--sp-8);
  padding:var(--sp-6) 0; }
.wms-empty-art { position:relative; aspect-ratio:3 / 2; border:1px dashed rgba(var(--ink-rgb),.32); }
.wms-empty-art svg { position:absolute; inset:0; width:100%; height:100%; fill:none; stroke:rgba(var(--ink-rgb),.6); stroke-width:1.2;
  stroke-linecap:round; stroke-linejoin:round; }
.wms-empty-art svg .accent { stroke:var(--section); }
.wms-empty h3 { margin:0; font:600 var(--fs-h2)/1.1 var(--fh); letter-spacing:var(--track-head-md); text-transform:uppercase; }
.wms-empty p { margin:var(--sp-2) 0 0; color:var(--dim); font-size:var(--fs-body); line-height:1.5; }
.wms-empty .acts { display:flex; flex-wrap:wrap; gap:var(--sp-3); margin-top:var(--sp-4); }
.wms-empty .acts:not(:has(> :not([hidden]))) { display:none; }   /* no key for this person: no empty row */
.wms-empty[hidden] { display:none; }
/* an empty table (its only row is the one message spanning it) shows the message without the column headings (2.11 empty states) */
table:has(> tbody > tr:only-child > td[colspan]:only-child) > thead { display:none; }
@media (max-width:600px) { .wms-empty { grid-template-columns:minmax(0,1fr); gap:var(--sp-4); padding:var(--sp-2) 0; } .wms-empty-art { max-width:240px; } }

:lang(zh) .wms-cap, :lang(zh) .wms-empty h3, :lang(zh) .wms-num { letter-spacing:0; text-transform:none; }
:lang(zh) .wms-cap { font-size:var(--fs-small); }

/* a list box (a select with size: Add item's warehouse items, Settings' time zones): its rows spaced alike and the chosen one in the accent
   tint, never the browser's grey bar (round 1 B2-4; one rule for both) */
select[size] option { padding:var(--sp-1) var(--sp-3); }
select[size] option:checked { background:var(--accent-bg); color:var(--text); }

/* a date field's day in the page language (wms-ui.js WMS.dateReadout): on the caption's line, at its end, so the field and its row keep
   their height; at the caption's size and never wider than its column (a half-width phone field: Labels' Day at 390 px). The field's
   wrapper is a <label> (Sets) or a <div> holding a caption <label> and the field (Labels' Day, round 2 B2a-01). */
:is(label,div):has(> .wms-date-readout) { display:grid; grid-template-columns:auto minmax(0,1fr); align-items:baseline; }
:is(label,div):has(> .wms-date-readout) > :not(:first-child):not(.wms-date-readout) { grid-column:1 / -1; }
.wms-date-readout { justify-self:end; min-width:0; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--text);
  font:500 var(--fs-caption)/1.2 var(--fb); letter-spacing:0; text-transform:none; font-variant-numeric:tabular-nums; }

/* the sub-page tabs (brief 4.2: only for sub-pages that are not in the sidebar: Labels & Listings, the Surprise Set Calculator, Admin): one
   look on every page (stage-2 review), a solid strip with a hairline under it; the open tab in the section colour, tinted, with a 2 px
   bar. The tabs wrap onto a second row when the screen is narrow: never cut off; on a phone (600 px or less) they keep one row instead
   (see below). A page places the strip (sticky, full-bleed) itself. */
.wms-tabs { display:flex; flex-wrap:wrap; gap:0; border-bottom:1px solid var(--line); background:var(--surface-1); }
.wms-tabs > :is(a,button) { position:relative; display:inline-flex; align-items:center; flex:none; min-height:var(--touch); margin:0 0 -1px; padding:0 var(--sp-4);
  border:0; border-bottom:2px solid transparent; border-radius:var(--r-0); background:transparent; color:var(--dim); box-shadow:none;
  font:600 var(--fs-body)/1.2 var(--fb); letter-spacing:0; text-transform:none; text-decoration:none; white-space:nowrap; cursor:pointer;
  touch-action:manipulation; -webkit-tap-highlight-color:transparent; transition:color var(--dur-out) ease,background-color var(--dur-out) ease; }
@media (hover:hover) and (pointer:fine) { .wms-tabs > :is(a,button):hover { background:var(--hover); color:var(--text); transition-duration:0s; } }
.wms-tabs > :is(a,button):focus-visible { outline:var(--focus-ring); outline-offset:-2px; }
.wms-tabs > :is([aria-selected="true"],[aria-current="page"]) { color:var(--text); border-bottom-color:var(--section); background:var(--accent-bg); }
/* phones: one row, never a second (round 1 B2-2: "Stats" alone on a second row made the sticky strip 86 px). The tabs share the row and
   fill it; only where they cannot all fit (a narrow phone, a long language) does the row scroll sideways, the open tab scrolled into view
   (wms-ui.js) and the next one showing cut at the edge. */
@media (max-width:600px) {
  .wms-tabs { flex-wrap:nowrap; overflow-x:auto; overscroll-behavior-x:contain; scrollbar-width:none; border-bottom:0; box-shadow:inset 0 -1px 0 var(--line); }
  .wms-tabs::-webkit-scrollbar { display:none; }
  .wms-tabs > :is(a,button) { flex:1 0 auto; justify-content:center; margin-bottom:0; padding:0 var(--sp-3); }   /* the hairline is inside: the open
     tab's 2 px bar is not cut by the scroll box */
}

/* the page footer (a footer after the page header): the product line from the server, then the owner line or the licence, centred and
   separated by a dot; one rule for every page that has one (stage-2 review: centred or split, with or without letter-spacing) */
header.wms-page-header ~ footer { display:flex; flex-wrap:wrap; justify-content:center; gap:var(--sp-1) var(--sp-2); padding:var(--sp-3) var(--gutter);
  border-top:1px solid var(--line); background:var(--surface-1); color:var(--dim); font:400 var(--fs-caption)/1.5 var(--fb);
  letter-spacing:var(--track-caps-sm); text-align:center; }
header.wms-page-header ~ footer > :empty { display:none; }
header.wms-page-header ~ footer > :not(:empty) ~ :not(:empty)::before { content:"·" / ""; margin-right:var(--sp-2); }
@media (max-width:600px) {   /* phones: one line each, no dot at the start of a wrapped line */
  header.wms-page-header ~ footer { flex-direction:column; align-items:center; }
  header.wms-page-header ~ footer > :not(:empty) ~ :not(:empty)::before { content:none; } }
:lang(zh) header.wms-page-header ~ footer { letter-spacing:0; text-transform:none; }
/* the footer sits at the bottom of the window when a page is shorter than it (owner, 2026-10-05: "Bottom Panel is lifted not at the
   bottom"): every page with the shared header and footer is one column whose main takes the free height; padding (the phone tab bar) is
   inside the window height, so a short page never scrolls */
body:has(> header.wms-page-header ~ footer) { box-sizing:border-box; display:flex; flex-direction:column; min-height:100vh; min-height:100dvh; }
body:has(> header.wms-page-header ~ footer) > main { flex:1 0 auto; }

/* a setting that is on or off, drawn as a key (Scan Station's Secondary sort): role="switch" + aria-checked, a square track before its
   words (as Labels' Reverse order switch); the words still say ON or OFF */
button[role="switch"]::before { content:""; flex:none; width:30px; height:18px; box-sizing:border-box; border:1px solid var(--line-field);
  background:linear-gradient(var(--dim),var(--dim)) 3px 50% / 10px 10px no-repeat,var(--panel2);
  transition:background-position var(--dur-base) var(--ease-out),border-color var(--dur-fast) ease; }
button[role="switch"][aria-checked="true"]::before { border-color:var(--blue);
  background:linear-gradient(var(--blue),var(--blue)) calc(100% - 3px) 50% / 10px 10px no-repeat,var(--accent-bg); }
/* a filter that is on or off (a checkbox in a label) drawn as a chip (2.11 filter chips): the tick stays a real checkbox, visually hidden
   but focusable; pressed = the accent tint and a blue edge, as .wms-chip[aria-pressed] */
label.wms-chip { position:relative; cursor:pointer; color:var(--text); }
label.wms-chip > input[type="checkbox"] { position:absolute; width:1px; height:1px; margin:0; opacity:0; pointer-events:none; }
label.wms-chip:has(> input:checked) { background:var(--accent-bg); border-color:var(--blue); }
label.wms-chip:has(> input:focus-visible) { outline:var(--focus-ring); outline-offset:var(--focus-offset); }
@media (pointer:coarse), (max-width:849px) { label.wms-chip { min-height:var(--touch); } }

/* every signed-in page keeps the scroll bar's room, so a long page and a short one are the same width and the header never shifts
   between pages (stage-2 review: only the Surprise Set pages did, 15 px narrower than the rest); overlay scroll bars (a Mac, a phone)
   take no room at all */
html:has(> body > header.wms-page-header) { scrollbar-gutter:stable; }

/* High Contrast (forced colours) drops backgrounds and shadows: a pressed, selected or current control keeps an outline in Highlight */
@media (forced-colors:active) {
  :is([aria-pressed="true"],[aria-checked="true"],[role="tab"][aria-selected="true"],.wms-tabs > [aria-current="page"],label.wms-chip:has(> input:checked),.wms-pick-opt[aria-selected="true"]) {
    outline:2px solid Highlight; outline-offset:-2px; }
}

/* ---------- Living Blueprint backgrounds (2.8) ----------
   Tier C (working pages): the page's own still 44 px grid; nothing here.
   Tier A (sign-in, Terms step, Admin PIN): <!--wms-blueprint--> (static/parts/blueprint-floor.html, filled in by the server) and
   <html data-wms-bg="a">: a drifting major grid, a warehouse drawing that draws itself once, crosshairs a survey line picks up.
   Tier B (Today's overview hero, empty states): data-wms-bg="b" and inline line art with .wms-draw paths, drawn once.
   Only transform and opacity loop. html.still (reduced motion, a weak PC, slow frames: wms-ui.js) is a finished still frame;
   html.paused (tab hidden, no input for --ambient-idle) holds the loops where they are. Never printed. */
.wms-bg { position:fixed; inset:0; z-index:-1; overflow:hidden; pointer-events:none; contain:strict; background-color:var(--floor);
  background-image:linear-gradient(var(--grid) 1px,transparent 1px),linear-gradient(90deg,var(--grid) 1px,transparent 1px); background-size:44px 44px; }
.wms-bg-vignette { position:absolute; inset:0; background:radial-gradient(ellipse 70% 62% at 50% 44%,var(--glow),transparent 70%); }
.wms-bg-major { position:absolute; inset:-44px;
  background:linear-gradient(rgba(var(--ink-rgb),.085) 1px,transparent 1px) 44px 44px/220px 220px,
             linear-gradient(90deg,rgba(var(--ink-rgb),.085) 1px,transparent 1px) 44px 44px/220px 220px;
  animation:wms-breathe var(--ambient-breathe) ease-in-out infinite alternate,wms-drift var(--ambient-drift) linear infinite alternate; }
@keyframes wms-breathe { from { opacity:.45; } to { opacity:1; } }
@keyframes wms-drift { from { transform:translate(0,0); } to { transform:translate(6px,6px); } }
.wms-plate { position:absolute; inset:0; width:100%; height:100%; }
.wms-plate path { fill:none; stroke-linecap:square; }
.wms-plate .frame path { stroke:rgba(var(--ink-rgb),.3); stroke-width:1; }
.wms-plate .frame path.inner { stroke:rgba(var(--ink-rgb),.16); }
.wms-plate .frame .ticks, .wms-plate .frame text { animation:wms-fade var(--dur-sheet-fade) ease-out var(--sheet-marks-at) both; }
.wms-plate .frame text { fill:rgba(var(--ink-rgb),.55); font:600 var(--fs-caption) var(--fb); letter-spacing:var(--track-caption);
  text-anchor:middle; dominant-baseline:central; }
.wms-plate .art path { stroke:rgba(var(--ink-rgb),.2); stroke-width:1; }
.wms-plate .art path.soft { stroke:rgba(var(--ink-rgb),.12); }
.wms-plate .art path.lane { stroke:rgba(var(--ink-rgb),.22); stroke-dasharray:7 7; animation:wms-fade var(--dur-sheet-lane) ease-out var(--sheet-lane-at) both; }
.wms-plate .art path.chev { stroke:rgba(var(--ink-rgb),.3); animation:wms-fade var(--dur-sheet-lane) ease-out var(--sheet-chev-at) both; }
/* line art that draws itself once (paths with pathLength="1"; --d delay, --t duration) */
.wms-draw { stroke-dasharray:1; stroke-dashoffset:0; animation:wms-draw var(--t,var(--dur-draw)) var(--ease-in-out) var(--d,0s) both; }
@keyframes wms-draw { from { stroke-dashoffset:1; } }
@keyframes wms-fade { from { opacity:0; } }
/* crosshairs on bin codes, lit as the survey line reaches them (--at: the share of the survey cycle the line needs) */
.wms-xh { position:absolute; width:0; height:0; opacity:.5;
  animation:wms-xh-life var(--ambient-survey) linear calc(var(--ambient-start) + var(--at) * var(--ambient-survey)) infinite both; }
.wms-xh .ret { position:absolute; left:-14px; top:-14px; width:28px; height:28px;
  animation:wms-xh-snap var(--ambient-survey) var(--ease-out) calc(var(--ambient-start) + var(--at) * var(--ambient-survey)) infinite both; }
.wms-xh .ret::before { content:""; position:absolute; inset:7px; border:1px solid rgba(var(--ink-rgb),.75); border-radius:var(--r-dot); }
.wms-xh .ret::after { content:""; position:absolute; inset:0;
  background:linear-gradient(rgba(var(--ink-rgb),.85),rgba(var(--ink-rgb),.85)) center/1px 100% no-repeat,
             linear-gradient(rgba(var(--ink-rgb),.85),rgba(var(--ink-rgb),.85)) center/100% 1px no-repeat;
  -webkit-mask:radial-gradient(circle,transparent 3.5px,#000 4px); mask:radial-gradient(circle,transparent 3.5px,#000 4px); }
.wms-xh .lbl { position:absolute; left:14px; top:-26px; font:600 var(--fs-caption)/1 var(--fb); letter-spacing:var(--track-caption);
  color:rgba(var(--ink-rgb),.8); white-space:nowrap; }
.wms-xh .cl { position:absolute; top:0; right:16px; width:var(--w); height:1px; transform-origin:right;
  background:repeating-linear-gradient(90deg,rgba(var(--ink-rgb),.4) 0 6px,transparent 6px 12px);
  animation:wms-xh-cl var(--ambient-survey) var(--ease-out) calc(var(--ambient-start) + var(--at) * var(--ambient-survey)) infinite both; }
.wms-xh .cl.r { right:auto; left:16px; transform-origin:left; }
@keyframes wms-xh-life { 0% { opacity:0; } 1.2% { opacity:1; } 15% { opacity:.85; } 22%, 100% { opacity:0; } }
@keyframes wms-xh-snap { 0% { transform:scale(.4) rotate(-90deg); } 2.2%, 100% { transform:none; } }
@keyframes wms-xh-cl { 0% { transform:scaleX(0); } 6%, 100% { transform:none; } }
/* the survey line: a crisp 1 px line with a 24 px fall-off (no glow in light), read by barcode heads at both frame edges */
.wms-survey { position:absolute; left:40px; right:40px; top:0; height:1px; opacity:0;
  background:linear-gradient(90deg,rgba(var(--ink-rgb),0),rgba(var(--ink-rgb),.55) 8%,rgba(var(--ink-rgb),.55) 92%,rgba(var(--ink-rgb),0));
  animation:wms-survey var(--ambient-survey) linear var(--ambient-start) infinite both; }
.wms-survey::before { content:""; position:absolute; left:0; right:0; bottom:1px; height:24px;
  background:linear-gradient(to top,rgba(var(--ink-rgb),.055),rgba(var(--ink-rgb),0)); }
body.light .wms-survey::before { display:none; }
.wms-survey .head { position:absolute; top:-3px; display:block; width:30px; height:7px; }
.wms-survey .head.l { left:-34px; } .wms-survey .head.r { right:-34px; }
.wms-survey .head i { position:absolute; top:0; bottom:0; background:var(--blue); }
@keyframes wms-survey { 0% { transform:translateY(-40px); opacity:0; } 1% { opacity:.85; } 42.4% { opacity:.85; }
  42.86% { transform:translateY(940px); opacity:0; } 100% { transform:translateY(940px); opacity:0; } }
/* phones: only the grid and the crosses (battery) */
/* phones: only the grid and the frame (battery); the full-bleed card would cut the crosshairs (they sit in its rows) */
@media (max-width:600px) { .wms-bg .wms-plate .art, .wms-bg .wms-survey, .wms-bg .wms-bg-major, .wms-bg .wms-xh { display:none; } }
/* a finished still frame */
@media (prefers-reduced-motion:reduce) {
  .wms-bg *, .wms-bg *::before, .wms-bg *::after, .wms-draw { animation:none !important; }
  .wms-bg .wms-survey { display:none; } .wms-bg .wms-xh { opacity:.55; }
  .wms-btn[aria-busy="true"]::after { animation:none; transform:none; }
  .wms-card-rule { animation:none; }
  .wms-skel { animation:wms-skel-in 0s linear var(--skel-delay) both; }
  .wms-progress > i { transition:none; }
  .wms-toast { transition:opacity var(--dur-fast) ease; }
  @starting-style { .wms-toast { translate:none; } }
}
html.still .wms-bg *, html.still .wms-bg *::before, html.still .wms-bg *::after, html.still .wms-draw { animation:none !important; }
html.still .wms-card-rule { animation:none; }
html.still .wms-bg .wms-survey { display:none; }
html.still .wms-bg .wms-xh { opacity:.55; }
html.paused .wms-bg *, html.paused .wms-bg *::before, html.paused .wms-bg *::after, html.paused .wms-draw { animation-play-state:paused !important; }
/* ---------- the floor under every signed-in page (owner, 2026-10-03: "use the background of the logins as all the backgrounds ...
   or a variant of it") ----------
   navigation.js puts one .wms-floor behind the page (the shell, so every page has it): the sign-in's drawing frame with its zone
   marks (1-8 across, A-E down) and the area's own view of ONE isometric warehouse plan (static/blueprint-plan.svg, built by
   scripts/build_blueprint.py; <html data-wms-view> names the view: the whole floor, the receiving dock, the shipping doors, the
   racks with their bin codes, the shelves, the packing benches, the office). The plan is a mask, so its lines are the theme's ink
   (graphite in light) at --floor-art, and the server tags each url() with the file's version: one cached file, no layout.
   Working pages: still, low, behind opaque panels. data-wms-bg="b" (Today's overview, empty states): the view draws on once at
   entry, a plotter line opening it left to right (transform only). Reduced motion, html.still and print: no drawing on. */
.wms-floor { position:fixed; top:0; bottom:0; left:var(--wms-nav-space,0px); right:0; z-index:-1; overflow:hidden; pointer-events:none; contain:strict; }
.wms-floor-sheet { position:absolute; inset:var(--sp-3); border:1px solid rgba(var(--ink-rgb),var(--floor-rule)); }
.wms-floor-sheet::before { content:""; position:absolute; inset:var(--sp-4); border:1px solid rgba(var(--ink-rgb),var(--floor-rule)); }
.wms-floor-zones { position:absolute; display:flex; font:600 var(--fs-caption)/1 var(--fb); letter-spacing:var(--track-caption);
  color:rgba(var(--ink-rgb),var(--floor-rule)); }
.wms-floor-zones.x { left:var(--sp-4); right:var(--sp-4); height:var(--sp-4); }
.wms-floor-zones.top { top:0; } .wms-floor-zones.bottom { bottom:0; }
.wms-floor-zones.y { flex-direction:column; top:var(--sp-4); bottom:var(--sp-4); width:var(--sp-4); }
.wms-floor-zones.left { left:0; } .wms-floor-zones.right { right:0; }
.wms-floor-zones i { flex:1; display:grid; place-items:center; font-style:normal; }
.wms-floor-zones.x i + i { border-left:1px solid rgba(var(--ink-rgb),var(--floor-rule)); }
.wms-floor-zones.y i + i { border-top:1px solid rgba(var(--ink-rgb),var(--floor-rule)); }
.wms-floor-plan { position:absolute; inset:calc(var(--sp-4) + var(--sp-3)); overflow:hidden; }
.wms-floor-plan > i { position:absolute; inset:0; background-color:rgba(var(--ink-rgb),var(--floor-art));
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat; -webkit-mask-size:cover; mask-size:cover; -webkit-mask-position:center; mask-position:center; }
html[data-wms-view="floor"] .wms-floor-plan > i { -webkit-mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#floor); mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#floor); }
html[data-wms-view="receiving"] .wms-floor-plan > i { -webkit-mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#receiving); mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#receiving); }
html[data-wms-view="shipping"] .wms-floor-plan > i { -webkit-mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#shipping); mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#shipping); }
html[data-wms-view="racks"] .wms-floor-plan > i { -webkit-mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#racks); mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#racks); }
html[data-wms-view="shelves"] .wms-floor-plan > i { -webkit-mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#shelves); mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#shelves); }
html[data-wms-view="packing"] .wms-floor-plan > i { -webkit-mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#packing); mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#packing); }
html[data-wms-view="office"] .wms-floor-plan > i { -webkit-mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#office); mask-image:url(/blueprint-plan.svg?v=a7f3804ef71f#office); }
.wms-floor-plan::after { content:""; position:absolute; top:0; bottom:0; right:0; width:1px; background:rgba(var(--ink-rgb),.3); opacity:0; }
html[data-wms-bg="b"] .wms-floor-plan { animation:wms-plot var(--dur-plot) var(--ease-in-out) var(--dur-out) both; }
html[data-wms-bg="b"] .wms-floor-plan > i { animation:wms-plot-hold var(--dur-plot) var(--ease-in-out) var(--dur-out) both; }
html[data-wms-bg="b"] .wms-floor-plan::after { animation:wms-plot-line var(--dur-plot) linear var(--dur-out) both; }
@keyframes wms-plot { from { transform:translateX(-100%); } }
@keyframes wms-plot-hold { from { transform:translateX(100%); } }
@keyframes wms-plot-line { 0%, 92% { opacity:1; } 100% { opacity:0; } }
@media (max-width:600px) { .wms-floor-zones, .wms-floor-sheet::before { display:none; } .wms-floor-plan { inset:0; } }
@media (prefers-reduced-motion:reduce) { .wms-floor-plan, .wms-floor-plan > i, .wms-floor-plan::after { animation:none !important; } }
html.still .wms-floor-plan, html.still .wms-floor-plan > i, html.still .wms-floor-plan::after { animation:none !important; }
@media print { .wms-bg, .wms-floor, .wms-toasts { display:none !important; } }
/* bars are drawn with backgrounds, which printers skip unless asked: Today's and the overview's progress (Stock's bar: inventory.css) */
@media print { .wms-progress, .wms-progress > i, [role="progressbar"], [role="progressbar"] *, progress { print-color-adjust:exact; -webkit-print-color-adjust:exact; } }
/* High Contrast (forced colours) would draw the decoration at full strength next to the text: it is left out. */
@media (forced-colors:active) { .wms-bg, .wms-floor { display:none !important; } }

/* ---------- pages for a list (wms-ui.js WMS.pager) ---------- */
/* Previous · Page X of Y · Next centred under the list; the page line keeps its width, so the keys keep their places as the numbers
   change and whether or not they show. Per page, or a page's own note beside the pager ("{n} completed"), sits at the right end.
   Touch-sized up to 850 px; when that one row is wider than the pager's own box (a phone, or the sidebar open beside a narrow window:
   wms-ui.js measures it, .wms-pager-stack) the page line takes the top row, Previous / Next share the row below and Per page (or the
   note) takes its own row; up to 480 px the page line and Previous / Next do so always; up to 640 px Per page uses 16 px text (no iOS
   zoom). No motion.
   The select's rules outrank a page's own field rules (.warehouse-inventory :is(main,dialog) select). */
.wms-pager { display:grid; grid-template-columns:1fr auto auto auto 1fr; align-items:center; gap:var(--sp-3); margin-top:var(--sp-5); }
.wms-pager[hidden], .wms-pager [hidden] { display:none; }
.wms-pager > .wms-pager-prev { grid-column:2; }
.wms-pager > .wms-pager-page { grid-column:3; min-width:11em; text-align:center; font-variant-numeric:tabular-nums; color:var(--text); }
.wms-pager > .wms-pager-next { grid-column:4; }
.wms-pager > :not(.wms-pager-prev, .wms-pager-page, .wms-pager-next) { grid-column:5; justify-self:end; }
.wms-pager-per { display:flex; flex-direction:row; align-items:center; gap:var(--sp-2); margin:0; white-space:nowrap; }
.wms-pager > .wms-pager-per > select.wms-input { width:auto; min-width:80px; min-height:var(--btn-h); padding-block:0; }
@media (max-width:850px) {
  .wms-pager > .wms-btn { min-height:var(--touch); min-width:88px; }
  .wms-pager > .wms-pager-per > select.wms-input { min-height:var(--touch); } }
.wms-pager.wms-pager-stack { grid-template-columns:1fr 1fr; }
.wms-pager.wms-pager-stack > .wms-pager-page { grid-column:1 / -1; grid-row:1; }
.wms-pager.wms-pager-stack > .wms-pager-prev { grid-column:1; grid-row:2; }
.wms-pager.wms-pager-stack > .wms-pager-next { grid-column:2; grid-row:2; }
.wms-pager.wms-pager-stack > :not(.wms-pager-prev, .wms-pager-page, .wms-pager-next) { grid-column:1 / -1; justify-self:center; }
@media (max-width:640px) { .wms-pager > .wms-pager-per > select.wms-input { font-size:16px; } }
@media (max-width:480px) {
  .wms-pager { grid-template-columns:1fr 1fr; gap:var(--sp-2); }
  .wms-pager > .wms-pager-page { grid-column:1 / -1; grid-row:1; min-width:0; }
  .wms-pager > .wms-pager-prev { grid-column:1; grid-row:2; }
  .wms-pager > .wms-pager-next { grid-column:2; grid-row:2; }
  .wms-pager > :not(.wms-pager-prev, .wms-pager-page, .wms-pager-next) { grid-column:1 / -1; justify-self:center; } }
/* A pager in a narrow box at any window width (the Scan Station's batch panel and Sessions card, two tables side by side, a window):
   the phone rows, the page line above Previous / Next. */
.wms-pager.wms-pager-narrow { grid-template-columns:1fr 1fr; gap:var(--sp-2); }
.wms-pager.wms-pager-narrow > .wms-pager-page { grid-column:1 / -1; grid-row:1; min-width:0; }
.wms-pager.wms-pager-narrow > .wms-pager-prev { grid-column:1; grid-row:2; }
.wms-pager.wms-pager-narrow > .wms-pager-next { grid-column:2; grid-row:2; }
@media (min-width:481px) {   /* in a wide window the keys keep their own width, side by side under the page line */
  .wms-pager.wms-pager-narrow > .wms-pager-prev { justify-self:end; }
  .wms-pager.wms-pager-narrow > .wms-pager-next { justify-self:start; } }
