/* ==========================================================================
 * FSIL Inventory Intake System v2 — design system foundation
 *
 * Single source of truth for v2 visual styling. Tokens, components, and
 * animations all extracted verbatim from the three Claude Design files
 * under design/ (FSIL_Inventory.html, FSIL_Intake_flows.html,
 * FSIL_Stock_Report.html). Subsequent prompts (B/C/D) reference classes
 * from here without redefining.
 *
 * Required Google Fonts (linked in each HTML <head>):
 *   <link rel="preconnect" href="https://fonts.googleapis.com" />
 *   <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
 *   <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600;700&family=Inter:wght@400;450;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
 * ========================================================================== */

/* ───────────── Tokens ───────────── */
/* Phase 1 of the visual reskin (feature/theme-foundation): the colour
   layer is split into two palettes — body.t-light (default) and
   body.t-dark — driven by the canonical handoff at
   ~/Desktop/design_handoff_fsil_theme (FSIL Themed preview.html).
   Phase 1 introduces the token system + theme toggle ONLY. The light
   palette reproduces today's production look verbatim (every legacy
   token name kept and pointed at its current value). Dark mode is
   opt-in via the toolbar toggle and is allowed to be imperfect on
   individual screens — later phases re-style each surface against the
   new --page / --surface / --text / etc. token set introduced below.

   Token name compatibility: every legacy token the v2/ callsites
   depend on (--navy / --cream / --forest / --pink / --line / status
   pairs / --shadow-1/2/modal / --r-card etc.) is declared inside both
   palettes so no existing rule breaks. Tokens introduced for the new
   handoff palette (--page, --bg, --surface, --surface-2, --border,
   --text, --heading, --field-bg, --primary-bg, --warn-tx, --m-bg/tx,
   --new-bg/tx, etc.) coexist alongside the legacy names — components
   will migrate onto them in later phases. */

/* Palette-invariant tokens: fonts, radii, and shared accents that the
   handoff explicitly calls out as identical between light and dark. */
