/* =====================================================================
   Royal WMS — shared design system (P0 batch 11)
   =====================================================================

   ONE visual language for the whole prototype.

   Before this file every standalone page carried its own copy-pasted CSS
   with drifted values: three different token vocabularies (the shell's
   --top/--bg/--panel/--text, the PC workbench family's
   --card/--ink/--brand/--ok/--soft, and the PDA family's darker
   --ink/--bg), ten variants of `.panel`, eight of `.btn`, eleven of
   `.pill`. Different pages read as different systems — the exact
   "patchwork" the visual completion standard rejects.

   Authoring rules for this file:

   1.  The SHELL is the source of truth. Values here are extracted from
       web-shell-v2.html's inline <style>, not redesigned. Where a page
       disagreed with the shell, the page converges to the SHELL value.
   2.  Pages link this sheet in <head> BEFORE their own <style>, so a
       genuinely page-specific rule still wins at equal specificity.
       Page <style> blocks keep ONLY what is page-specific.
   3.  New shared families the pages used to hand-roll differently are
       namespaced `wms-` (`.wms-notice`, `.wms-modal`, `.wms-drawer`,
       `.wms-form-row`, `.wms-pagination`, `.wms-empty`) so they cannot
       collide with the overloaded page-local names (`.drawer`, `.sheet`,
       `.note`, `.ok`, `.warn`, `.error`) that mean different things on
       different pages.
   4.  This sheet is layout-agnostic: no `html,body` sizing lives here.
       The shell's 1180px desktop minimum and the PDA's 390px scanner
       column stay in their own files.
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. Tokens
   ---------------------------------------------------------------------
   1a. The shell's :root block, extracted verbatim. Deleting the shell's
       copy makes this the single definition in the whole prototype.
       (--panel / --green / --success / --warn / --danger were declared
       but never painted by the shell; they are kept byte-identical so
       the extraction is faithful and any existing reference resolves
       exactly as it did.)
   --------------------------------------------------------------------- */
