*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
  --sc-green:#7cbd3c; --sc-yellow:#f2c840; --sc-orange:#e07235; --sc-red:#d13644; --sc-magenta:#86347c;
  --bg:#fdf8e5; --bg2:#f5f0d8; --bg3:#ece6cc;
  --surface:#ffffff; --surface2:#f8f3e0;
  --border:rgba(35,34,32,0.12); --border-strong:rgba(35,34,32,0.25);
  --text:#232220; --text2:#5a5750; --text3:#8a857c;
  --accent:#d13644;
  /* Chrome (top bar, sidebar, footer, sticky table headers): a
     step darker than --bg3 in light mode so it reads as a layered
     surface, not a body row. --chrome-rgb is the rgb of the text
     drawn ON chrome — kept as raw rgb so chrome overlays can use
     `rgba(var(--chrome-rgb), 0.NN)` and flip with the theme. */
  --hbg:#e4dcc0; --htxt:#232220; --chrome-rgb:35,34,32;
  /* WORKFLOW_STATUS_COLOR.pending — text + bg flip per theme.
     Light: default text color (var(--text), the "no color" /
     ungrouped look) on the same 10%-alpha gray the cancelled
     chip derives.
     Dark: white text on 10%-alpha white (the "transparent white"
     against dark chrome). */
  --chip-pending-text: var(--text);
  --chip-pending-bg: color-mix(in srgb, #8a857c 10%, transparent);
  /* Filled-button background that contrasts against alternating list
     rows (surface + surface2). Light theme: a step darker than both
     row colours. Dark theme override below uses a step lighter, since
     dark rows are already near-black and need to recede. */
  --btn-fill:#c8bf9d; --btn-fill-hover:#b3a980;
  --sidebar-w:52px; --sidebar-w-open:200px;
  /* Left-menu (Products column + sub-menu) inactive item color.
     Light: full near-black brand color so nav items read crisp, not
     gray. The dark override below keeps the prior 50%-alpha cream. */
  --nav-item:#232220;
}
[data-theme="dark"] {
  --bg:#232220; --bg2:#2e2c29; --bg3:#3a3835;
  --surface:#2e2c29; --surface2:#3a3835;
  --border:rgba(253,248,229,0.10); --border-strong:rgba(253,248,229,0.22);
  --text:#fdf8e5; --text2:#c8c3b0; --text3:#857f70;
  --accent:#f2c840;
  --hbg:#1a1917; --htxt:#fdf8e5; --chrome-rgb:253,248,229;
  --chip-pending-text: #ffffff;
  --chip-pending-bg: color-mix(in srgb, #ffffff 10%, transparent);
  /* See --btn-fill note above — dark theme steps lighter than both
     surface (#2e2c29) and surface2 (#3a3835) so filled buttons stand
     proud of either row. */
  --btn-fill:#6c6862; --btn-fill-hover:#7d7972;
  /* Matches the inline default this replaced: 50%-alpha cream on dark chrome. */
  --nav-item:rgba(var(--chrome-rgb),0.5);
}
html,body { height:100%; font-family:'IBM Plex Mono',monospace; background:var(--bg); color:var(--text); }
#root { height:100%; display:flex; flex-direction:column; }
* { scrollbar-width:thin; scrollbar-color:var(--border-strong) transparent; }
::-webkit-scrollbar { width:6px; height:6px; }
::-webkit-scrollbar-track { background:transparent; }
::-webkit-scrollbar-thumb { background:var(--border-strong); border-radius:3px; }

/* Sidebar transitions */
.sidebar { transition: width 0.22s cubic-bezier(.4,0,.2,1); overflow:hidden; }
.nav-label { transition: opacity 0.15s, width 0.22s; white-space:nowrap; overflow:hidden; }

/* Live pulse animation */
@keyframes pulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.5;transform:scale(1.4)} }
.live-dot { animation: pulse 1.4s ease-in-out infinite; }

/* Scanline for live feed */
@keyframes scan { 0%{top:-10%} 100%{top:110%} }
.scanline { animation: scan 3s linear infinite; }

/* Fade-in for modals */
@keyframes fadeUp { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:none} }
.modal-enter { animation: fadeUp 0.18s ease; }

/* Blink cursor */
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:0} }
.blink { animation: blink 1s step-end infinite; }

/* Spin for the DataTable refresh button while a load is in flight */
@keyframes datatable-spin { from{transform:rotate(0)} to{transform:rotate(360deg)} }