:root {
  --mustard:      #e8bf44;
  --mustard-soft: #f6e7b6;

  /* Radii — handoff prescribes 14/10–12/9/5 for cards/inputs/buttons/
     badges. Current production uses tighter 8/6/4. Per phase-1 rule
     (no visible shift), the legacy radii are kept; later phases pick
     a final scale once the broader retheme lands. */
  --r-card: 8px;
  --r-btn:  6px;
  --r-pill: 4px;

  --serif: "Cormorant Garamond", Georgia, "Times New Roman", serif;
  --sans:  "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono:  "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ───────────── Light palette (default) ─────────────
   Legacy token values reproduce today's production verbatim — same
   hex values that lived in :root before the split. The new handoff-
   canonical names (--page, --surface, --text, etc.) sit underneath
   as a forward-looking parallel set.

   Notable kept-as-today divergences from the handoff light spec
   (silently changing these would visibly shift core screens, so
   today's values are retained — flagged in the phase-1 report):
   • --muted #4a4a4a (handoff: #6b7787) — current is AAA contrast
     against the white canvas; switching would lighten secondary text
     across every screen.
   • --navy #0c2c7a (handoff --heading: #122754) — current is the
     storefront-matching deeper blue used in buttons, headings, input
     borders. Switching would shift every chrome on the site.
   • Radii (--r-card/--r-btn/--r-pill) kept at 8/6/4 (handoff 14/9/5)
     — every card, button, pill on the site would re-round otherwise. */
body.t-light {
  /* Phase-6.1 re-tone: warm daylight sibling of the warm-charcoal
     dark. Cream/warm-gray surfaces, not stark white; warm hairlines;
     warm near-black text. Same token NAMES — only VALUES change.
     The light variant should feel like "the warm family in
     daylight" rather than a cool clinical white app. */

  /* ---- legacy aliases, warm-tuned ---- */
  --navy:   #2A2520;   /* used by buttons/headings in legacy rules → warm near-black */
  --navy-2: #1F1B17;   /* hover/active darker, matches dark --page */

  --forest:   #4A6A4F;
  --forest-2: #3D5A42;

  --accent-cream: #F7EFDF;

  --cream:     #FAF7F1;
  --cream-2:   #F0EBE1;
  --pink:      #e8bf44;
  --pink-soft: #F0EBE1;

  --ink:    #2A2520;
  --white:  #FFFFFF;
  --muted:  #8A8175;
  --line:   #E2DBCE;
  --line-2: #EBE5D9;

  --green:    #4A6A4F;
  --green-bg: #4A6A4F;
  --green-tx: #FAF7F1;
  --blue-bg:  #4A6480;
  --blue-tx:  #FAF7F1;
  --orange-bg:#F4D9C6;
  --orange-tx:#8C4A28;
  --yellow-bg:#e8bf44;
  --yellow-tx:#2A2520;
  --red:    #A8392E;
  --red-bg: #F4DDD7;

  --shadow-1: 0 1px 2px rgba(42,37,32,.06);
  --shadow-2: 0 1px 2px rgba(42,37,32,.07), 0 4px 12px rgba(42,37,32,.05);
  --shadow-modal: 0 30px 80px rgba(42,37,32,.28), 0 8px 22px rgba(42,37,32,.10);

  /* ---- canonical tokens (light, warm daylight) ---- */
  --page:         #EFEAE0;
  --bg:           #F2EEE6;
  --surface:      #FAF7F1;
  --surface-2:    #F0EBE1;
  --border:       #E2DBCE;
  --border-2:     #EBE5D9;
  --text:         #2A2520;
  --heading:      #1F1B17;
  --field-bg:     #FAF7F1;
  --field-border: #DCD3C2;
  --primary-bg:   #2A2520;
  --primary-fg:   #FAF7F1;
  --primary-bg-h: #1F1B17;
  --ghost-border: #D2CABA;
  --logo-bg:      #2A2520;
  --logo-fg:      #FAF7F1;
  --shadow:       0 1px 2px rgba(42,37,32,.06), 0 10px 26px rgba(42,37,32,.05);
  --shadow-sm:    0 1px 2px rgba(42,37,32,.05);
  --inset:        inset 0 1px 2px rgba(42,37,32,.04);
  --m-bg:#DBE7CE;  --m-tx:#4E6A3B;
  --s-bg:#F4DCC0;  --s-tx:#8C4A28;
  --o-bg:#F2E6BE;  --o-tx:#7A5A14;
  --c-bg:#F4DDD7;  --c-tx:#A8392E;
  --warn-tx:#7A5A14;
  --new-bg:#DBE7CE; --new-tx:#4E6A3B;
  --stk-bg:#DEE2EC; --stk-tx:#3F506B;
  --ret-bg:#F2DDCB; --ret-tx:#8C4A28;
  --prc-bg:#F2E6BE; --prc-tx:#7A5A14;
  --frame:#E2DBCE;
}

/* ───────────── Dark palette (warm charcoal — new default) ─────────────
   Phase-6 rewrite: replace the cool-slate handoff dark with a warm
   charcoal palette matched to the reference app the owner picked.
   Token NAMES are unchanged so every downstream consumer keeps
   working — only the VALUES change. Contained surfaces, subtle
   warm-gray hairlines, amber accents, generous data colors.

   Reference targets:
     page    = warm near-black     #1F1B17
     surface = warm charcoal +1    #2A231B   (row card)
     surface-2 = warm charcoal +2  #332B22   (hover lift)
     border  = subtle warm hairline #3A312A
     text    = warm off-white      #EDE8E0
     muted   = warm gray           #9B9389
     mustard (existing) #e8bf44    → primary amber accent
     red     #E5705B               → overdue / negative figures */
body.t-dark {
  /* ---- canonical tokens (dark, neutral charcoal) ----
     Retuned from warm brown-charcoal to a near-neutral dark
     charcoal with the faintest cool lean (Claude-app character).
     Mustard #E8BF44 is preserved as the single warm accent and
     reads stronger against the neutral surfaces. */
  --page:         #1A1A1C;
  --bg:           #1E1E20;
  --surface:      #26262A;
  --surface-2:    #2F2F34;
  --border:       #34343A;
  --border-2:     #2A2A2F;
  --text:         #E8E8EA;
  --heading:      #F5F5F7;
  --field-bg:     #26262A;
  --field-border: #3C3C42;
  --primary-bg:   #E8BF44;
  --primary-fg:   #1A1A1C;
  --primary-bg-h: #F0CD63;
  --ghost-border: #44444B;
  --logo-bg:      #E8BF44;
  --logo-fg:      #1A1A1C;
  --shadow:       0 1px 2px rgba(0,0,0,.50), 0 12px 28px rgba(0,0,0,.40);
  --shadow-sm:    0 1px 2px rgba(0,0,0,.45);
  --inset:        inset 0 1px 2px rgba(0,0,0,.40);

  /* Status pairs — same hues, neutral bgs. --m shifts to a clean
     green (no warm sage cast); --c keeps the overdue red. */
  --m-bg: rgba(120,180,130,.16);  --m-tx: #8FC79E;
  --s-bg: rgba(232,150,70,.16);   --s-tx: #ECB073;
  --o-bg: rgba(232,191,68,.14);   --o-tx: #ECC75A;
  --c-bg: rgba(229,112,91,.18);   --c-tx: #E5705B;
  --warn-tx: #ECC75A;

  --new-bg: rgba(120,180,130,.18); --new-tx: #8FC79E;
  --stk-bg: rgba(140,170,210,.16); --stk-tx: #9CC0E6;
  --ret-bg: rgba(229,140,95,.16);  --ret-tx: #ECB073;
  --prc-bg: rgba(232,191,68,.14);  --prc-tx: #ECC75A;
  --frame:  #26262A;

  /* ---- legacy aliases, neutral-mapped ---- */
  --navy:   #E8E8EA;
  --navy-2: #F5F5F7;

  --forest:   #4A8A5F;
  --forest-2: #3D7A4F;

  --accent-cream: #2F2F34;

  --cream:     #26262A;
  --cream-2:   #2F2F34;
  --pink:      #E8BF44;
  --pink-soft: #2F2F34;

  --ink:    #E8E8EA;
  --white:  #F5F5F7;
  --muted:  #95959C;
  --line:   #34343A;
  --line-2: #2A2A2F;

  --green:    #8FC79E;
  --green-bg: rgba(120,180,130,.18);
  --green-tx: #8FC79E;
  --blue-bg:  rgba(140,170,210,.16);
  --blue-tx:  #9CC0E6;
  --orange-bg:rgba(229,140,95,.16);
  --orange-tx:#ECB073;
  --yellow-bg:rgba(232,191,68,.14);
  --yellow-tx:#ECC75A;
  --red:      #E5705B;
  --red-bg:   rgba(229,112,91,.18);

  --shadow-1: 0 1px 2px rgba(0,0,0,.45);
  --shadow-2: 0 1px 2px rgba(0,0,0,.50), 0 4px 12px rgba(0,0,0,.40);
  --shadow-modal: 0 30px 80px rgba(0,0,0,.70), 0 8px 22px rgba(0,0,0,.55);
}

/* Theme cross-fade — per handoff, switching body.t-light/.t-dark
   should fade .35s ease across the chrome surfaces. Limited to large
   container surfaces that don't already declare their own transition
   (buttons, inputs, chips already animate at 150-200ms and would slow
   down their hover/focus if overridden here). Phase 2 will extend the
   list as it converts more components to palette tokens. */
body,
.chrome,
.page,
.modal,
.login-card,
.doc-stepper .ds-row {
  transition: background-color .35s ease, color .35s ease,
              border-color .35s ease, box-shadow .35s ease;
}

/* Theme toggle (segmented Light/Dark in the top chrome). Styles only
   — wiring lives in components.js via event delegation. Phase-4: the
   chrome is now --surface, so the toggle capsule rides on --surface-2
   with --ghost-border and --text labels. Active state is mustard with
   navy text in either palette (mustard reads on both modes). */
.theme-toggle {
  display: inline-flex;
  background: var(--surface-2);
  border: 1px solid var(--ghost-border);
  border-radius: 999px;
  padding: 2px;
  gap: 2px;
}
.theme-toggle button {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--text);
  font: inherit;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 999px;
  cursor: pointer;
  opacity: 0.75;
  transition: background-color 180ms ease-out, color 180ms ease-out, opacity 180ms ease-out;
  min-height: 26px;
}
.theme-toggle button:hover { opacity: 1; }
.theme-toggle button.is-active {
  background: var(--mustard);
  color: #10203a;
  opacity: 1;
}

*, *::before, *::after { box-sizing: border-box; }
html, body {
  margin: 0;
  padding: 0;
  /* Kill horizontal swipe + bounce on iPad Safari. Vertical scroll stays normal. */
  overflow-x: hidden;
  overscroll-behavior-x: none;
  touch-action: pan-y;
}
body {
  background: var(--page);
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
button { font-family: inherit; cursor: pointer; }
a { color: inherit; }
.hidden { display: none !important; }
.muted { color: var(--muted); }
.serif { font-family: var(--serif); }
.mono  { font-family: var(--mono); }

/* ───────────── Top chrome ───────────── */
/* Phase-4 restyle onto handoff tokens: chrome bar is now --surface
   (not forest), with a hairline --border bottom and nav text in
   --text/--heading. The logo mark sits in a small --logo-bg chip
   (navy chip in light, mustard chip in dark). The source PNG is
   navy-on-transparent; brightness(0)+invert(1) turns it white so it
   reads on whichever chip color the active palette gives us. */
.chrome {
  position: sticky; top: 0; z-index: 30;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
.chrome-inner {
  max-width: 1440px;
  margin: 0 auto;
  padding: 14px 32px;
  display: flex; align-items: center; gap: 20px;
}
.brand {
  display: flex; align-items: center; gap: 12px;
  min-width: 0;
}
.logo-mark {
  height: 32px; width: auto;
  display: block;
  flex-shrink: 0;
  vertical-align: middle;
  image-rendering: -webkit-optimize-contrast;
}
.chrome .logo-mark {
  filter: brightness(0) invert(1);
  background: var(--logo-bg);
  border-radius: 8px;
  padding: 5px;
  box-sizing: content-box;
}
@media (max-width: 720px) {
  .logo-mark { height: 28px; }
}
@media (max-width: 480px) {
  .logo-mark { height: 24px; }
}
.brand-divider {
  width: 1px; height: 24px; background: var(--border);
}
.page-title {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 24px;
  color: var(--heading);
  letter-spacing: 0.04em;
  text-transform: lowercase;
  font-variant: small-caps;
}
.chrome-right {
  margin-left: auto;
  display: flex; align-items: center; gap: 18px;
}
/* Roll-pill keeps a soft accent surface — --surface-2 capsule on
   --border, mustard status dot. Both intentional brand anchors
   (this and sc-resume-callout) stay; the difference is they now
   ride on the new --surface chrome rather than the old forest bar. */
.roll-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 12px;
  color: var(--text);
}
.roll-pill .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--mustard);
  box-shadow: 0 0 0 3px rgba(232,191,68,0.22);
}
.roll-pill .label-tag {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
}
.logout {
  font-size: 13px;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  transition: border-color 200ms ease-out;
  background: transparent; border-top: 0; border-left: 0; border-right: 0;
  cursor: pointer;
}
.logout:hover { border-bottom-color: var(--text); }