:root {
  --top: #202733;
  --bg: #f1f4f8;
  --panel: #fff;
  --line: #dbe3ec;
  --text: #17241f;
  --muted: #6b7886;
  --blue: #2563eb;
  --active: #eef3f9;
  --green: #164b3d;
  --success: #1f8f5f;
  --warn: #d58a1f;
  --danger: #c44b4b;

  /* 1b. Status tones — the ONE status vocabulary.
     These are the colours the shell actually PAINTS (its .pill set), so
     status pills and the feedback banners below share one palette
     instead of the four amber/green/red pairs the pages invented. */
  --tone-wait-bg: #fff4df;
  --tone-wait-fg: #946113;
  --tone-work-bg: #eaf2ff;
  --tone-work-fg: #315fa7;
  --tone-done-bg: #e6f5ec;
  --tone-done-fg: #24724e;
  --tone-danger-bg: #fdecec;
  --tone-danger-fg: #a33b3b;

  /* 1c. Surface / control values the shell hardcodes, named so a page
     can reference them instead of re-typing the literal. */
  --primary: #174d3e;
  --line-soft: #e6ebf0;
  --line-table: #dce4eb;
  --line-cell: #e7ecf1;
  --field-line: #d6dee7;
  --btn-line: #d3dce5;
  --btn-ink: #314050;
  --head-bg: #f7f9fb;
  --head-ink: #596760;
  --row-hover: #fbfcfd;

  /* 1d. Legacy vocabulary aliases.
     The PC-workbench and PDA pages were written against these names.
     Mapping them onto shell tokens converges every page to one palette
     without touching ~120 individual var() references:
       --card   #fff      (was #fff everywhere — no shift)
       --ink    #17241f   (was #17231f PC / #14201c PDA)
       --brand  #164b3d   (was #153f34 PC / #143f34 PDA)
       --ok     #24724e   (was #167451 PC / #167a53 PDA — the shell's
                           painted success text, contrast-checked)
       --soft   #e6f5ec   (was #eef6f2 / #eaf3ef / #edf5f1)
     --warn / --danger / --blue collide with shell token names above and
     therefore keep the SHELL value; the page rules that used them as a
     TEXT colour were rewritten to --tone-wait-fg / --tone-danger-fg so
     no page loses text contrast. */
  --card: var(--panel);
  --ink: var(--text);
  --brand: var(--green);
  --ok: var(--tone-done-fg);
  --soft: var(--tone-done-bg);

  /* 1e. PDA support tokens (scanner surfaces only). */
  --brand-deep: #0d3028;
  --blue-soft: var(--active);
  --danger-soft: #fff0ef;
  --shadow: 0 8px 24px rgba(23, 43, 35, 0.08);

  /* 1f. Typography scale — the sizes the shell actually uses. */
  --fs-hero: 28px;
  --fs-h1: 24px;
  --fs-h2: 21px;
  --fs-h3: 17px;
  --fs-lg: 16px;
  --fs-body: 14px;
  --fs-sm: 13px;
  --fs-xs: 12px;
  --fs-2xs: 11px;
  --fs-3xs: 10px;

  /* 1g. Spacing scale. */
  --sp-1: 4px;
  --sp-2: 6px;
  --sp-3: 8px;
  --sp-4: 10px;
  --sp-5: 12px;
  --sp-6: 14px;
  --sp-7: 18px;
  --sp-8: 22px;
  --sp-9: 26px;
  --sp-10: 32px;

  /* 1h. Radius + control heights. */
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 13px;
  --radius-pill: 999px;
  --control-h: 40px;
  --field-h: 44px;

  --font-sans:
    Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

* {
  box-sizing: border-box;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
}

/* ---------------------------------------------------------------------
   2. Page header — .page-head / .crumb
   --------------------------------------------------------------------- */
.page-head {
  padding: var(--sp-9) 0 20px;
}

.crumb {
  font-size: var(--fs-xs);
  color: #748175;
  font-weight: 750;
  margin-bottom: 5px;
}

/* Standalone pages whose page header sits on the dark brand bar rather than on
   the shell's light .main. Same breadcrumb, legible ground. */
.crumb.on-dark {
  color: rgba(255, 255, 255, 0.72);
}

.page-head h1 {
  font-size: var(--fs-hero);
  margin: 0 0 var(--sp-1);
}

.page-head p {
  margin: 0;
  color: #6e7b75;
}

/* ---------------------------------------------------------------------
   3. Side navigation — .side-group / .side-item
   --------------------------------------------------------------------- */
.side-group {
  margin-bottom: var(--sp-7);
}

.side-group-title {
  padding: var(--sp-3) var(--sp-6);
  font-size: var(--fs-lg);
  font-weight: 850;
  display: flex;
  justify-content: space-between;
}

.side-item {
  display: block;
  width: 100%;
  border: 0;
  background: transparent;
  text-align: left;
  padding: var(--sp-5) var(--sp-7) var(--sp-5) 34px;
  border-radius: var(--radius-sm);
  color: #425163;
  font-weight: 680;
}

.side-item:hover {
  background: #f5f7fa;
}

.side-item.active {
  background: var(--active);
  color: var(--blue);
  font-weight: 850;
}

.side-item.sub {
  padding-left: 52px;
  position: relative;
}

.side-item.sub:before {
  content: '';
  position: absolute;
  left: 35px;
  top: 50%;
  width: var(--sp-4);
  height: 1px;
  background: #ccd5df;
}

.side-sep {
  height: 1px;
  background: #edf1f5;
  margin: 9px var(--sp-5);
}

/* ---------------------------------------------------------------------
   4. Panels + cards — .panel / .panel-head / .eyebrow / .table-wrap
   --------------------------------------------------------------------- */
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-7) var(--sp-8);
  border-bottom: 1px solid var(--line-soft);
}

.panel-head h2 {
  font-size: var(--fs-h2);
  margin: 0;
}

.panel-head p {
  margin: 3px 0 0;
  color: #718078;
  font-size: var(--fs-sm);
}

.eyebrow {
  font-size: var(--fs-2xs);
  color: #798680;
  font-weight: 850;
  margin: 0 0 3px;
}

/* A `.table-wrap` scrolls a wide table INSIDE the panel — but only if the boxes
   above it are allowed to be narrower than the table. `.panel` carries
   `overflow: hidden` above, which is what zeroes a panel's automatic minimum
   size when the panel itself is a grid/flex item. The one box the family cannot
   reach is the page's own layout column: a grid/flex ITEM whose `overflow` is
   `visible` takes min-content as its automatic minimum, so the wide table widens
   the TRACK and the PAGE scrolls horizontally instead of the wrap.
   `web-shell-v2.html` has always answered that with `.main{min-width:0}`;
   `inventory-control-console.html` copied the same `.layout` grid WITHOUT it and
   overflowed the viewport by 229px as soon as the shared inventory store grew
   past 15 rows (batch 17). Any surface that puts a `.table-wrap` inside a
   grid/flex column must give that column `min-width: 0`. */
.table-wrap {
  padding: var(--sp-6) var(--sp-8) 24px;
  overflow: auto;
}

/* ---------------------------------------------------------------------
   5. Filters — .filter-card / .field
   --------------------------------------------------------------------- */
.filter-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--sp-7) 20px;
  display: grid;
  grid-template-columns: 1.25fr 0.75fr 1fr 1fr;
  gap: var(--sp-6);
}

.field label {
  display: block;
  font-size: var(--fs-xs);
  color: #66736d;
  font-weight: 750;
  margin-bottom: var(--sp-2);
}

.field input,
.field select {
  width: 100%;
  height: var(--field-h);
  border: 1px solid var(--field-line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  padding: 0 var(--sp-5);
  outline: none;
}

/* ---------------------------------------------------------------------
   6. Tabs — .tabs / .tab
   --------------------------------------------------------------------- */
.tabs {
  margin-top: 16px;
  display: flex;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  overflow: hidden;
  width: max-content;
}

.tab {
  min-width: 145px;
  height: 54px;
  border: 0;
  border-right: 1px solid var(--line);
  background: var(--panel);
  font-weight: 850;
  color: #52605a;
}

.tab.active {
  color: #174d3e;
  box-shadow: inset 0 4px 0 #174d3e;
}

/* ---------------------------------------------------------------------
   7. Buttons — .btn (+ .primary / .blue / .danger)
   --------------------------------------------------------------------- */
.btn {
  height: var(--control-h);
  border-radius: var(--radius-sm);
  border: 1px solid var(--btn-line);
  background: var(--panel);
  padding: 0 var(--sp-6);
  font-weight: 800;
  color: var(--btn-ink);
}

.btn.primary {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}

.btn.blue {
  background: var(--blue);
  color: #fff;
  border-color: var(--blue);
}

.btn.danger {
  color: var(--tone-danger-fg);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* ---------------------------------------------------------------------
   8. Tables
   --------------------------------------------------------------------- */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--line-table);
  border-radius: var(--radius-md);
  overflow: hidden;
  font-size: var(--fs-sm);
}

th {
  background: var(--head-bg);
  color: var(--head-ink);
  font-size: var(--fs-2xs);
  font-weight: 850;
  text-align: left;
  padding: var(--sp-5) 13px;
  border-bottom: 1px solid var(--line-table);
  white-space: nowrap;
}

td {
  padding: var(--sp-6) 13px;
  border-bottom: 1px solid var(--line-cell);
  white-space: nowrap;
}

tr:last-child td {
  border-bottom: 0;
}

tbody tr:hover {
  background: var(--row-hover);
}