/* ───────────── Persistent shell-nav (bottom) ───────────── */
/* Six-item fixed bottom nav (Dashboard / Intake / Print labels /
   Invoices / Vendor copy / More). Always visible on non-login pages;
   active item gets a 2px mustard top-border + mustard text. Pure CSS
   token resolution — same markup serves dark and light. The More
   button opens a centered bottom sheet (.shell-more-backdrop) wired
   by a delegated handler in components.js. */
.shell-nav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 35;
  height: calc(72px + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--surface);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: stretch;
  justify-content: stretch;
}
.shell-nav-item {
  flex: 1 1 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 4px;
  padding: 6px 4px 4px;
  border: 0;
  border-top: 2px solid transparent;
  background: transparent;
  color: var(--muted);
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
  min-width: 0;
  transition: color 160ms ease-out, border-color 160ms ease-out, background-color 160ms ease-out;
}
.shell-nav-item:hover { color: var(--text); }
.shell-nav-item.is-active {
  color: var(--mustard);
  border-top-color: var(--mustard);
}
.shell-nav-icon {
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
}
.shell-nav-icon svg { width: 22px; height: 22px; display: block; }
.shell-nav-label {
  font-size: 11px;
  letter-spacing: 0.04em;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  font-weight: 500;
}
@media (max-width: 480px) {
  .shell-nav-label { font-size: 10.5px; letter-spacing: 0.02em; }
}