.link {
  color: var(--green);
  font-weight: 850;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---------------------------------------------------------------------
   9. Status pills — .pill (+ .wait / .work / .done / .danger)
   ---------------------------------------------------------------------
   ONE status vocabulary. 待… → .wait, …中 / 已领取 → .work,
   已完成 / 已… → .done, 异常 / 冻结 / 失败 → .danger.
   --------------------------------------------------------------------- */
.pill {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 var(--sp-4);
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 800;
}

.pill.wait {
  background: var(--tone-wait-bg);
  color: var(--tone-wait-fg);
}

.pill.work {
  background: var(--tone-work-bg);
  color: var(--tone-work-fg);
}

.pill.done {
  background: var(--tone-done-bg);
  color: var(--tone-done-fg);
}

.pill.danger {
  background: var(--tone-danger-bg);
  color: var(--tone-danger-fg);
}

/* A fifth, genuinely neutral tone for non-status metadata (a wave number, a
   channel tag, "不可跳号"). The PDA pages had invented it; naming it here keeps
   it from being confused with a status. */
.pill.neutral {
  background: #edf1ef;
  color: #67736f;
}

/* Legacy tone NAMES the PDA + workbench pages were written against. Each is an
   alias of one of the four canonical tones — declaring them here means those
   pages stop carrying six private, drifted colour pairs (and stops `.pill.ok`
   from rendering as an UNCOLOURED pill wherever the page forgot to define it,
   which is what 库存控制台's 解冻 / 上架 / 盘点 rows used to do). */
.pill.ok {
  background: var(--tone-done-bg);
  color: var(--tone-done-fg);
}

.pill.warn {
  background: var(--tone-wait-bg);
  color: var(--tone-wait-fg);
}

.pill.blue {
  background: var(--tone-work-bg);
  color: var(--tone-work-fg);
}

/* ---------------------------------------------------------------------
   10. Metrics / quick cards / summary strip
   --------------------------------------------------------------------- */
.metric {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--sp-5);
  padding: var(--sp-7);
}

.metric span {
  display: block;
  color: #748078;
  font-size: var(--fs-xs);
  font-weight: 800;
}

.metric strong,
.metric b {
  display: block;
  font-size: 30px;
  margin: var(--sp-2) 0 3px;
}

.metric small {
  color: #748078;
}

.quick-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-6);
}

.quick {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--sp-5);
  padding: var(--sp-7);
}

.quick h3 {
  margin: 0 0 7px;
  font-size: var(--fs-h3);
}

.quick p {
  color: var(--muted);
  font-size: var(--fs-sm);
  min-height: 38px;
}

.quick .actions {
  display: flex;
  gap: var(--sp-3);
  margin-top: 13px;
}

.summary-strip {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}

.summary-strip div {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 13px;
}

.summary-strip b {
  display: block;
  font-size: 20px;
}

.summary-strip small {
  color: var(--muted);
}

/* ---------------------------------------------------------------------
   11. Empty states
   ---------------------------------------------------------------------
   `.empty` is the in-panel variant the shell already paints (plain
   centred text inside a .table-wrap). `.wms-empty` is the standalone
   card variant that replaces the three hand-rolled dashed boxes.
   --------------------------------------------------------------------- */
.empty {
  padding: 38px;
  text-align: center;
  color: #718090;
}

/* An in-table empty state may carry a title + hint, exactly like the standalone
   card below. Put `.empty` on a DIV inside the placeholder cell rather than on
   the <td>: a page's own `.table td { padding }` rule out-specifies a single
   class and would flatten it. */
.empty strong {
  display: block;
  font-size: var(--fs-lg);
  color: var(--text);
  margin-bottom: var(--sp-2);
}

.empty p {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.6;
}

.wms-empty {
  padding: 34px 22px;
  border: 1px dashed #c3cfd9;
  border-radius: var(--radius-lg);
  background: var(--panel);
  text-align: center;
  color: var(--muted);
}

.wms-empty strong {
  display: block;
  font-size: var(--fs-lg);
  color: var(--text);
  margin-bottom: var(--sp-2);
}