/* More overflow — bottom sheet pinned above the shell-nav, with a
   dimmed backdrop covering the rest. CSS-only animation; JS toggles
   [hidden] + .is-open via a delegated handler in components.js. */
.shell-more-backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(0,0,0,0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  opacity: 0;
  transition: opacity 200ms ease-out;
}
.shell-more-backdrop.is-open { opacity: 1; }
.shell-more-backdrop[hidden] { display: none; }
.shell-more-sheet {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  margin-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px 14px 0 0;
  box-shadow: var(--shadow-2);
  padding: 16px 16px 12px;
  transform: translateY(16px);
  transition: transform 220ms ease-out;
}
.shell-more-backdrop.is-open .shell-more-sheet { transform: translateY(0); }
.shell-more-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 4px 6px 12px;
}
.shell-more-eyebrow {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.shell-more-close {
  width: 32px; height: 32px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--muted);
  cursor: pointer;
  transition: color 160ms ease-out, border-color 160ms ease-out, background-color 160ms ease-out;
}
.shell-more-close:hover { color: var(--text); border-color: var(--text); }
.shell-more-close svg { width: 16px; height: 16px; }
.shell-more-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
@media (max-width: 560px) {
  .shell-more-list { grid-template-columns: 1fr; }
}
.shell-more-link {
  display: grid;
  gap: 2px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  text-decoration: none;
  color: var(--text);
  transition: background-color 160ms ease-out, border-color 160ms ease-out;
}
.shell-more-link:hover { background: #38383E; border-color: #44444B; }
body.t-light .shell-more-link:hover { background: #E6DFD0; border-color: #C7BDA8; }
.shell-more-title {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 500;
  color: var(--heading);
  line-height: 1.2;
}
.shell-more-desc {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.35;
}

/* Reserve bottom space inside every shelled main so the fixed
   shell-nav never sits on top of content. login.html has no shell
   and is intentionally excluded. */
main.page,
main.dash {
  padding-bottom: calc(72px + 24px + env(safe-area-inset-bottom, 0px));
}

/* ───────────── Breadcrumb ───────────── */
.breadcrumb {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--heading);
  font-size: 14px;
  margin: 18px 0 8px;
  background: transparent; border: 0; padding: 4px 0;
  border-bottom: 1px solid transparent;
  transition: border-color 200ms ease-out;
  text-decoration: none;
  cursor: pointer;
}
.breadcrumb:hover { border-bottom-color: var(--heading); }
.breadcrumb .chev {
  width: 7px; height: 7px;
  border-left: 1.5px solid var(--heading);
  border-bottom: 1.5px solid var(--heading);
  transform: rotate(45deg);
  margin-right: 4px;
}

/* ───────────── Page body ───────────── */
.page {
  max-width: 1280px;
  margin: 0 auto;
  padding: 28px 64px 56px;
}
@media (max-width: 1100px) { .page { padding: 28px 32px 56px; } }

/* PR #6 v2 (2026-05-14): tool-page background bands. The page body
   itself becomes a softly tinted container, with the cream body
   showing around it on wide viewports. Form cards / tables / inputs
   inside the page sit on top of the band and keep their own
   backgrounds, so the band reads as scenery rather than as a flat
   wash. Hue assignments mirror the dashboard: amber for daily-use
   pages (print-labels, intake), sage for stock-adjacent pages and
   utility footers (full count, spot check, vendor copy, submissions,
   sku-audit), blue for invoices.

   2026-05-29 (D): page-band-sage is the count screen's wrapper. D's
   canvas is white with one anchor structural colour (forest, used in
   the chrome). A sage tint underneath competes with the forest bar
   for "the green of the page," so sage is flattened to paper-2
   (#fafaf7) — soft surface lift without a competing hue. Amber/blue
   bands remain in their hues for the pages that still use them. */
/* Phase-4 restyle: every page already overrides its band to var(--page)
   in its own inline block, so the shared rule collapses to --page too.
   Keeps the selectors live (markup still references them) but no longer
   paints a competing tint behind the new handoff surfaces. */
.page.page-band-amber,
.page.page-band-sage,
.page.page-band-blue {
  background: var(--page);
  border-radius: 0;
}

.page h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 36px;
  margin: 0 0 4px;
  color: var(--heading);
  letter-spacing: 0.005em;
}
.page .subhead {
  color: var(--muted);
  font-size: 13px;
  max-width: 70ch;
  margin: 0 0 22px;
}

/* ───────────── Buttons ───────────── */
/* Phase-4 restyle: 10px radius across the family, --primary-bg/-fg
   fills, --ghost-border on transparent for ghost, --c-tx for
   destructive. Hovers use --primary-bg-h / --surface-2. */
.btn-primary, .btn-ghost, .btn-link, .btn-destructive {
  font-family: inherit;
  border-radius: 10px;
  transition: background-color 200ms ease-out, transform 80ms ease-out, border-color 200ms ease-out;
  min-height: 44px;
}
.btn-primary {
  background: var(--primary-bg); color: var(--primary-fg);
  border: 1px solid var(--primary-bg);
  padding: 12px 18px;
  font-size: 14px; font-weight: 500;
  cursor: pointer;
}
.btn-primary:hover { background: var(--primary-bg-h); border-color: var(--primary-bg-h); }
.btn-primary:active { transform: scale(0.97); }
.btn-primary.full { width: 100%; min-height: 52px; font-size: 15px; }
.btn-primary[disabled] {
  background: var(--surface-2); color: var(--muted);
  border-color: var(--border); cursor: not-allowed;
  transform: none;
}
.btn-ghost {
  background: transparent; color: var(--text);
  border: 1px solid var(--ghost-border);
  padding: 11px 16px;
  font-size: 13px;
  min-height: 40px;
  cursor: pointer;
}
.btn-ghost:hover { background: var(--surface-2); }
.btn-ghost:active { transform: scale(0.97); }
.btn-ghost.sm { padding: 8px 12px; font-size: 12px; min-height: 34px; }
.btn-destructive {
  background: var(--c-tx); color: #ffffff;
  border: 1px solid var(--c-tx);
  padding: 12px 18px;
  font-size: 14px; font-weight: 500;
  cursor: pointer;
}
.btn-destructive:hover { filter: brightness(0.92); }
.btn-destructive:active { transform: scale(0.97); }
.btn-link {
  background: transparent; border: 0;
  padding: 6px 0; min-height: 0;
  color: var(--heading); font-size: 13px;
  border-bottom: 1px solid transparent; border-radius: 0;
  cursor: pointer;
}
.btn-link:hover { border-bottom-color: var(--heading); }

/* Button loading state — reusable across any action that pulls from
   Shopify or the session store. The .is-loading class is applied by
   setBtnLoading() in components.js; the button keeps its background
   (it is busy, not disabled), drops the :active scale, and ignores
   taps via pointer-events so a double-tap mid-flight is a no-op. The
   button's width is locked to its pre-loading rect, so the contents
   (spinner ± label) are centered via inline-flex and any overflow
   beyond the locked width is clipped — this is what keeps narrow .sm
   buttons (e.g. the row-level Resume) from reflowing the row.
   We don't use the `disabled` attribute on purpose — that is reserved
   for genuinely inert controls (see "visually disabled" convention). */
.btn-primary.is-loading,
.btn-ghost.is-loading,
.btn-destructive.is-loading {
  pointer-events: none;
  cursor: progress;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  white-space: nowrap;
  overflow: hidden;
}
.btn-primary.is-loading:active,
.btn-ghost.is-loading:active,
.btn-destructive.is-loading:active {
  transform: none;
}
/* Spinner: explicit display + box-sizing + will-change for iPad Safari.
   Without display: inline-block, the <span> defaults to inline display,
   and on iOS Safari that occasionally suppresses the width/height (the
   inline-flex parent's flex-item promotion is unreliable in some
   webkit versions). will-change hints the GPU compositor, which gets
   Safari to actually start the animation on a freshly-injected node —
   the precise bug the user hit on iPad. */
.btn-spinner {
  display: inline-block;
  box-sizing: border-box;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 800ms linear infinite;
  -webkit-animation: spin 800ms linear infinite;
  will-change: transform;
  flex-shrink: 0;
}
@keyframes spin { to { transform: rotate(360deg); } }
@-webkit-keyframes spin { to { -webkit-transform: rotate(360deg); } }

/* ───────────── Inputs ───────────── */
/* Phase-4 restyle: --field-bg/--field-border surfaces, --inset
   shadow, mustard focus ring (3px @ .35 alpha per handoff), 10px
   radius, --text body / --muted placeholder. */