.wms-empty p {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.6;
}

/* ---------------------------------------------------------------------
   12. Feedback — .wms-notice (info / success / warning / error)
   ---------------------------------------------------------------------
   The four tones every page used to invent (.note, .notice, .info,
   .warning, .alert, .bad …). One family, the status palette above.
   --------------------------------------------------------------------- */
.wms-notice {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--panel);
  color: var(--text);
  font-size: var(--fs-sm);
  line-height: 1.6;
}

.wms-notice + .wms-notice {
  margin-top: var(--sp-4);
}

/* Scanner density. The PDA pages stack notices between cards at 11px in a
   390px column; this is the same family, not a second one. */
.wms-notice.compact {
  margin-top: var(--sp-4);
  padding: 11px;
  font-size: var(--fs-2xs);
  line-height: 1.55;
}

.wms-notice strong {
  font-weight: 850;
}

.wms-notice.info {
  background: var(--tone-work-bg);
  border-color: #c9dcfa;
  color: var(--tone-work-fg);
}

.wms-notice.success {
  background: var(--tone-done-bg);
  border-color: #bfe3cf;
  color: var(--tone-done-fg);
}

.wms-notice.warning {
  background: var(--tone-wait-bg);
  border-color: #ead0a7;
  color: var(--tone-wait-fg);
}

.wms-notice.error {
  background: var(--tone-danger-bg);
  border-color: #f0c9c9;
  color: var(--tone-danger-fg);
}

/* ---------------------------------------------------------------------
   13. Modal shell — .wms-modal-backdrop > .wms-modal
   ---------------------------------------------------------------------
   These are the names the prototype ALREADY uses: business-action-panels-v1.js
   renders every bulk-action dialog as
     .wms-modal-backdrop(.open) > .wms-modal > head / body / foot
   and carried a private copy of this look in its injected <style>. The values
   below are that copy, extracted — so the dialog is byte-identical and the
   look now has one owner. `.wms-modal` is the CARD, never the overlay.
   --------------------------------------------------------------------- */
.wms-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9998;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(17, 24, 39, 0.48);
}

.wms-modal-backdrop.open {
  display: flex;
}

.wms-modal {
  width: min(620px, 96vw);
  max-height: 88vh;
  overflow: auto;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.28);
}

.wms-modal-head {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-7);
  padding: 20px var(--sp-8);
  border-bottom: 1px solid var(--line-soft);
}

.wms-modal-head h2,
.wms-modal-head h3 {
  margin: 0;
  font-size: 20px;
}

.wms-modal-head p {
  margin: 5px 0 0;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.wms-modal-body {
  padding: 20px var(--sp-8);
}

.wms-modal-foot,
.wms-modal-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-5);
  padding: 16px var(--sp-8);
  border-top: 1px solid var(--line-soft);
}

/* ---------------------------------------------------------------------
   14. Drawer shell — .wms-drawer
   --------------------------------------------------------------------- */
.wms-drawer {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: none;
  justify-content: flex-end;
  background: rgba(15, 28, 23, 0.38);
}

.wms-drawer.open {
  display: flex;
}

.wms-drawer-card {
  width: min(560px, 100%);
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  box-shadow: -10px 0 40px rgba(15, 28, 23, 0.16);
}

.wms-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  padding: var(--sp-7) var(--sp-8);
  border-bottom: 1px solid var(--line-soft);
}

.wms-drawer-head h2 {
  margin: 0;
  font-size: var(--fs-h2);
}

.wms-drawer-body {
  flex: 1;
  overflow: auto;
  padding: var(--sp-7) var(--sp-8);
}

.wms-drawer-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-3);
  padding: var(--sp-6) var(--sp-8);
  border-top: 1px solid var(--line-soft);
}

/* ---------------------------------------------------------------------
   15. Form rows — .wms-form-row / .wms-form-grid
   --------------------------------------------------------------------- */
.wms-form-grid {
  display: grid;
  gap: var(--sp-6);
}

.wms-form-grid.cols-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.wms-form-grid.cols-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.wms-form-row {
  display: grid;
  gap: var(--sp-2);
}

/* The row's own caption. Pages write it as a <label> when the row IS a field
   wrapper and as a <span> when the row itself is the <label> element — both
   spellings exist in this prototype, so the family styles both. */
.wms-form-row > label,
.wms-form-row > span {
  font-size: var(--fs-xs);
  color: #66736d;
  font-weight: 750;
}

.wms-form-row input,
.wms-form-row select,
.wms-form-row textarea {
  width: 100%;
  min-height: var(--field-h);
  border: 1px solid var(--field-line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  padding: 0 var(--sp-5);
  outline: none;
  color: var(--text);
}

.wms-form-row textarea {
  padding: var(--sp-4) var(--sp-5);
  min-height: 96px;
  line-height: 1.6;
}

.wms-form-row input:focus,
.wms-form-row select:focus,
.wms-form-row textarea:focus {
  border-color: var(--blue);
}

.wms-form-hint {
  font-size: var(--fs-xs);
  color: var(--muted);
}

.wms-form-error {
  font-size: var(--fs-xs);
  color: var(--tone-danger-fg);
  font-weight: 800;
}

.wms-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-3);
  margin-top: var(--sp-7);
}

/* ---------------------------------------------------------------------
   16. Pagination — .wms-pagination
   --------------------------------------------------------------------- */
/* Extracted from the ONE pager the prototype already renders — the one
   table-interactions-v1.js injects under every enhanced table. It used to live
   as a private rule inside that file's injected <style>; owning it here means
   the site has one pagination look instead of one-per-injector. */
.wms-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  margin: var(--sp-4) 0 0;
  padding: var(--sp-4) var(--sp-5);
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  color: #52605a;
}

.wms-pagination > div {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.wms-pagination .wms-page-info {
  color: #52605a;
  margin-right: auto;
}

.wms-pagination button {
  min-width: var(--control-h);
  padding: 0 var(--sp-5);
  border: 1px solid var(--btn-line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--btn-ink);
  font-weight: 800;
}

.wms-pagination button.active {
  background: var(--active);
  border-color: #bcd0ea;
  color: var(--blue);
}

.wms-pagination button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ---------------------------------------------------------------------
   14. Detail-page business actions (batch 12)

   Every detail page grew a 业务动作 panel whose buttons call the owning
   store. Before this family each page carried its own `.actions
   button{height:40px;border:1px solid #cfd8e3…}` copy — the same
   hand-rolled component eleven times, with three different heights and
   two different disabled looks. The panel is now one shared family:
   `.wms-actions` for the row, `.btn` for the buttons (disabled state
   included) and `.wms-act-hint` for the honest one-line explanation that
   sits under it — the line that says WHY an action is unavailable.
   --------------------------------------------------------------------- */

.wms-actions {
  display: flex;
  gap: var(--sp-3);
  flex-wrap: wrap;
  align-items: center;
  margin-top: var(--sp-1);
}

.wms-actions .btn {
  min-height: var(--control-h);
  cursor: pointer;
}

.wms-act-hint {
  margin: var(--sp-4) 0 0;
  color: var(--muted);
  font-size: var(--fs-xs);
  line-height: 1.6;
}

/* ---------------------------------------------------------------------
   17. Global search / command centre — .wms-omni (batch 16)

   The top bar's `.search` input used to be the most conspicuous decorative
   control in the product: a hardcoded 12-row route table in
   shell-global-nav-v1.js that no real 入库单号 / LPN / SKU ever matched, and
   a Ctrl/⌘+K that only moved focus. global-search-v1.js replaces it with a
   real command centre, and this is the one place its look is defined — the
   runtime injects no <style> and carries no inline one-offs.

   Structure:
     .wms-omni-backdrop(.open) > .wms-omni
        > .wms-omni-head  (glyph + input + .pill.neutral scope + close)
        > .wms-omni-body  (.wms-omni-group headers + .wms-omni-hit rows,
                           or a shared `.empty` state)
        > .wms-omni-foot  (scope note + .wms-omni-key hints)
   The palette sits ABOVE the shell's other overlays (.global-pop 17000,
   .b4-overlay 19000) and BELOW the auth login veil (30000), which the
   runtime also refuses to open under.
   --------------------------------------------------------------------- */
.wms-omni-backdrop {
  position: fixed;
  inset: 0;
  z-index: 20000;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 92px var(--sp-8) var(--sp-8);
  background: rgba(17, 24, 39, 0.44);
}

.wms-omni-backdrop.open {
  display: flex;
}

.wms-omni {
  width: min(760px, 96vw);
  max-height: min(70vh, 620px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.28);
}

.wms-omni-head {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-6);
  border-bottom: 1px solid var(--line-soft);
}