.input, select.input, textarea.input {
  appearance: none;
  border: 1px solid var(--field-border);
  background: var(--field-bg);
  color: var(--text);
  border-radius: 10px;
  padding: 12px 14px;
  font-family: inherit;
  font-size: 14px;
  width: 100%;
  min-height: 44px;
  box-shadow: var(--inset);
  transition: box-shadow 150ms ease-out, border-color 150ms ease-out;
}
.input.lg { min-height: 52px; padding: 14px 16px; font-size: 16px; }
.input:focus, select.input:focus, textarea.input:focus {
  outline: 0;
  border-color: var(--mustard);
  box-shadow: 0 0 0 3px rgba(232,191,68,0.35);
}
.input::placeholder { color: var(--muted); }
.input.error { border-color: var(--c-tx); background: var(--c-bg); }
.input:disabled, select.input:disabled, textarea.input:disabled {
  color: var(--muted); background: var(--surface-2);
  border-color: var(--border); cursor: not-allowed;
}
textarea.input { min-height: 96px; resize: vertical; padding-top: 12px; }
/* Chevron triangle in select. Uses currentColor so it follows --text. */
select.input {
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 36px;
}
.field-label {
  display: block;
  font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.field { display: flex; flex-direction: column; }
.field + .field { margin-top: 16px; }
.field-help { font-size: 12px; color: var(--muted); margin-top: 6px; }
.field-help.error { color: var(--c-tx); }
.search-wrap { position: relative; }
.search-wrap > svg {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  color: var(--muted);
}
.search-wrap .input { padding-left: 42px; }

/* ───────────── Pills, badges, chips ───────────── */
/* Phase-4 restyle: handoff badge radius is 5px. Pills ride on ghost
   borders by default; status variants use the --m/c/s/o pairs. Badges
   use the action-token pairs (--new/--stk/--ret/--prc). */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  background: var(--surface);
  border: 1px solid var(--ghost-border);
  color: var(--text);
  white-space: nowrap;
}
.pill.p-edits    { border-color: var(--mustard); color: var(--warn-tx); }
.pill.p-failed   { border-color: var(--c-tx); color: var(--c-tx); }
.pill.p-approved { border-color: var(--m-tx); color: var(--m-tx); }
.pill.p-rejected { border-color: var(--c-tx); color: var(--c-tx); }
.pill.p-pending  { border-color: var(--ghost-border); color: var(--text); }

.badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
}
.badge.b-new      { background: var(--new-bg); color: var(--new-tx); }
.badge.b-stock    { background: var(--stk-bg); color: var(--stk-tx); }
.badge.b-return   { background: var(--ret-bg); color: var(--ret-tx); }
.badge.b-price    { background: var(--prc-bg); color: var(--prc-tx); }
.badge.b-intake   { background: var(--primary-bg); color: var(--primary-fg); }
.badge.b-count    { background: var(--surface-2); color: var(--text); border: 1px solid var(--ghost-border); }

.chip-strip { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; }
.chip {
  appearance: none;
  padding: 7px 14px;
  color: var(--text); font-size: 13px;
  border-radius: 5px;
  background: var(--surface);
  border: 1px solid var(--ghost-border);
  border-bottom: 2px solid var(--ghost-border);
  transition: background-color 200ms ease-out, border-color 200ms ease-out;
  min-height: 34px;
  cursor: pointer;
}
.chip:hover { background: var(--surface-2); }
.chip.is-active { border-bottom: 3px solid var(--mustard); font-weight: 500; }
.chip .n { color: var(--muted); margin-left: 6px; font-size: 12px; }
.chip.is-active .n { color: var(--heading); }

/* ───────────── Yellow note (dismissable) ───────────── */
.yellow-note {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--o-bg);
  border: 1px solid var(--mustard);
  color: var(--warn-tx);
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.5;
}
.yellow-note .x {
  margin-left: auto; cursor: pointer; opacity: 0.6;
  font-size: 14px; line-height: 1;
}

/* ───────────── Landing page ───────────── */
.landing-head {
  text-align: center;
  padding: 36px 0 12px;
}
.landing-head .wordmark {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--heading);
  display: inline-flex; align-items: center; gap: 10px;
}
.landing-head .wordmark .sparkle {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--mustard);
  box-shadow: 0 0 0 4px rgba(232,191,68,0.18);
}
.landing-head .subhead {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 8px;
}

.ask {
  text-align: center;
  margin: 24px auto 32px;
}
.ask h1 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 32px;
  color: var(--heading);
  margin: 0;
  letter-spacing: 0.005em;
}

/* Section header (between tile groups) */
.tile-section { max-width: 1100px; margin: 0 auto 28px; }
.tile-section + .tile-section { margin-top: 8px; }
.tile-section-head {
  margin: 0 4px 14px;
}
.tile-section-head h2 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 22px;
  color: var(--heading);
  margin: 0;
  letter-spacing: 0.005em;
}
.tile-section-head .desc {
  font-size: 13px;
  color: var(--muted);
  margin: 4px 0 0;
}

/* Tile grid — flexible column count via data-cols on the grid container */
.tile-grid {
  display: grid;
  gap: 18px;
}
.tile-grid[data-cols="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.tile-grid[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tile-grid[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tile-grid[data-cols="1"] { grid-template-columns: minmax(0, 1fr); max-width: 540px; margin: 0 auto; }
@media (max-width: 1100px) {
  .tile-grid[data-cols="4"] { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
  .tile-grid[data-cols="4"],
  .tile-grid[data-cols="3"],
  .tile-grid[data-cols="2"] { grid-template-columns: 1fr; }
}

.tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 22px 22px 20px;
  cursor: pointer;
  transition: transform 200ms ease-out, box-shadow 200ms ease-out, border-color 200ms ease-out;
  position: relative;
  text-align: left;
  min-height: 160px;
  display: flex; flex-direction: column;
  appearance: none; font-family: inherit;
  color: var(--text);
  text-decoration: none;
}
.tile:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
  border-color: var(--primary-bg);
}
.tile:active { transform: scale(0.97); transition: transform 80ms ease-out; }
.tile .icon {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--heading);
  display: grid; place-items: center;
  margin-bottom: 14px;
}
.tile .t-title {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 22px;
  color: var(--heading);
  margin-bottom: 4px;
  line-height: 1.15;
}
.tile .t-desc {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.45;
  margin-top: auto;
  padding-top: 8px;
}
.tile.featured {
  border-top: 4px solid var(--mustard);
  padding-top: 19px;
}

.landing-footer {
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  margin: 36px 0 8px;
}
.landing-footer .dot { margin: 0 10px; opacity: 0.5; }
.landing-footer strong { color: var(--heading); font-weight: 500; }

/* ───────────── Modal (sticky + generic) ───────────── */
/* Phase-4 restyle: --surface cards, --border hairlines, handoff
   --shadow, status icons on --m/c pairs. Backdrop kept on a dim
   black wash so both palettes share it without needing a token. */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.40);
  backdrop-filter: blur(2px);
  z-index: 90;
  display: grid; place-items: center;
  animation: backdrop-in 200ms ease-out both;
}
.modal-backdrop.is-out { animation: backdrop-out 200ms ease-in both; }
@keyframes backdrop-in  { from { opacity: 0 } to { opacity: 1 } }
@keyframes backdrop-out { from { opacity: 1 } to { opacity: 0 } }
.modal {
  width: min(520px, 92vw);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 32px 32px 24px;
  animation: modal-in 240ms ease-out both;
}
@keyframes modal-in {
  from { transform: translateY(-8px) scale(0.98); opacity: 0; }
  to   { transform: translateY(0) scale(1); opacity: 1; }
}
.modal h2 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 26px;
  margin: 0 0 8px;
  color: var(--heading);
}
.modal p {
  color: var(--text);
  font-size: 14px;
  line-height: 1.55;
  margin: 0 0 8px;
}
.modal .modal-meta {
  color: var(--muted);
  font-size: 13px;
  margin-bottom: 22px;
}
.modal-actions {
  display: flex; gap: 10px; justify-content: flex-end;
  margin-top: 18px;
}
.modal-icon {
  display: inline-grid; place-items: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--o-bg);
  color: var(--warn-tx);
  margin-bottom: 14px;
}
/* Verdict-modal variants — bumped to 56px and centered with the
   title because verdict modals are acknowledgement screens (not
   inline-with-text affordances like the mustard default). */
.modal--with-icon { position: relative; text-align: center; padding-top: 36px; }
.modal--with-icon .modal-icon {
  width: 56px; height: 56px;
  margin: 0 auto 14px;
}
.modal--with-icon h2 { margin-bottom: 6px; }
.modal--with-icon .modal-actions { justify-content: center; }
.modal-icon--approved { background: var(--m-bg); color: var(--m-tx); }
.modal-icon--rejected { background: var(--c-bg); color: var(--c-tx); }
/* X-close affordance for dismissible modals (verdict, etc).
   Positioned in the modal card's top-right corner. */
.modal-close {
  position: absolute; top: 10px; right: 12px;
  width: 32px; height: 32px;
  background: transparent; border: 0;
  color: var(--muted);
  font-size: 22px; line-height: 1;
  cursor: pointer; border-radius: 50%;
  display: grid; place-items: center;
}
.modal-close:hover { background: var(--surface-2); color: var(--heading); }
.modal-close:focus-visible { outline: 2px solid var(--primary-bg); outline-offset: 2px; }

/* Staff name picker — wide rows, primary initial circle, serif name */
.staff-picker { width: min(440px, 92vw); }
.staff-picker h2 { margin-bottom: 16px; }
.staff-picker .picker-row {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid transparent;
  cursor: pointer;
  background: transparent;
  width: 100%;
  text-align: left;
  appearance: none;
  font-family: inherit;
  min-height: 60px;
  transition: background-color 150ms ease-out, border-color 150ms ease-out;
}
.staff-picker .picker-row:hover {
  background: var(--surface-2);
  border-left-color: var(--primary-bg);
  border-left-width: 4px;
}
.staff-picker .picker-row .pick-init {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--primary-bg);
  color: var(--primary-fg);
  display: grid; place-items: center;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 16px;
}
.staff-picker .picker-row .pick-name {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 20px;
  color: var(--heading);
}