.wms-omni-glyph {
  color: var(--muted);
  font-size: var(--fs-h3);
  line-height: 1;
}

.wms-omni-head input {
  flex: 1;
  min-width: 0;
  height: var(--field-h);
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
  font-size: var(--fs-lg);
  font-weight: 750;
}

.wms-omni-head input::placeholder {
  color: var(--muted);
  font-weight: 600;
}

/* type="search" keeps the input out of the shell-safety dirty-tracking scope, but
   its native clear affordance would sit next to the palette's own close button —
   two ✕ in a row. Suppress the native one; the panel owns the control. */
.wms-omni-head input::-webkit-search-cancel-button,
.wms-omni-head input::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
}

.wms-omni-close {
  flex: 0 0 auto;
  width: var(--control-h);
  height: var(--control-h);
  border: 1px solid var(--btn-line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--muted);
  font-size: var(--fs-lg);
  line-height: 1;
}

.wms-omni-close:hover {
  background: var(--head-bg);
  color: var(--text);
}

.wms-omni-body {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

.wms-omni-group {
  padding: var(--sp-4) var(--sp-6) var(--sp-2);
  background: var(--head-bg);
  border-top: 1px solid var(--line-soft);
  color: var(--head-ink);
  font-size: var(--fs-3xs);
  font-weight: 900;
  letter-spacing: 0.04em;
}

.wms-omni-body > .wms-omni-group:first-child {
  border-top: 0;
}

.wms-omni-hit {
  display: flex;
  width: 100%;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-5) var(--sp-6);
  border: 0;
  border-bottom: 1px solid var(--line-cell);
  background: var(--panel);
  text-align: left;
}

.wms-omni-hit:hover,
.wms-omni-hit[aria-selected='true'] {
  background: var(--active);
}

.wms-omni-tag {
  flex: 0 0 auto;
}

.wms-omni-id {
  flex: 1;
  min-width: 0;
}

.wms-omni-name {
  display: block;
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: 800;
}

.wms-omni-sub {
  display: block;
  margin-top: 3px;
  overflow: hidden;
  color: var(--muted);
  font-size: var(--fs-xs);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.wms-omni-go {
  flex: 0 0 auto;
  color: var(--muted);
  font-size: var(--fs-xs);
  opacity: 0;
}

.wms-omni-hit:hover .wms-omni-go,
.wms-omni-hit[aria-selected='true'] .wms-omni-go {
  opacity: 1;
}

.wms-omni-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-4) var(--sp-6);
  border-top: 1px solid var(--line-soft);
  background: var(--head-bg);
  color: var(--muted);
  font-size: var(--fs-2xs);
}

.wms-omni-key {
  display: inline-flex;
  align-items: center;
  height: 19px;
  margin: 0 2px;
  padding: 0 5px;
  border: 1px solid var(--btn-line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--btn-ink);
  font-family: var(--font-sans);
  font-size: var(--fs-3xs);
  font-weight: 800;
}