/* ───────────── Toast (bottom-right stack) ───────────── */
.toast-stack {
  position: fixed; right: 24px; bottom: 24px;
  z-index: 100;
  display: flex; flex-direction: column-reverse; gap: 10px;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border);
  padding: 14px 18px; border-radius: 14px;
  box-shadow: var(--shadow);
  font-size: 13.5px;
  min-width: 240px;
  max-width: 360px;
  display: flex; align-items: center; gap: 12px;
  animation: toast-in 250ms ease-out both;
  cursor: pointer;
}
.toast.is-out { animation: toast-out 220ms ease-in both; }
.toast .check {
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--mustard);
  color: #10203a;
  display: grid; place-items: center;
  font-weight: 700; font-size: 12px;
  flex: none;
}
.toast.error { background: var(--c-bg); color: var(--c-tx); border-color: var(--c-tx); }
.toast.error .check { background: var(--c-tx); color: #ffffff; }
@keyframes toast-in  { 0% { transform: translateX(40px); opacity: 0; } 100% { transform: translateX(0); opacity: 1; } }
@keyframes toast-out { 0% { opacity: 1; } 100% { transform: translateX(40px); opacity: 0; } }

/* ───────────── Login screen ───────────── */
.login-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}
.login-card {
  width: min(360px, 92vw);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 36px 32px 32px;
  text-align: center;
}
.login-card .wordmark {
  font-family: var(--serif);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--heading);
  display: inline-flex; align-items: center; gap: 10px;
  margin-bottom: 8px;
}
.login-card .wordmark .sparkle {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--mustard);
  box-shadow: 0 0 0 4px rgba(232,191,68,0.18);
}
.login-card .subhead {
  font-size: 12px;
  color: var(--muted);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: 24px;
}
.login-card .field { text-align: left; }
.login-card .err {
  color: var(--c-tx);
  font-size: 12px;
  margin-top: 8px;
  text-align: left;
}

/* ───────────── Animations (reusable utility classes) ───────────── */
.anim-pink-flash { animation: anim-pink-flash 1500ms ease-out both; }
@keyframes anim-pink-flash {
  0%   { background: var(--mustard-soft); }
  100% { background: transparent; }
}
.anim-mustard-glow { animation: anim-mustard-glow 600ms ease-out both; }
@keyframes anim-mustard-glow {
  0%   { box-shadow: 0 0 0 0 var(--mustard-soft); }
  60%  { box-shadow: 0 0 0 3px var(--mustard-soft); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.anim-slide-off-right { animation: anim-slide-off-right 400ms ease-in-out both; }
@keyframes anim-slide-off-right {
  to { transform: translateX(100%); opacity: 0; }
}
.anim-button-press { animation: anim-button-press 80ms ease-out; }
@keyframes anim-button-press {
  50%  { transform: scale(0.97); }
  100% { transform: scale(1); }
}
.anim-tile-hover {
  transition: transform 200ms ease-out, box-shadow 200ms ease-out;
}
.anim-tile-hover:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}
.anim-focus-ring { animation: anim-focus-ring 150ms ease-out both; }
@keyframes anim-focus-ring {
  to { box-shadow: 0 0 0 2px var(--mustard); }
}
.anim-content-slide-in { animation: anim-content-slide-in 250ms ease-out both; }
@keyframes anim-content-slide-in {
  from { transform: translateX(24px); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

/* ----- Documents stage stepper (Prompt C3 Fix C1) ----- */
.doc-stepper { margin: 4px 0 18px; }
.doc-stepper .ds-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 14px 18px;
}
.doc-stepper .ds-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  min-width: 92px;
}
.doc-stepper .ds-node {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 14px; font-weight: 600;
  background: var(--surface-2);
  border: 2px solid var(--border);
  color: var(--muted);
  transition: background-color 200ms ease-out, border-color 200ms ease-out, color 200ms ease-out, box-shadow 200ms ease-out;
}
.doc-stepper .ds-label {
  font-size: 12px; color: var(--muted);
  text-align: center; line-height: 1.2;
}
.doc-stepper .ds-line {
  flex: 1 1 30px;
  height: 2px;
  background: var(--border);
  min-width: 24px;
}
.doc-stepper .ds-line.is-completed { background: var(--primary-bg); }
/* Muted (default) */
.doc-stepper .ds-step.is-muted .ds-node { /* defaults already muted */ }
/* Upcoming = same visual as muted but slightly more present */
.doc-stepper .ds-step.is-upcoming .ds-node {
  border-color: var(--border);
  color: var(--muted);
}
/* Current — primary fill, mustard glow ring */
.doc-stepper .ds-step.is-current .ds-node {
  background: var(--primary-bg);
  border-color: var(--primary-bg);
  color: var(--primary-fg);
  box-shadow: 0 0 0 4px rgba(232, 191, 68, 0.25);
}
.doc-stepper .ds-step.is-current .ds-label {
  color: var(--heading); font-weight: 600;
}
/* Completed — primary outline + check */
.doc-stepper .ds-step.is-completed .ds-node {
  background: var(--surface);
  border-color: var(--primary-bg);
  color: var(--primary-bg);
}
.doc-stepper .ds-step.is-completed .ds-label {
  color: var(--heading);
}
/* Skipped (no-deposit path collapses DR + BI) */
.doc-stepper .ds-step.is-skipped .ds-node {
  width: 32px; height: 32px;
  border-style: dotted;
  border-color: var(--border);
  color: var(--muted);
  font-size: 12px;
}
.doc-stepper .ds-step.is-skipped .ds-label {
  color: var(--muted);
  text-decoration: line-through;
  text-decoration-color: var(--border);
}
.doc-stepper .ds-caption {
  margin: 8px 4px 0;
  font-size: 12px;
  color: var(--muted);
}
@media (max-width: 700px) {
  .doc-stepper .ds-step { min-width: 70px; }
  .doc-stepper .ds-node { width: 32px; height: 32px; font-size: 12px; }
  .doc-stepper .ds-step.is-skipped .ds-node { width: 24px; height: 24px; font-size: 10px; }
  .doc-stepper .ds-label { font-size: 10px; }
  .doc-stepper .ds-line { min-width: 12px; }
}
