:root {
  /* Palette */
  --ink:        #1a1a2e;
  --ink-soft:   #4a4a6a;
  --ink-muted:  #8888aa;
  --surface:    #f7f7fb;
  --surface-2:  #eeeef6;
  --white:      #ffffff;
  --accent:     #D01D5A;
  --accent-soft:#fde8ef;
  --accent-dark:#a8164a;
  --success:    #22c55e;
  --success-soft:#dcfce7;
  --warn:       #f59e0b;
  --warn-soft:  #fef3c7;
  --danger:     #ef4444;
  --danger-soft:#fee2e2;

  /* Order Status card outline (2026-09-15 s3). Its own pair rather than a
     reuse of --surface-2: the card body is --white and the header fill is
     --surface, and --surface-2 sits between them, so a border in that tone
     read as a seam rather than an edge. These are deliberately a step
     darker than any fill on the card, and flip in theme-dark below. */
  --pd-card-border:      #d6d3e6;
  --pd-card-border-open: #b4b0cf;

  /* Growth/Operations toggle (added 2026-08-05) — its own variables
     rather than reusing --ink/--white, since those two are text-role
     colors that intentionally invert in dark mode; the toggle needs its
     own light/dark pair instead. See html.theme-dark below for the dark
     values.
     Light-mode background corrected 2026-08-07 — the original value
     (#1a1a2e, a dark navy) was a deliberate early choice for contrast,
     but read as a heavy dark blob against the light topbar in practice
     (flagged directly by Dylan). Switched to a soft neutral matching the
     rest of the light-mode UI's own resting-surface color, with a
     muted-ink inactive label instead of translucent white (which needs a
     dark background to read at all). --growth-toggle-text-active is
     unchanged — it only ever sits on the solid pink active pill, which
     has enough contrast regardless of theme. */
  --growth-toggle-bg:          var(--surface-2);
  --growth-toggle-text:        var(--ink-muted);
  --growth-toggle-text-active: #ffffff;


  /* Priority colours */
  --high:       #ef4444;
  --high-soft:  #fee2e2;
  --med:        #f59e0b;
  --med-soft:   #fef3c7;
  --low:        #6b7280;
  --low-soft:   #f3f4f6;

  /* Type */
  --font-display: 'Poppins', system-ui, sans-serif;
  --font-body:    'Poppins', system-ui, sans-serif;

  /* Spacing */
  --radius:     10px;
  --radius-lg:  16px;
  --shadow:     0 1px 3px rgba(26,26,46,0.08), 0 4px 16px rgba(26,26,46,0.06);
  --shadow-lg:  0 8px 32px rgba(26,26,46,0.12);

  /* Status color families (consolidated 2026-07-24 for dark-mode theming —
     previously scattered hardcoded hex literals throughout the file;
     pulling them into variables here is what makes the html.theme-dark
     override block near the end of this file possible without hunting
     down every individual selector by hand). */
  --success-text:         #15803d;
  --success-strong:       #16a34a;
  --success-border-soft:  #86efac;
  --success-bg-strong:    #bbf7d0;
  --success-bg-stronger:  #4ade80;
  --success-bg-faint:     #f0fdf4;
  --warn-text:            #92400e;
  --warn-text-alt:        #b45309;
  --warn-border-alt:      #d97706;
  --danger-text:          #991b1b;
  --danger-text-alt:      #b91c1c;
  --danger-text-strong:   #dc2626;
  --danger-border-soft:   #fca5a5;
  --danger-bg-soft:       #fecaca;
  --danger-bg-faint:      #fef2f2;
  --info-badge-bg:        #e8ecff;
  --info-badge-text:      #4f6ef7;
  --info-soft:            #e0f2fe;
  --info-soft-hover:      #cfeafd;
  --cyan-bg:              #cffafe;
  --cyan-text:            #0e7490;
  --cyan-border:          #22d3ee;
  --cyan-border-hover:    #67e8f9;
  --ccm-accent:           #1cd5ff;
  --border-dashed:        #c2c0d8;
  --bg-soft:              #f6f7f9;

  /* White text on a colored (accent/success) background -- buttons,
     avatar circles, chat bubbles. Deliberately separate from --white
     (which means "card surface" and legitimately becomes dark in dark
     mode below) -- these need to stay pure white in both themes since
     the buttons/bubbles they sit on keep roughly the same brightness. */
  --on-accent:            #ffffff;

  /* Always-dark "chrome" bubbles — toast, both tooltip styles, and the
     code block below all keep a fixed dark-bg/light-text look regardless
     of page theme (same convention most dark-mode sites use for toasts/
     tooltips). Previously these all reused var(--ink)/var(--white), which
     would have inverted (and become unreadable) once those two variables
     themselves flip to their dark-mode meanings — see html.theme-dark
     near the end of this file. */
  --chrome-dark-bg:       #1a1a2e;
  --chrome-dark-text:     #ffffff;
  --code-text:            #e2e2ef;

  /* Remittance Review pairing-highlight pastels (2026-07-23) — four
     color pairs (bg + hover), one per simultaneous group on screen. */
  --remit-a-bg:           #f5f0ff;
  --remit-a-bg-hover:     #ece2ff;
  --remit-b-bg:           #eefaf3;
  --remit-b-bg-hover:     #dff5e8;
  --remit-c-bg:           #fff7e8;
  --remit-c-bg-hover:     #ffedc9;
  --remit-d-bg:           #eef6fb;
  --remit-d-bg-hover:     #ddedf7;
}

/* ---- Reset ---- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; -webkit-font-smoothing: antialiased; }
body { font-family: var(--font-body); background: var(--surface); color: var(--ink); line-height: 1.6; }
a { color: var(--accent); text-decoration: none; }
button { cursor: pointer; font-family: var(--font-body); }

/* =============================================
   LOGIN PAGE
   ============================================= */

.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #f0f2ff 0%, #f7f7fb 60%, #fff0f5 100%);
}

.login-container {
  width: 100%;
  max-width: 400px;
  padding: 2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2rem;
}

.login-brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-body);
}

.brand-badge {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 500;
  font-style: italic;
  font-size: 1.1rem;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1.5px solid var(--accent);
  padding: 0.5rem 1.1rem;
  border-radius: 10px;
  white-space: nowrap;
}

.login-card {
  width: 100%;
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 2.5rem;
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  text-align: center;
}

.login-card h1 {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 400;
  color: var(--ink);
  line-height: 1.2;
}

.login-sub {
  font-size: 0.9rem;
  color: var(--ink-soft);
  line-height: 1.6;
}

.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.875rem 1.5rem;
  background: var(--white);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--ink);
  transition: all 0.15s ease;
  box-shadow: var(--shadow);
}

.btn-google:hover {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  transform: translateY(-1px);
}

.btn-google:active { transform: translateY(0); }

.login-note {
  font-size: 0.775rem;
  color: var(--ink-muted);
}

.login-footer {
  display: flex;
  gap: 0.5rem;
  font-size: 0.775rem;
  color: var(--ink-muted);
  align-items: center;
}

.dot { color: var(--surface-2); }

/* =============================================
   PORTAL LAYOUT (post-login)
   ============================================= */

.portal-page { background: var(--surface); min-height: 100vh; }

/* Topbar */
.topbar {
  background: var(--white);
  border-bottom: 1px solid var(--surface-2);
  padding: 0 2rem;
  height: 58px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  /* 170, not 100 — bumped 2026-08-06 to fix the settings/notification
     dropdowns rendering behind the open Growth chat widget. The dropdowns
     have their own z-index:200 (.settings-menu-dropdown), which looks like
     it should already win over the panel's 160 — but z-index only
     resolves within a shared stacking context, and .topbar (position:
     sticky + z-index) creates its own. That capped the ENTIRE topbar
     subtree, dropdowns included, at 100 versus the panel's 160-161,
     regardless of the dropdown's own higher number. Raising the topbar's
     own z-index above the panel's fixes it for both dropdowns at once.
     Checked for regressions: nothing else sits in the 100-170 band that
     visually overlaps the topbar's own screen space (back-to-top-btn is
     bottom-left; growth-chat-edge-tab is vertically centered) — modals
     (200), the drag mask/toast/tooltips (500+) all stay above regardless. */
  z-index: 170;
}

.topbar-left { display: flex; align-items: center; gap: 0.6rem; }

/* ---- Agent name row (Sue, 2026-10-13) — injected by auth.js's
   injectAgentNavStrip() right after .topbar. One plain link per agent the
   user may talk to; each opens that agent's office in its own window.
   Not sticky, so it never covers a page's own sticky headers. ---- */
.agent-nav-strip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  padding: 0.35rem 2rem;
  background: var(--white);
  border-bottom: 1px solid var(--surface-2);
  font-size: 0.82rem;
}
.agent-nav-strip-label {
  color: var(--ink-muted);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.agent-nav-link {
  color: var(--ink);
  text-decoration: none;
  font-weight: 500;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  transition: color 0.15s, background 0.15s;
}
.agent-nav-link:hover { color: var(--accent); background: var(--accent-soft); }
.agent-nav-link--current { color: var(--accent); font-weight: 600; }
html.embed-mode .agent-nav-strip { display: none !important; }

/* ---- Back button (added 2026-08-05) — injected by auth.js's
   injectBackButton() as the first child of .topbar-left, before the
   brand link. Mirrors .settings-menu-btn's icon-button chrome for visual
   consistency with the rest of the topbar. ---- */
.topbar-back-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  color: var(--ink-muted);
  text-decoration: none;
  transition: color 0.15s, background 0.15s;
}
.topbar-back-btn:hover { color: var(--accent); background: var(--accent-soft); }

.topbar-brand-badge {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-style: italic;
  font-size: 0.8rem;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1.5px solid var(--accent);
  padding: 0.3rem 0.7rem;
  border-radius: 8px;
  white-space: nowrap;
}

/* Favicon-only home button (2026-09-09, Dylan's ask) — replaces the
   "MMS Internal Portal" text badge on every page's topbar. Height matches
   the old badge's footprint (~30px) so nothing around it reflows. */
.topbar-brand-favicon {
  display: block;
  height: 30px;
  width: 30px;
  /* True circle (2026-09-11 s3 follow-up — was border-radius:8px, which read
     as a rounded square). The favicon art is itself a rounded square, so a
     straight 50% clip would cut its corners — the 3px padding shrinks the art
     to 24px, whose outermost corner sits ~14.3px from center, safely inside
     the 15px circle. box-sizing keeps the 30px footprint so nothing reflows. */
  border-radius: 50%;
  padding: 3px;
  box-sizing: border-box;
  object-fit: contain;
  /* Brand-pink ring — box-shadow instead of border/outline so it follows the
     border-radius exactly and adds no layout size. */
  box-shadow: 0 0 0 2px #D01D5A;
}
.topbar-brand-link:hover .topbar-brand-favicon {
  opacity: 0.8;
  transition: opacity 0.15s;
}

.topbar-version {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--ink-muted);
  background: var(--surface);
  padding: 0.15rem 0.45rem;
  border-radius: 999px;
  letter-spacing: 0.02em;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
}
.topbar-version:hover {
  background: var(--surface-hover, var(--bg-soft));
  color: var(--ink);
}
.topbar-version:visited {
  color: var(--ink-muted);
}
/* Version number reads green for 30 min after a new zip upload
   (js/auth.js injectPortalVersion). Own colour on the span beats the
   inherited hover/visited colour above, so it stays green on hover.
   --success is a raw hex, legible on both themes. */
.topbar-version-num--fresh { color: var(--success); }

.topbar-right { display: flex; align-items: center; gap: 1rem; }

/* ---- Growth mode toggle (added 2026-08-05) — injected by auth.js's
   injectGrowthToggle() as a new .topbar child between .topbar-left and
   .topbar-right. .topbar's own justify-content:space-between centers it
   automatically — no positioning rules needed here.
   Uses the dedicated --growth-toggle-* variables (see :root / html.theme-
   dark above) rather than --ink/--white — those two are text-role colors
   that intentionally invert in dark mode, which is what made this pill
   turn near-white in dark mode when first built off of them. */
.growth-toggle-wrap {
  display: flex;
  background: var(--growth-toggle-bg);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
  /* True page-center (2026-09-09 s2 follow-up): the toggle used to sit between
     .topbar-left and .topbar-right under justify-content:space-between, which
     only centers it when both sides are the same width — swapping the text
     home button for the favicon shrank the left side and pushed the pills
     over. Absolute against the (already-positioned, sticky) .topbar centers it
     regardless of what either side holds. Falls back to in-flow on narrow
     screens where an absolute center would overlap the sides. 1200px, not
     900 (2026-09-24): a vertical monitor at ~1080px still overlapped the
     right side, which needs ~410px of the bar even with its buttons in ☰. */
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
@media (max-width: 1200px) {
  .growth-toggle-wrap { position: static; transform: none; }
}

.growth-toggle-pill {
  padding: 0.35rem 1rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--growth-toggle-text);
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}

.growth-toggle-pill--active {
  background: var(--accent);
  color: var(--growth-toggle-text-active);
}

.growth-toggle-pill:not(.growth-toggle-pill--active):hover {
  color: var(--growth-toggle-text-active);
}

/* ---- Page loading overlay (added 2026-08-05) — a small spinner shown
   from first paint until auth.js's requireAccess()/requireAnyAccess()
   resolves (hidePageLoadingOverlay()), then faded out to reveal the page
   underneath. Also re-shown briefly by the Growth toggle/back button
   right before navigating away (showPageLoadingOverlayAgain()), so
   leaving a page has the same visual treatment as arriving on one. */
.page-loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  opacity: 1;
  transition: opacity 0.12s ease;
}
.page-loading-overlay.page-loading-overlay--hidden {
  opacity: 0;
  pointer-events: none;
}
.page-loading-spinner {
  width: 22px;
  height: 22px;
  border: 2.5px solid var(--surface-2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: page-loading-spin 0.7s linear infinite;
}
@keyframes page-loading-spin {
  to { transform: rotate(360deg); }
}

/* ---- Back to top (added 2026-08-05) — portal-wide floating button,
   injected by auth.js's injectBackToTop(). Bottom-left, subtle by design
   — smaller and quieter than a primary action. (Originally placed here
   to stay clear of the old Dashboard/Funnel chat FABs' bottom-right
   corner; those were replaced 2026-08-05 session 5 by the Growth chat
   widget, whose collapsed state is a right-edge tab, not a corner FAB —
   no collision either way, so this position stayed as-is.) Hidden until
   the page is scrolled down a bit (see the scroll listener in auth.js). */
.back-to-top-btn {
  position: fixed;
  bottom: 1.75rem;
  left: 1.75rem;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--surface-2);
  background: var(--white);
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow);
  z-index: 140;
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.back-to-top-btn.back-to-top-btn--visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.back-to-top-btn:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

/* ---- Growth landing page (pages/growth.html, added 2026-08-05) ----
   Deliberately its own layout, not a reuse of .launchpad-grid's
   accordion-card grid — Dylan's call, wants room to diverge visually as
   this section grows. Reuses .card-icon/.card-title/.card-desc/
   .card-soon-badge/.launchpad-card-hit/.reorder-btn as-is (those are
   already generic, not launchpad-specific) rather than duplicating them. */
.growth-section-label {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 0.6rem 2px;
}

.growth-tools-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin-bottom: 1.75rem;
}

.growth-tool-card { min-height: 150px; }

.growth-tool-card--soon {
  opacity: 0.65;
  /* Deliberately NOT pointer-events:none like .launchpad-card--soon —
     these placeholder cards have no href/hit-target to begin with, but
     Dylan wants all 4 tool cards reorderable including the two
     not-built-yet ones, so the reorder arrows must stay clickable. */
}

.growth-reorder-controls { flex-direction: row; }

.growth-widgets-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}

.growth-widget-card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
}

.growth-widget-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.growth-widget-label {
  font-size: 0.78rem;
  color: var(--ink-muted);
}

.growth-widget-value {
  font-size: 1.4rem;
  font-weight: 600;
  margin: 0.4rem 0 0;
}

@media (max-width: 900px) {
  .growth-tools-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .growth-tools-grid { grid-template-columns: 1fr; }
}

.user-badge {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  position: relative;
  z-index: 2; /* added 2026-08-12 follow-up — must beat .topbar-avatar's z-index: 1, or the positioned stack avatars paint over this static one regardless of DOM order */
}

.user-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 1.5px solid var(--accent);
  object-fit: cover;
}

.btn-signout {
  font-size: 0.8rem;
  color: var(--ink-muted);
  background: none;
  border: 1px solid var(--surface-2);
  padding: 0.3rem 0.75rem;
  border-radius: 6px;
  transition: all 0.15s;
}

.btn-signout:hover { border-color: var(--danger); color: var(--danger); }

/* Main content */
.portal-main {
  max-width: 900px;
  margin: 0 auto;
  padding: 2.5rem 2rem;
}

/* Page header */
.page-header {
  margin-bottom: 2rem;
}

.page-header h1 {
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 0.25rem;
}

.page-header p {
  font-size: 0.875rem;
  color: var(--ink-soft);
}

/* Editable page descriptions (added 2026-08-10) — admin-only pencil
   button injected right after .page-header p (see auth.js's
   injectEditablePageDescription()). Small and inline so it doesn't
   compete with the description text itself for attention. */
.page-desc-edit-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 0.4rem;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  vertical-align: middle;
  transition: color 0.15s, background 0.15s;
}
.page-desc-edit-btn:hover { color: var(--accent); background: var(--accent-soft); }
.page-desc-edit-box { margin-top: 0.4rem; max-width: 700px; }

/* =============================================
   CHECKLIST PAGE
   ============================================= */

/* Product input bar */
.checklist-meta {
  background: var(--white);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.75rem;
  box-shadow: var(--shadow);
  display: flex;
  gap: 1rem;
  align-items: flex-end;
  flex-wrap: wrap;
}

.meta-field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  flex: 1;
  min-width: 200px;
}

.meta-field label {
  font-size: 0.775rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.meta-field input, .meta-field select {
  padding: 0.6rem 0.875rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.9rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--surface);
  transition: border-color 0.15s;
}

.meta-field input:focus, .meta-field select:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--white);
}

/* Progress bar */
.progress-bar-wrap {
  background: var(--surface-2);
  border-radius: 999px;
  height: 6px;
  margin-bottom: 1.75rem;
  overflow: hidden;
}

.progress-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), #7c9eff);
  border-radius: 999px;
  transition: width 0.3s ease;
  width: 0%;
}

.progress-label {
  font-size: 0.8rem;
  color: var(--ink-muted);
  margin-bottom: 0.5rem;
  display: flex;
  justify-content: space-between;
}

/* Section cards */
.checklist-section {
  background: var(--white);
  border-radius: var(--radius);
  margin-bottom: 1rem;
  box-shadow: var(--shadow);
  overflow: hidden;
}

.section-header {
  padding: 1rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  user-select: none;
  border-bottom: 1px solid var(--surface-2);
  transition: background 0.1s;
}

.section-header:hover { background: var(--surface); }

.section-title-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.section-num {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 0.2rem 0.5rem;
  border-radius: 4px;
}

.section-title {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
}

.section-progress {
  font-size: 0.8rem;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.chevron {
  width: 16px;
  height: 16px;
  color: var(--ink-muted);
  transition: transform 0.2s;
}

.section-header.open .chevron { transform: rotate(180deg); }

.section-body {
  padding: 0.5rem 0;
}

/* Checklist items */
.checklist-item {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
  padding: 0.75rem 1.5rem;
  transition: background 0.1s;
}

.checklist-item:hover { background: var(--surface); }

.checklist-item input[type="checkbox"] {
  width: 17px;
  height: 17px;
  margin-top: 2px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

.item-content { flex: 1; }

.item-text {
  font-size: 0.9rem;
  color: var(--ink);
  line-height: 1.5;
}

.item-text.checked {
  color: var(--ink-muted);
  text-decoration: line-through;
}

.priority-badge {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.15rem 0.45rem;
  border-radius: 4px;
  margin-left: 0.5rem;
  vertical-align: middle;
}

.priority-badge.high { background: var(--high-soft); color: var(--high); }
.priority-badge.med  { background: var(--med-soft);  color: var(--warn); }
.priority-badge.low  { background: var(--low-soft);  color: var(--low);  }

/* Notes field per section */
.section-notes {
  padding: 0.5rem 1.5rem 1rem;
}

.section-notes textarea {
  width: 100%;
  padding: 0.6rem 0.875rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.85rem;
  font-family: var(--font-body);
  color: var(--ink);
  resize: vertical;
  min-height: 70px;
  background: var(--surface);
  transition: border-color 0.15s;
}

.section-notes textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--white);
}

.section-notes label {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  display: block;
  margin-bottom: 0.4rem;
}

/* Action bar */
.action-bar {
  display: flex;
  gap: 1rem;
  margin-top: 2rem;
  flex-wrap: wrap;
}

.btn-primary {
  padding: 0.75rem 1.75rem;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: var(--radius);
  font-size: 0.9rem;
  font-weight: 600;
  transition: all 0.15s;
}

.btn-primary:hover {
  background: var(--accent-dark);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(79,110,247,0.3);
}

.btn-secondary {
  padding: 0.75rem 1.75rem;
  background: var(--white);
  color: var(--ink-soft);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.9rem;
  font-weight: 500;
  transition: all 0.15s;
}

.btn-secondary:hover { border-color: var(--ink-soft); }

/* Discrete/ghost variant — for manual fallback actions that shouldn't
   compete visually with primary actions (e.g. AR's "Sync from Shopify"
   once webhook-based sync exists — added 2026-07-22). Same shape as
   btn-secondary, just visually quieter: no border, muted text, smaller. */
.btn-discrete {
  padding: 0.4rem 0.7rem;
  background: transparent;
  color: var(--ink-soft);
  border: none;
  border-radius: var(--radius);
  font-size: 0.78rem;
  font-weight: 500;
  opacity: 0.75;
  transition: all 0.15s;
}

.btn-discrete:hover { opacity: 1; background: var(--surface-2); }

/* Toast notification */
.toast {
  position: fixed;
  bottom: 2rem;
  right: 2rem;
  background: var(--chrome-dark-bg);
  color: var(--chrome-dark-text);
  padding: 0.875rem 1.25rem;
  border-radius: var(--radius);
  font-size: 0.875rem;
  font-weight: 500;
  box-shadow: var(--shadow-lg);
  transform: translateY(120%);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  /* visibility is delayed on hide so the slide-down animation can finish
     first, but applied instantly on show. Without opacity/visibility, an
     empty toast (no message set yet) collapses to a short box — 120% of a
     short height isn't always enough to clear it past bottom:2rem, which
     was leaving a small sliver of the box visibly peeking up in the
     bottom-right corner even when no toast was actually showing. */
  transition: transform 0.3s ease, opacity 0.3s ease, visibility 0s linear 0.3s;
  z-index: 999;
  max-width: 320px;
}

.toast.show {
  transform: translateY(0);
  opacity: 1;
  visibility: visible;
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.toast.success { border-left: 4px solid var(--success); }
.toast.error   { border-left: 4px solid var(--danger); }

/* Past assessments table */
.assessments-table-wrap {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  margin-top: 2.5rem;
}

.assessments-table-wrap h2 {
  font-size: 1rem;
  font-weight: 600;
  padding: 1rem 1.5rem;
  border-bottom: 1px solid var(--surface-2);
  color: var(--ink);
}

.assessments-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.assessments-table th {
  text-align: left;
  padding: 0.6rem 1.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background: var(--surface);
  border-bottom: 1px solid var(--surface-2);
}

.assessments-table td {
  padding: 0.75rem 1.5rem;
  border-bottom: 1px solid var(--surface);
  color: var(--ink-soft);
}

.assessments-table tr:last-child td { border-bottom: none; }
.assessments-table tr:hover td { background: var(--surface); }

.score-pill {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
}

.score-pill.good { background: var(--success-soft); color: var(--success-text); }
.score-pill.fair { background: var(--warn-soft); color: var(--warn-text); }
.score-pill.poor { background: var(--danger-soft); color: var(--danger-text); }

/* Private Orders page (2026-07-28) — same pill shape as .score-pill,
   separate class since the three states here (draft created / needs
   review / failed) don't map cleanly onto good/fair/poor's semantics. */
.po-status-badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
}
.po-status-badge.po-status-ok   { background: var(--success-soft); color: var(--success-text); }
.po-status-badge.po-status-warn { background: var(--warn-soft); color: var(--warn-text); }
.po-status-badge.po-status-danger { background: var(--danger-soft); color: var(--danger-text); }
.po-status-badge.po-status-fail { background: var(--danger-soft); color: var(--danger-text); }

.empty-state {
  text-align: center;
  padding: 2.5rem;
  color: var(--ink-muted);
  font-size: 0.875rem;
}

.btn-reopen {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--accent);
  background: var(--accent-soft);
  border: none;
  padding: 0.3rem 0.75rem;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.15s;
}

.btn-reopen:hover {
  background: var(--accent);
  color: var(--on-accent);
}

/* =============================================
   HOME / LAUNCHPAD
   ============================================= */

.topbar-brand-link {
  text-decoration: none;
  display: flex;
  align-items: center;
}

.topbar-brand-link:hover .topbar-brand-badge {
  opacity: 0.85;
  transition: opacity 0.15s;
}

.home-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 2.5rem;
  flex-wrap: wrap;
  gap: 1rem;
}

/* Unified date/time position across Ops/Finance/Growth (2026-09-09 s2
   follow-up, Dylan's screenshots): the text block now SHRINKS (wrapping its
   own subtitle) instead of pushing the date onto a second row — Finance's
   longer subtitle was doing exactly that, so its clock rendered below-left
   while the other two sat top-right. The date block never wraps or shrinks. */
.home-header > div:first-child { flex: 1 1 0; min-width: 0; padding-right: 1rem; }
.home-header .home-date { flex-shrink: 0; white-space: nowrap; }

.home-header h1 {
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 300;
  color: var(--ink);
  margin-bottom: 0.25rem;
  letter-spacing: -0.02em;
}

.home-header p {
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.home-date {
  font-size: 0.825rem;
  color: var(--ink-muted);
  text-align: right;
  padding-top: 0.4rem;
}

.launchpad-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
}

/* ---- Card size variants (2026-09-18 s1, per user per section) ----
   Applied as a class on each section's grid containers (main grid, folder
   accordions, pinned area). No class = that section's historical default. */
.card-size--lg .launchpad-grid,
.card-size--lg.launchpad-grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.card-size--md .launchpad-grid,
.card-size--md.launchpad-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.card-size--sm .launchpad-grid,
.card-size--sm.launchpad-grid { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.card-size--lg .growth-tools-grid,
.card-size--lg.growth-tools-grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.card-size--md .growth-tools-grid,
.card-size--md.growth-tools-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.card-size--sm .growth-tools-grid,
.card-size--sm.growth-tools-grid { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.card-size--sm .launchpad-card { padding: 0.7rem 0.85rem; gap: 0.4rem; }
.card-size--sm .card-icon { width: 30px; height: 30px; }
.card-size--sm .card-title { font-size: 0.9rem; }
.card-size--sm .card-desc { font-size: 0.74rem; }
.card-size--md .launchpad-card { padding: 0.9rem 1rem; gap: 0.5rem; }
.card-size--md .card-icon { width: 34px; height: 34px; }
.card-size--md .card-title { font-size: 0.98rem; }
.card-size--md .card-desc { font-size: 0.78rem; }
.card-size--lg .launchpad-card { padding: 1.2rem 1.35rem; }
.card-size--lg .card-icon { width: 42px; height: 42px; }
/* The size picker itself */
.card-size-picker { display: inline-flex; gap: 2px; margin-left: 0.5rem; vertical-align: middle; }
.card-size-picker button {
  border: 1px solid var(--surface-2); background: var(--white); color: inherit;
  font-size: 11px; padding: 3px 8px; cursor: pointer; line-height: 1;
}
.card-size-picker button:first-child { border-radius: 6px 0 0 6px; }
.card-size-picker button:last-child { border-radius: 0 6px 6px 0; }
.card-size-picker button.active { background: var(--accent); color: #fff; border-color: var(--accent); }


.launchpad-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  text-decoration: none;
  color: inherit;
  border: 1.5px solid transparent;
  transition: all 0.18s ease;
  position: relative;
  cursor: pointer;
  text-align: left;
  width: 100%;
  font-family: var(--font-body);
  -webkit-appearance: none;
  appearance: none;
}

.launchpad-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-lg);
  transform: translateY(-2px);
}

.launchpad-card--soon {
  opacity: 0.65;
  cursor: default;
  pointer-events: none;
}

.card-icon {
  width: 38px;
  height: 38px;
  border-radius: 50%;   /* circles portal-wide, 2026-09-18 s1 (Dylan) — was 9px */
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.card-content { flex: 1; min-width: 0; }

/* ---- Edit-layout extras: folder picker, icon editor (2026-09-18 s1) ---- */
.card-folder-select {
  position: absolute; left: 8px; bottom: 8px; z-index: 3;
  font-size: 11px; padding: 2px 4px; max-width: 46%;
  border: 1px solid var(--surface-2); border-radius: 6px;
  background: var(--white); color: inherit;
}
.card-icon-edit-btn {
  position: absolute; right: 8px; bottom: 8px; z-index: 3;
  width: 24px; height: 24px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--surface-2); background: var(--white);
  color: inherit; font-size: 12px; line-height: 1;
}
.launchpad-new-folder-btn { margin-top: 0.7rem; font-size: 0.8rem; }
.icon-editor-overlay {
  position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,0.45);
  display: flex; align-items: center; justify-content: center;
}
.icon-editor-modal {
  background: var(--white); color: var(--ink); border-radius: 12px;
  padding: 1.1rem 1.2rem; width: min(380px, 92vw);
  border: 1px solid var(--surface-2); box-shadow: 0 12px 40px rgba(0,0,0,0.25);
}
.icon-preset-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }
.icon-preset-btn {
  aspect-ratio: 1; border-radius: 50%; border: 2px solid transparent;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.icon-preset-btn:hover { border-color: var(--accent); }
.icon-preset-btn--active { border-color: var(--accent); }


.card-category {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  display: block;
  margin-bottom: 0.3rem;
}

.card-title {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.3rem;
  line-height: 1.3;
}

/* Slimmer cards (2026-07-28) — same width, less height. Description wraps
   but is capped at 2 lines with an ellipsis rather than growing the card
   to fit, and rather than adding a separate "Read more" link — the whole
   card is already one big clickable hit-target (see .launchpad-card-hit
   below), so a second "read more" affordance would be redundant with
   what clicking the card already does. */
.card-desc {
  font-size: 0.8rem;
  color: var(--ink-soft);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-arrow {
  color: var(--accent);
  align-self: flex-end;
  opacity: 0;
  transform: translateX(-4px);
  transition: all 0.18s ease;
}

.launchpad-card:hover .card-arrow {
  opacity: 1;
  transform: translateX(0);
}

.card-soon-badge {
  position: absolute;
  top: 1rem;
  right: 1rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background: var(--surface-2);
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
}

/* Full-bleed invisible click target inside a .launchpad-card — lets us add
   the reorder-arrow controls as a sibling overlay without nesting a
   <button>/<a> inside another (invalid HTML, breaks on iOS Safari). See
   home.html's card renderer / Section 5 of the state doc. */
/* Launchpad edit-layout toolbar (added 2026-07-15) — the reorder arrows on
   each card only render while _layoutEditMode is true (see home.html);
   this button toggles that state. Card links/buttons are also disabled
   (pointer-events:none) while editing, so rearranging doesn't accidentally
   navigate away mid-edit. Scoped off body.layout-editing (2026-07-28 —
   was a single grid container's own class before the accordion/pin
   redesign introduced several grid containers at once). */
.launchpad-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 0.75rem;
}

.launchpad-edit-btn {
  padding: 0.45rem 0.9rem;
  font-size: 0.82rem;
}

body.layout-editing .launchpad-card-hit {
  pointer-events: none;
}

body.layout-editing .launchpad-card {
  cursor: default;
}

.launchpad-card-hit {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  text-decoration: none;
  color: inherit;
}

.card-reorder-controls {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.reorder-btn {
  width: 24px;
  height: 20px;
  border: none;
  background: var(--surface-2);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--ink-muted);
  font-size: 0.6rem;
  line-height: 1;
  -webkit-appearance: none;
  appearance: none;
}

.reorder-btn:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent);
}

.reorder-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Pin-to-top toggle (2026-07-28) — sits in the same corner slot as
   .card-reorder-controls above; the two are mutually exclusive (pin
   shows when NOT editing, reorder arrows show when editing — see
   renderCardHtml() in home.html), so they can safely share positioning. */
.card-pin-btn {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 2;
  width: 26px;
  height: 26px;
  border: none;
  background: transparent;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--ink-muted);
  opacity: 0;
  transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease;
  -webkit-appearance: none;
  appearance: none;
}

.launchpad-card:hover .card-pin-btn,
.card-pin-btn--active {
  opacity: 1;
}

.card-pin-btn:hover {
  background: var(--surface-2);
  color: var(--accent);
}

.card-pin-btn--active {
  color: var(--accent);
}

/* Pinned section (2026-07-28) — hidden entirely via inline style when the
   user has nothing pinned (see home.html); default state for every user
   is everything living under the category accordions below instead. */
/* Version Updates page (2026-07-28) — one card per "## " heading in the
   uploaded doc, newest at the top (Dylan writes it that way; nothing here
   re-sorts). Deliberately plain — this is a changelog, not a dashboard. */
.vu-entry {
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1.25rem 1.5rem;
  margin-bottom: 1rem;
}

.vu-entry-heading {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.75rem;
}

.vu-list {
  margin: 0;
  padding-left: 1.25rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
  line-height: 1.7;
}

.vu-list li { margin-bottom: 0.35rem; }
.vu-list li:last-child { margin-bottom: 0; }

.vu-plain {
  color: var(--ink-soft);
  font-size: 0.9rem;
  line-height: 1.6;
  margin-bottom: 0.5rem;
}

.launchpad-pinned {
  margin-bottom: 1.75rem;
}

.launchpad-section-label {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 0.75rem;
}

/* Category accordions (2026-07-28) — collapsed by default (Dylan's
   explicit call, matches the "organize/declutter" goal), state is
   in-memory only (resets to all-collapsed on every page load, no
   persistence — a much smaller feature than the pin/reorder state,
   easy to add later if it turns out to matter). */
.launchpad-accordions {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* Folder wraps on the Finance/Growth landings (2026-09-18 s3, Dylan's
   screenshot): the wrap div is inserted directly after the card grid with no
   spacing, so the first folder accordion hugged the bottom card row. :empty
   guard keeps pages without folders free of a phantom gap. */
#financeToolFolders, #growthToolFolders {
  margin-top: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
#financeToolFolders:empty, #growthToolFolders:empty { margin-top: 0; }

.accordion-category {
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.accordion-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem 1.25rem;
  position: relative;
  cursor: pointer;
}

.accordion-header:hover {
  background: var(--surface);
}

/* Full-bleed invisible click target, same sibling-not-parent pattern as
   .launchpad-card-hit — .accordion-header itself is a plain <div>, not a
   <button>, specifically so the real <button> reorder controls below can
   be DOM siblings rather than nested inside another button (invalid
   HTML, breaks on iOS Safari — see the state doc's Section 10 note on
   this exact anti-pattern elsewhere in the portal). */
.accordion-header-hit {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.accordion-chevron {
  position: relative;
  z-index: 2;
  color: var(--ink-muted);
  flex-shrink: 0;
  transition: transform 0.18s ease;
  pointer-events: none;
}

.accordion-chevron--open {
  transform: rotate(90deg);
}

.accordion-title {
  position: relative;
  z-index: 2;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
  flex: 1;
  pointer-events: none;
}

.accordion-count {
  position: relative;
  z-index: 2;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--ink-muted);
  background: var(--surface-2);
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  flex-shrink: 0;
  pointer-events: none;
}

/* Sits ABOVE .accordion-header-hit (z-index 2 vs 1) so a click on these
   real <button> elements registers on them, not the full-bleed toggle
   underneath — same layering trick .card-reorder-controls/.card-pin-btn
   already use against .launchpad-card-hit. No stopPropagation needed. */
.accordion-reorder-controls {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-left: 0.5rem;
}

.accordion-body {
  padding: 0 1.25rem 1.25rem;
}

.accordion-body .launchpad-grid {
  padding-top: 0.25rem;
}

/* Modal option, "coming soon" variant — used for Merchant Center Monitor
   inside the Marketing Tools modal (not a dedicated card anymore). */
.modal-option--soon {
  opacity: 0.6;
  cursor: default;
}

.modal-option--soon .modal-option-soon-badge {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background: var(--surface-2);
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  flex-shrink: 0;
}

/* Profile modal (added 2026-07-15) */
.profile-modal-card {
  max-width: 360px;
}

.profile-modal-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  padding: 0.5rem 0 1rem;
}

.profile-avatar-preview {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--surface-2);
}

.profile-name-label {
  font-weight: 600;
  color: var(--ink);
}

.profile-modal-actions {
  display: flex;
  gap: 0.6rem;
}

.profile-upload-btn {
  cursor: pointer;
}

.profile-modal-status {
  font-size: 0.8rem;
  color: var(--ink-muted);
  min-height: 1.1em;
}

/* Responsive */
@media (max-width: 600px) {
  .topbar { padding: 0 1rem; }
  .agent-nav-strip { padding: 0.35rem 1rem; }
  .portal-main { padding: 1.5rem 1rem; }
  .checklist-meta { flex-direction: column; }
  .action-bar { flex-direction: column; }
  .btn-primary, .btn-secondary { width: 100%; text-align: center; }
  .launchpad-grid { grid-template-columns: 1fr; }
}

/* =============================================
   SHOPIFY ASSISTANT — CHAT UI
   ============================================= */

.assistant-intake {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.75rem;
  box-shadow: var(--shadow);
  margin-bottom: 1.5rem;
}

.intake-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.25rem;
}

.intake-sub {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: 1.25rem;
}

.intake-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.875rem;
}

@media (max-width: 600px) {
  .intake-grid { grid-template-columns: 1fr; }
}

/* Chat container */
.chat-container {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
  height: calc(100vh - 240px);
  min-height: 500px;
}

.chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--surface-2);
  background: var(--white);
}

.chat-product-label {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
}

/* Messages */
.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  background: var(--surface);
}

.chat-message {
  display: flex;
  max-width: 85%;
  min-width: 0; /* flex items default to min-width:auto (their content's intrinsic width) — without this override, wide content (e.g. a table) prevents the bubble from ever shrinking to fit a narrow container, forcing clipped overflow instead of wrapping */
  align-items: flex-start;
  gap: 0.5rem;
}

.chat-message--user {
  align-self: flex-end;
  flex-direction: row-reverse;
}

.chat-message--assistant {
  align-self: flex-start;
}

.chat-bubble {
  padding: 0.75rem 1rem;
  border-radius: 14px;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ink);
  min-width: 0;
  overflow-wrap: break-word;
  word-break: break-word;
}

.chat-message--user .chat-bubble {
  background: var(--accent);
  color: var(--on-accent);
  border-bottom-right-radius: 4px;
}

.chat-message--assistant .chat-bubble {
  /* Claude-like restyle (2026-08-06, per Dylan's ask) — was background:
     var(--white); border: 1px solid var(--surface-2); box-shadow:
     var(--shadow); border-bottom-left-radius: 4px (a bordered card,
     mirroring the user bubble's look). Removed all four — assistant
     responses now render as plain text directly on .chat-messages'
     background, with no visible container of their own. User bubbles
     above are untouched — this only affects the assistant side, and
     since this is the shared .chat-bubble class, it takes effect
     everywhere at once: David and Zipp (widget + dedicated page),
     Customer Service, and Shopify Assistant. Horizontal padding dropped
     to 0 since there's no card edge left to inset from; vertical padding
     kept for the same breathing room between messages as before. */
  padding: 0.75rem 0;
}

.chat-bubble code {
  font-family: monospace;
  font-size: 0.8rem;
  background: var(--surface-2);
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
}

.chat-message--user .chat-bubble code {
  background: rgba(255,255,255,0.2);
}

/* Typing indicator */
/* Typing indicator (restyled 2026-08-06 to add rotating "thinking"
   phrases — see advisor.js's/assistant.js's ADVISOR_THINKING_PHRASES/
   ASSISTANT_THINKING_PHRASES) — .chat-typing-bubble wraps the text label
   and the dots together; .chat-typing itself is now just the three dots,
   padding moved to the outer .chat-bubble (which already gets it from
   the shared/assistant-side rules) since this is no longer the only
   thing in the bubble. */
.chat-typing-bubble {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.chat-typing-label {
  font-size: 0.85rem;
  color: var(--ink-muted);
  font-style: italic;
}
.chat-typing {
  display: flex;
  gap: 5px;
  align-items: center;
}

.chat-typing span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ink-muted);
  animation: bounce 1.2s infinite;
}

.chat-typing span:nth-child(2) { animation-delay: 0.2s; }
.chat-typing span:nth-child(3) { animation-delay: 0.4s; }

@keyframes bounce {
  0%, 60%, 100% { transform: translateY(0); }
  30% { transform: translateY(-6px); }
}

/* Input bar */
.chat-input-wrap {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--surface-2);
  background: var(--white);
  flex-shrink: 0; /* never let this row get squeezed/hidden when the container is narrow or short */
}
.chat-input-wrap > button { flex-shrink: 0; }

.chat-input {
  flex: 1;
  min-width: 0; /* without this, a textarea's intrinsic content width can prevent the row from shrinking below it in a narrow container, forcing the whole row to overflow (and then get clipped by an ancestor's overflow:hidden) instead of shrinking gracefully */
  padding: 0.65rem 0.875rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.9rem;
  font-family: var(--font-body);
  color: var(--ink);
  resize: none;
  line-height: 1.5;
  background: var(--surface);
  transition: border-color 0.15s;
  max-height: 120px;
  overflow-y: auto;
}

/* Explicit fixed size (added 2026-08-06) — matches .chat-send-btn's own
   treatment exactly. The generic .btn-secondary/.btn-sm classes this
   used before are meant for text buttons (padding-driven width, no
   flex-shrink/grow pinning) — fine for most uses, but not deterministic
   enough for an icon-only button sharing a flex row with a shrinking
   textarea. Pinning this to a fixed circle removes the ambiguity
   entirely regardless of container width. */
.advisor-attach-btn {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0; flex-grow: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 0; font-size: 1rem; line-height: 1;
  background: var(--surface); border: 1.5px solid var(--surface-2); color: var(--ink-soft);
  cursor: pointer; transition: border-color 0.15s, background 0.15s;
}
.advisor-attach-btn:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-dark); }

.chat-input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--white);
}

.chat-send-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--accent);
  border: none;
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all 0.15s;
}

.chat-send-btn:hover { background: var(--accent-dark); transform: scale(1.05); }
.chat-send-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }

/* =============================================
   MODAL
   ============================================= */

.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(26,26,46,0.5);
  z-index: 200;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.modal-overlay.open { display: flex; }

.modal-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 480px;
  max-height: 80vh;
  overflow-y: auto;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--surface-2);
}

.modal-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}

.modal-close {
  background: none;
  border: none;
  color: var(--ink-muted);
  padding: 0.25rem;
  cursor: pointer;
  border-radius: 6px;
  display: flex;
  align-items: center;
}

.modal-close:hover { background: var(--surface-2); color: var(--ink); }

.modal-options { padding: 1rem; }

.modal-option {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  border: 1.5px solid var(--surface-2);
  transition: all 0.15s;
  margin-bottom: 0.5rem;
}

.modal-option:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.modal-option-icon {
  width: 42px;
  height: 42px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.modal-option-content { flex: 1; }

.modal-option-title {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.2rem;
}

.modal-option-desc {
  display: block;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.modal-divider {
  height: 1px;
  background: var(--surface-2);
  margin: 1rem 0;
}

.modal-option-label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 0.75rem;
}

.modal-loading, .modal-empty {
  text-align: center;
  padding: 1.5rem;
  font-size: 0.85rem;
  color: var(--ink-muted);
}

.modal-session-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.875rem 1rem;
  border-radius: var(--radius);
  border: 1px solid var(--surface-2);
  text-decoration: none;
  color: inherit;
  margin-bottom: 0.5rem;
  transition: all 0.15s;
}

.modal-session-row:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.session-info { display: flex; flex-direction: column; gap: 0.2rem; }

.session-product {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
}

.session-meta {
  font-size: 0.775rem;
  color: var(--ink-muted);
}

.session-resume {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--accent);
  flex-shrink: 0;
}

/* Mark complete button */
.btn-complete {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--success-text);
  background: var(--success-soft);
  border: none;
  padding: 0.3rem 0.75rem;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.15s;
}

.btn-complete:hover { background: var(--success); color: var(--on-accent); }

/* =============================================
   MARKETING DASHBOARD
   ============================================= */

.dash-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 2rem;
  flex-wrap: wrap;
  gap: 1rem;
}

.dash-controls {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.dash-month-select {
  padding: 0.5rem 0.875rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.875rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--white);
  cursor: pointer;
}

.dash-section-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 0.875rem;
}

/* Loading */
.dash-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 4rem;
  color: var(--ink-soft);
  font-size: 0.875rem;
}

.dash-spinner {
  width: 20px;
  height: 20px;
  border: 2px solid var(--surface-2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.dash-error {
  background: var(--danger-soft);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  color: var(--danger);
  font-size: 0.875rem;
}

.dash-cpc-warning {
  align-items: flex-start;
  gap: 0.5rem;
  background: var(--warn-soft);
  color: var(--warn-text);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  font-size: 0.8rem;
  line-height: 1.5;
  margin-bottom: 1.25rem;
}
.dash-cpc-warning-icon { flex-shrink: 0; }

/* Same shape as .dash-cpc-warning, neutral/info tone instead of amber —
   used for FYI-only notes (partial refunds, unmatched order numbers) that
   aren't flagged for removal, just worth knowing about. Added 2026-08-07
   alongside checkCpcCancelledOrders() in dashboard.js. */
.dash-cpc-info {
  align-items: flex-start;
  gap: 0.5rem;
  background: var(--info-badge-bg);
  color: var(--info-badge-text);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  font-size: 0.8rem;
  line-height: 1.5;
  margin-bottom: 1.25rem;
}

.dash-sheet-link {
  display: inline-flex;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.dash-sheet-link:hover { opacity: 0.8; transform: scale(1.05); }

/* KPI grid */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(155px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.kpi-card {
  background: var(--white);
  border-radius: var(--radius);
  padding: 1rem 1.125rem;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  border-left: 3px solid transparent;
  position: relative;
}

.kpi-card.kpi-good { border-left-color: var(--success); }
.kpi-card.kpi-warn { border-left-color: var(--warn); }
.kpi-card.kpi-bad  { border-left-color: var(--danger); }

/* GA4-vs-Shopify data source distinction (added 2026-07-31) — deliberately
   NOT reusing --success/--accent/--low, since those already mean
   Organic/Paid/Other on this same page's channel bars further down;
   using them here too would make two unrelated things look connected.
   Blue = GA4-sourced, Shopify's own brand green = Shopify-sourced, amber
   = Conversion Rate specifically (a blend of both sources). */
.kpi-card.kpi-source-ga4      { border-left-color: #4f6ef7; }
.kpi-card.kpi-source-shopify  { border-left-color: #95BF47; }
.kpi-card.kpi-source-blend    { border-left-color: var(--warn); }

.kpi-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  display: block;
  padding-right: 20px;
}

.kpi-value {
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.2;
}

.kpi-sub {
  font-size: 0.72rem;
  color: var(--ink-muted);
}

/* ROAS/PAAS bar */
.roas-bar {
  background: var(--white);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  box-shadow: var(--shadow);
  margin-bottom: 0.75rem;
}

.roas-bar-inner {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.roas-bar-item { display: flex; flex-direction: column; gap: 0.4rem; }

.roas-bar-label {
  display: flex;
  justify-content: space-between;
  font-size: 0.825rem;
  font-weight: 500;
  color: var(--ink);
}

.roas-bar-label small { color: var(--ink-muted); font-weight: 400; }

.roas-track {
  height: 8px;
  background: var(--surface-2);
  border-radius: 999px;
  position: relative;
  overflow: visible;
}

.roas-fill {
  height: 100%;
  border-radius: 999px;
  transition: width 0.6s ease;
}

.roas-fill.good { background: var(--success); }
.roas-fill.warn { background: var(--warn); }

.roas-target-line {
  position: absolute;
  top: -4px;
  width: 2px;
  height: 16px;
  background: var(--ink-muted);
  border-radius: 1px;
}

/* Campaign table */
.dash-table-wrap {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow-x: auto;
}

.dash-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.825rem;
  min-width: 900px;
}

.dash-table th {
  text-align: left;
  padding: 0.6rem 1rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  background: var(--surface);
  border-bottom: 1px solid var(--surface-2);
  white-space: nowrap;
}

.dash-table td {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--surface);
  color: var(--ink-soft);
  white-space: nowrap;
}

.dash-table tr:last-child td { border-bottom: none; }
.dash-table tr:hover td { background: var(--surface); }

.campaign-name {
  font-weight: 600;
  color: var(--ink);
  font-size: 0.85rem;
}

.dash-table td.pos { color: var(--success-text); font-weight: 600; }
.dash-table td.neg { color: var(--danger); font-weight: 600; }

.dash-updated {
  font-size: 0.75rem;
  color: var(--ink-muted);
  margin-top: 1rem;
  text-align: right;
}

/* Toggle group */
.toggle-group {
  display: flex;
  background: var(--surface-2);
  border-radius: var(--radius);
  padding: 3px;
  gap: 2px;
}

.toggle-btn {
  padding: 0.4rem 0.875rem;
  font-size: 0.8rem;
  font-weight: 500;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  transition: all 0.15s;
  position: relative;
}

.toggle-btn.active {
  background: var(--white);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.toggle-btn:hover:not(.active) { color: var(--ink); }

/* Small unread-style indicator — currently only used on the Delay Orders
   page's READY tab button, to flag there's at least one order in it
   without requiring a click to check. */
.tab-badge-dot {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--danger);
  box-shadow: 0 0 0 2px var(--surface-2);
}

/* Growth indicators */
.growth-good { color: var(--success-text); font-weight: 600; }
.growth-bad  { color: var(--danger); font-weight: 600; }

/* Sub-tab group (inside All Time view) */
.sub-tab-group {
  display: inline-flex;
  background: var(--surface-2);
  border-radius: var(--radius);
  padding: 3px;
  gap: 2px;
}

.sub-tab-btn {
  padding: 0.45rem 1rem;
  font-size: 0.825rem;
  font-weight: 500;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  transition: all 0.15s;
}

.sub-tab-btn.active {
  background: var(--white);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.sub-tab-btn:hover:not(.active) { color: var(--ink); }

/* =============================================
   INTEGRATIONS MAP
   ============================================= */

.integrations-section {
  margin-top: 2.5rem;
}

/* Map card + info panel (changed 2026-07-24 — panel now overlays the
   map's right edge rather than sitting as a flex sibling, so the map
   never gets narrower when the panel opens). Falls back to normal
   stacking below the map on narrow viewports, where an overlay would
   cover too much of the diagram to be usable. */
.integrations-layout {
  position: relative;
}
@media (max-width: 900px) {
  .node-info-panel {
    position: static !important;
    width: 100% !important;
    margin-top: 1.25rem;
  }
}

.integrations-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  box-shadow: var(--shadow);
}

.integrations-legend {
  display: flex;
  gap: 1.5rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--surface-2);
  flex-wrap: wrap;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.legend-line {
  display: inline-block;
  width: 28px;
  height: 0;
  border-top: 1.5px solid var(--ink-muted);
}

.legend-dashed {
  border-top: 1.5px dashed var(--border-dashed);
}

/* =============================================
   INTEGRATIONS MAP PAGE
   ============================================= */

.integrations-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  box-shadow: var(--shadow);
}

.integrations-toolbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.zoom-hint {
  font-size: 0.78rem;
  color: var(--ink-muted);
  margin-left: 0.5rem;
}

.integrations-canvas {
  width: 100%;
  height: 600px;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface);
  position: relative;
  cursor: grab;
  user-select: none;
  display: flex;
  align-items: center;
  justify-content: center;
}

.integrations-viewport {
  width: 900px;
  height: 640px; /* fallback — actual height is set per-view by switchMapView() in integrations-map.js, since each view's SVG has a different total height */
  position: relative;
  transform-origin: center center;
  transition: transform 0.05s linear;
  flex-shrink: 0;
}

.integrations-viewport svg {
  width: 100%;
  height: 100%;
  display: block;
}

.map-node:hover rect:first-of-type {
  filter: brightness(0.97);
}

.integrations-legend {
  display: flex;
  gap: 1.5rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--surface-2);
  flex-wrap: wrap;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.legend-line {
  display: inline-block;
  width: 28px;
  height: 0;
  border-top: 1.5px solid var(--ink-muted);
}

.legend-dashed {
  border-top: 1.5px dashed var(--border-dashed);
}

/* Node info panel */
.node-info-panel {
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg, var(--shadow));
  padding: 1.5rem;
  width: 300px;
  position: absolute;
  top: 0;
  right: 0;
  z-index: 5;
}

.code-modal-pre {
  background: #1a1a2e;
  color: #e8e8f0;
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  font-size: 0.8rem;
  line-height: 1.6;
  overflow-x: auto;
  white-space: pre;
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  max-height: 55vh;
}

.info-panel-coderefs {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--surface-2);
}
.info-panel-coderef-link {
  display: block;
  text-align: left;
  background: none;
  border: none;
  color: var(--accent);
  font-size: 0.82rem;
  padding: 0.3rem 0;
  cursor: pointer;
  text-decoration: underline;
}
.info-panel-coderef-link:hover { color: var(--accent-dark, var(--accent)); }

.info-panel-shared-note {
  margin-top: 0.75rem;
  padding: 0.6rem 0.75rem;
  background: var(--surface);
  border-left: 3px solid #8b5cf6;
  border-radius: 0 6px 6px 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.tree-chevron { pointer-events: none; }

.node-info-panel h3 {
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.5rem;
  padding-right: 2rem;
}

.node-info-panel p {
  font-size: 0.875rem;
  color: var(--ink-soft);
  line-height: 1.6;
}

@media (max-width: 600px) {
  .integrations-canvas { height: 420px; }
}

/* =============================================
   GROWTH CHAT WIDGET (added 2026-08-05, session 5)
   Replaces the old per-tab Dashboard/Funnel Assistant chats (removed
   same session) — one shared widget across every Growth-side page
   instead of two separate simple Q&A bots, since David's own tools
   (get_campaign_summary/get_funnel_summary) now cover that same ground
   plus a lot more. Evolves the removed widget's exact "quarter-of-page
   docked side panel" shape (proven UX, redesigned into that form
   2026-07-31) rather than starting from scratch — adds a resize handle,
   a tab switcher (David/Assistant), and a pop-out-to-real-window button.
   ============================================= */

.growth-chat-edge-tab {
  position: fixed;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  width: 34px;
  height: 64px;
  border-radius: 10px 0 0 10px;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-lg);
  cursor: pointer;
  z-index: 150;
  transition: background 0.15s, width 0.15s;
}
.growth-chat-edge-tab:hover { background: var(--accent-dark); width: 40px; }
.growth-chat-edge-tab--hidden { display: none; }

/* Starts below the topbar (58px, sticky), same as the widget this
   replaces, so sign-out/settings/avatar stay reachable while open. */
.growth-chat-panel {
  position: fixed;
  top: 58px;
  right: 0;
  bottom: 0;
  min-width: 340px;
  background: var(--white);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 160;
  transform: translateX(100%);
  transition: transform 0.22s ease;
}
.growth-chat-panel.open { transform: translateX(0); }

/* Bottom-right corner dock mode (added 2026-08-06, per Dylan's ask for a
   4th widget option alongside Pop Out/Reset Width/Collapse) — a floating
   box anchored to the bottom-right corner, like a traditional Intercom/
   Drift-style chat widget, instead of the default full-height side
   panel. Toggled via growthChatDockCornerBtn — see
   toggleGrowthChatDockMode() in growth-chat-widget.js.
   Resizable as of 2026-08-07, per Dylan's ask — width/height are now set
   inline by JS (growthChatCornerWidth/Height, applied in
   applyGrowthChatDockMode()) instead of a fixed 380x600 !important box.
   min-width/min-height here are just a CSS-level floor matching the JS
   constants (GROWTH_CHAT_CORNER_MIN_WIDTH/HEIGHT) — belt-and-suspenders
   in case inline styles haven't applied yet on first paint. */
.growth-chat-panel.growth-chat-dock-corner {
  top: auto;
  right: 20px;
  bottom: 20px;
  min-width: 320px;
  min-height: 380px;
  border-radius: 12px;
}

/* Fixed 2026-08-11 — found live: the base closed-state transform below
   (translateX(100%)) only slides the panel by its OWN width, which is
   exactly right for side mode (flush against right:0) but leaves a
   sliver still inside the viewport in corner mode, since corner mode
   sits 20px in from the edge. That leftover sliver isn't interactive —
   it's just visual — but it looked clickable and persisted across page
   loads (it's a steady-state CSS bug, not a one-time animation glitch,
   so it reproduced identically every time the corner+closed state was
   active). Adding the missing 20px clears it fully. */
.growth-chat-panel.growth-chat-dock-corner:not(.open) {
  transform: translateX(calc(100% + 20px));
}

/* Top/corner handles only ever mean anything in corner mode (side mode
   has no independent height to drag) — hidden outside it. The left
   handle (.growth-chat-resize-handle) stays visible in BOTH modes; it's
   the same DOM element driving either the side panel's width or the
   corner box's width, mode-aware in growth-chat-widget.js. */
.growth-chat-panel:not(.growth-chat-dock-corner) .growth-chat-resize-handle-top,
.growth-chat-panel:not(.growth-chat-dock-corner) .growth-chat-resize-handle-corner {
  display: none;
}

/* Drag-to-resize handle (added this session, the old widget didn't have
   one) — sits on the panel's left edge, facing the main page content. */
.growth-chat-resize-handle {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 6px;
  cursor: ew-resize;
  z-index: 161;
}
.growth-chat-resize-handle:hover { background: var(--accent-soft); }

/* Top edge (height) and top-left corner (both) handles — added
   2026-08-07, corner-dock mode only. Both anchor against the box's fixed
   bottom-right corner (right:20px/bottom:20px never moves), so dragging
   either one grows the box up/left. The corner grip sits ON TOP of where
   the left and top strips would otherwise overlap (higher z-index) so
   that exact pixel always resolves to the "resize both" cursor/behavior
   rather than whichever strip happened to be drawn on top. */
.growth-chat-resize-handle-top {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 6px;
  cursor: ns-resize;
  z-index: 161;
}
.growth-chat-resize-handle-top:hover { background: var(--accent-soft); }
.growth-chat-resize-handle-corner {
  position: absolute;
  top: 0; left: 0;
  width: 14px;
  height: 14px;
  cursor: nwse-resize;
  z-index: 162;
}
.growth-chat-resize-handle-corner:hover { background: var(--accent-soft); border-radius: 12px 0 0 0; }

/* Only exists in the DOM for the duration of an active drag (see
   initGrowthChatResize() in growth-chat-widget.js) — sits above the
   panel's iframe so mousemove keeps landing on this parent document
   instead of getting swallowed by the iframe once the cursor crosses
   over it. Higher z-index than anything else that could plausibly be
   showing at the same time. */
.growth-chat-drag-mask {
  position: fixed;
  inset: 0;
  z-index: 500;
  cursor: ew-resize;
}

.growth-chat-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 0.75rem 0.6rem 1rem;
  border-bottom: 1px solid var(--surface-2);
  background: var(--white);
  flex-shrink: 0;
}

/* Tabs scroll horizontally instead of shoving the action buttons (popout /
   resize / dock / close) out of the panel — that squeeze is exactly what cut
   the X off at quarter width once the roster grew past four agents
   (2026-09-17 s1). The right edge fades to signal there's more to scroll;
   the scrollbar itself is hidden. Action buttons are flex-shrink:0 below. */
.growth-chat-tabs {
  display: flex; gap: 0.3rem;
  flex: 1 1 auto; min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 26px), transparent);
  mask-image: linear-gradient(to right, black calc(100% - 26px), transparent);
}
.growth-chat-tabs::-webkit-scrollbar { display: none; }
.growth-chat-tab {
  background: none; border: none; padding: 0.4rem 0.8rem; font-size: 0.82rem;
  font-weight: 500; color: var(--ink-muted); cursor: pointer; border-radius: 999px;
  font-family: var(--font-body); transition: color 0.15s, background 0.15s;
  flex-shrink: 0; white-space: nowrap;
}
.growth-chat-tab:hover { color: var(--ink); background: var(--surface); }
.growth-chat-tab.active { color: var(--accent-dark); background: var(--accent-soft); font-weight: 600; }

.growth-chat-panel-actions { display: flex; gap: 0.2rem; flex-shrink: 0; }
.growth-chat-action-btn {
  background: none; border: none; color: var(--ink-muted); padding: 0.3rem;
  border-radius: 6px; cursor: pointer; display: flex;
}
.growth-chat-action-btn:hover { background: var(--surface-2); color: var(--ink); }

/* Body holds either an iframe (a built agent — reuses that page's own
   code/UI entirely, zero duplication) or a plain placeholder (an agent
   that isn't built yet, e.g. Assistant today). */
.growth-chat-panel-body { flex: 1; overflow: hidden; }
.growth-chat-iframe { width: 100%; height: 100%; border: none; }
.growth-chat-placeholder {
  display: flex; align-items: center; justify-content: center; height: 100%;
  padding: 2rem; text-align: center; color: var(--ink-muted); font-size: 0.88rem;
  background: var(--surface);
}

/* !important below overrides the inline px width JS sets from the saved
   resize preference — responsive breakpoints must win over a stored
   "quarter screen on a wide monitor" width once the viewport is this narrow. */
@media (max-width: 900px) {
  .growth-chat-panel { width: 85vw !important; min-width: 0; }
}
@media (max-width: 480px) {
  .growth-chat-panel { width: 100vw !important; }
  .growth-chat-edge-tab { width: 30px; height: 56px; }
}

/* =============================================
   INVENTORY COUNT ASSISTANT
   ============================================= */

.inv-setup-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.75rem;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.inv-setup-section {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.25rem;
  background: var(--surface);
  border-radius: var(--radius);
  flex-wrap: wrap;
}

.inv-setup-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink);
}

.inv-file-status {
  font-size: 0.775rem;
  color: var(--ink-muted);
  font-weight: 400;
  margin-left: 0.25rem;
}

.inv-info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1.5px solid var(--ink-muted);
  color: var(--ink-muted);
  font-size: 0.7rem;
  font-weight: 700;
  font-style: italic;
  font-family: Georgia, serif;
  line-height: 1;
  cursor: help;
  user-select: none;
  flex-shrink: 0;
}

.inv-info-icon:hover,
.inv-info-icon:focus {
  border-color: var(--accent);
  color: var(--accent);
  outline: none;
}

.inv-upload-btn {
  padding: 0.5rem 1.125rem;
  background: var(--white);
  color: var(--ink-soft);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
}

.inv-upload-btn:hover { border-color: var(--accent); color: var(--accent); }

.inv-setup-actions {
  display: flex;
  gap: 0.875rem;
  align-items: center;
  flex-wrap: wrap;
}

.inv-previous-date {
  font-size: 0.75rem;
  color: var(--ink-muted);
  font-weight: 400;
  margin-left: 0.3rem;
}

.inv-warning {
  font-size: 0.825rem;
  color: var(--warn-text);
  background: var(--warn-soft);
  padding: 0.75rem 1rem;
  border-radius: var(--radius);
  border-left: 3px solid var(--warn);
}

/* Count screen */
.inv-session-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.5rem;
  gap: 1rem;
}

.inv-session-meta {
  font-size: 0.8rem;
  color: var(--ink-muted);
}

.inv-sku-wrap {
  background: var(--white);
  border-radius: var(--radius);
  padding: 1.25rem;
  box-shadow: var(--shadow);
  margin-bottom: 1.25rem;
}

.inv-sku-label {
  display: block;
  font-size: 0.775rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 0.5rem;
}

.inv-sku-row {
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

.inv-sku-input {
  flex: 1;
  padding: 0.75rem 1rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 1rem;
  font-family: var(--font-body);
  font-weight: 500;
  color: var(--ink);
  background: var(--surface);
  letter-spacing: 0.04em;
  transition: border-color 0.15s;
}

.inv-sku-input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--white);
}

/* Chat area */
.inv-chat-area {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.25rem;
  min-height: 320px;
  max-height: 500px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  margin-bottom: 1rem;
}

.inv-welcome {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  color: var(--ink-muted);
  font-size: 0.875rem;
  text-align: center;
  padding: 2rem;
}

.inv-message { display: flex; }

.inv-message--user { justify-content: flex-end; }
.inv-message--assistant { justify-content: flex-start; }

.inv-bubble {
  max-width: 90%;
  padding: 0.75rem 1rem;
  border-radius: 12px;
  font-size: 0.875rem;
  line-height: 1.6;
}

.inv-message--user .inv-bubble {
  background: var(--accent);
  color: var(--on-accent);
  border-bottom-right-radius: 4px;
  font-weight: 500;
  letter-spacing: 0.05em;
}

.inv-message--assistant .inv-bubble {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--surface-2);
  border-bottom-left-radius: 4px;
}

.inv-message--assistant .inv-bubble code {
  font-family: monospace;
  font-size: 0.82rem;
  background: var(--white);
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
  border: 1px solid var(--surface-2);
}

pre.inv-code {
  background: var(--chrome-dark-bg);
  color: var(--code-text);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  font-family: monospace;
  font-size: 0.82rem;
  line-height: 1.6;
  overflow-x: auto;
  margin: 0.5rem 0;
  white-space: pre-wrap;
}

.inv-count-input-wrap {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.25rem;
  border-left: 3px solid var(--accent);
}

/* Inventory step cards */
.inv-step-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  box-shadow: var(--shadow);
  margin-bottom: 1rem;
  transition: opacity 0.2s;
}

.inv-step-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.inv-step-num {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 0.8rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.inv-step-title {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
}

/* Inventory result card */
.inv-result-card { display: flex; flex-direction: column; gap: 0.75rem; }

.inv-result-sku {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--ink);
  font-family: monospace;
  letter-spacing: 0.05em;
}

.inv-result-title {
  font-size: 0.875rem;
  color: var(--ink-soft);
  margin-top: -0.5rem;
}

.inv-qty-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
}

.inv-qty-item {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 0.6rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.inv-qty-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.inv-qty-val {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--ink);
}

.inv-detail-row {
  display: flex;
  gap: 0.75rem;
  font-size: 0.85rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--surface);
}

.inv-detail-label {
  color: var(--ink-muted);
  min-width: 120px;
  flex-shrink: 0;
}

.inv-detail-val { color: var(--ink); }

.inv-orders-summary {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 0.75rem;
}

.inv-committed-toggle {
  background: none;
  border: none;
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  margin-top: 0.2rem;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 0.15rem;
}

.inv-committed-toggle:hover { text-decoration: underline; }

.inv-committed-orders {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 0.75rem;
  margin-top: -0.5rem;
}

.inv-line-items-list {
  padding: 1rem 1.5rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  max-height: 320px;
  overflow-y: auto;
}

.inv-line-item-row {
  padding: 0.5rem 0.6rem;
  background: var(--surface);
  border-radius: var(--radius);
}

.inv-line-item-title {
  font-size: 0.85rem;
  color: var(--ink);
  font-weight: 500;
}

.inv-line-item-meta {
  font-size: 0.75rem;
  color: var(--ink-muted);
  font-family: monospace;
  margin-top: 0.15rem;
}

.inv-order-line {
  font-size: 0.8rem;
  color: var(--ink-soft);
  padding: 0.2rem 0;
  font-family: monospace;
}

.inv-expected {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
  padding: 0.75rem;
  background: var(--accent-soft);
  border-radius: var(--radius);
  border-left: 3px solid var(--accent);
}

.inv-expected-calc {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--ink-muted);
  margin-left: 0.5rem;
}

/* Basic/Advanced display toggle (added 2026-07-20) — CSS-only visibility
   switch, same body-class pattern as .helper-tips-off. Nothing about the
   underlying data or calculations changes between modes, only what renders. */
body.basic-display .inv-advanced-only {
  display: none;
}

.inv-count-summary {
  font-size: 0.85rem;
  color: var(--ink-soft);
  padding: 0.6rem 0.75rem;
  background: var(--bg-soft);
  border-radius: var(--radius);
  line-height: 1.4;
}

.inv-count-result {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--surface-2);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.inv-physical-count { font-size: 0.9rem; color: var(--ink); }

.inv-discrepancy { font-size: 0.875rem; padding: 0.6rem 0.875rem; border-radius: var(--radius); }
.inv-discrepancy.match { background: var(--success-soft); color: var(--success-text); }
.inv-discrepancy.over  { background: var(--warn-soft); color: var(--warn-text); }
.inv-discrepancy.under { background: var(--danger-soft); color: var(--danger-text); }

.inv-helper-tip {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid rgba(0,0,0,0.08);
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1.4;
}

.inv-correction-actions { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: 0.25rem; }

.inv-loading {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--ink-soft);
  font-size: 0.875rem;
  padding: 1rem 0;
}

.inv-error-msg {
  color: var(--danger);
  font-size: 0.875rem;
  padding: 0.75rem;
  background: var(--danger-soft);
  border-radius: var(--radius);
}

/* Inventory links */
.inv-link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
}
.inv-link:hover { text-decoration: underline; }
a.inv-result-sku { display: inline-block; }

/* =============================================
   PORTAL SEARCH
   ============================================= */

.portal-search-wrap {
  position: relative;
  margin-bottom: 1.5rem;
  max-width: 480px;
}

.portal-search-inner {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  background: var(--white);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 0.6rem 0.875rem;
  box-shadow: var(--shadow);
  transition: border-color 0.15s;
}

.portal-search-wrap:focus-within .portal-search-inner {
  border-color: var(--accent);
}

.portal-search-icon { color: var(--ink-muted); flex-shrink: 0; }

.portal-search-input {
  flex: 1;
  border: none;
  outline: none;
  font-size: 0.9rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: transparent;
}

.portal-search-input::placeholder { color: var(--ink-muted); }

.portal-search-kbd {
  font-size: 0.7rem;
  color: var(--ink-muted);
  background: var(--surface);
  border: 1px solid var(--surface-2);
  border-radius: 4px;
  padding: 0.1rem 0.35rem;
  display: none;
  font-family: monospace;
}

.portal-search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--white);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  z-index: 100;
  max-height: 360px;
  overflow-y: auto;
}

.search-result-item {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.75rem 1rem;
  cursor: pointer;
  transition: background 0.1s;
  border-bottom: 1px solid var(--surface);
}

.search-result-item:last-child { border-bottom: none; }
.search-result-item:hover, .search-result-item.active { background: var(--surface); }
.search-result-soon { opacity: 0.55; cursor: default; }

.search-result-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.search-result-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-result-desc {
  font-size: 0.775rem;
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-result-category {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.search-highlight {
  background: var(--accent-soft);
  color: var(--accent-dark);
  border-radius: 2px;
  padding: 0 1px;
  font-style: normal;
}

.search-no-results {
  padding: 1rem;
  font-size: 0.85rem;
  color: var(--ink-muted);
  text-align: center;
}

/* Inventory pre-session checklist */
.inv-check-row {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
  padding: 0.875rem 1rem;
  background: var(--surface);
  border-radius: var(--radius);
  cursor: pointer;
  border: 1.5px solid transparent;
  transition: border-color 0.15s, background 0.15s;
}

.inv-check-row:has(input:checked) {
  background: var(--success-soft);
  border-color: var(--success);
}

.inv-check-row input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--success);
  flex-shrink: 0;
  margin-top: 2px;
  cursor: pointer;
}

.inv-check-content {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.inv-check-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
}

.inv-check-desc {
  font-size: 0.775rem;
  color: var(--ink-muted);
}

/* Excluded orders section */
.inv-excluded-wrap {
  background: var(--warn-soft);
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  padding: 0.75rem;
  margin-top: 0.25rem;
}

.inv-excluded-label {
  font-size: 0.775rem;
  font-weight: 600;
  color: var(--warn-text);
  margin-bottom: 0.4rem;
}

/* SKU suggestions */
.inv-suggestions {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.inv-suggestions-header {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: 0.25rem;
}

.inv-suggestion-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.75rem 1rem;
  background: var(--surface);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.inv-suggestion-item:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.inv-suggestion-sku {
  font-size: 0.95rem;
  font-weight: 700;
  font-family: monospace;
  color: var(--ink);
  letter-spacing: 0.04em;
}

.inv-suggestion-title {
  font-size: 0.8rem;
  color: var(--ink-muted);
}

.inv-suggestions-footer {
  font-size: 0.775rem;
  color: var(--ink-muted);
  margin-top: 0.25rem;
}

/* =============================================
   BARCODE FIX LIST PAGE
   ============================================= */

.barcode-stats {
  display: flex;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.barcode-stat {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.875rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 90px;
}

.barcode-stat-val {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
}

.barcode-stat-label {
  font-size: 0.75rem;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}

.barcode-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  padding: 4rem 2rem;
  color: var(--ink-muted);
  text-align: center;
  font-size: 0.875rem;
  line-height: 1.6;
}

.barcode-issue-card {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1rem 1.25rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.625rem;
  transition: opacity 0.2s;
}

.barcode-issue-fixed {
  opacity: 0.5;
}

.barcode-issue-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}

.barcode-issue-sku {
  font-size: 0.95rem;
  font-weight: 700;
  font-family: monospace;
  color: var(--accent);
  letter-spacing: 0.04em;
}

.barcode-issue-name {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink);
}

.barcode-issue-meta {
  display: flex;
  gap: 1rem;
  font-size: 0.775rem;
  color: var(--ink-muted);
  margin-top: 0.15rem;
  flex-wrap: wrap;
}

.barcode-issue-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

.barcode-fixed-badge {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--success-text);
  background: var(--success-soft);
  border-radius: 20px;
  padding: 0.25rem 0.75rem;
}

/* Not-found inline prompt */
.inv-not-found {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.inv-not-found-msg {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--danger-text);
  background: var(--danger-soft);
  border: 1px solid var(--danger-border-soft);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
}

.inv-prefix-matches {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.inv-prefix-match-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  width: 100%;
  text-align: left;
  background: var(--surface);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 0.6rem 0.875rem;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.inv-prefix-match-btn:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.inv-prefix-match-sku {
  font-family: monospace;
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--ink);
}

.inv-prefix-match-title {
  font-size: 0.8rem;
  color: var(--ink-muted);
}

.inv-barcode-prompt {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.825rem;
  color: var(--ink-soft);
  padding: 0.5rem 0;
}

.inv-barcode-prompt-btn {
  font-size: 0.825rem;
  font-weight: 500;
  color: var(--accent);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.inv-barcode-prompt-btn:hover { color: var(--accent-dark); }

.inv-barcode-form {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1rem;
  border: 1.5px solid var(--surface-2);
}

.inv-barcode-form-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.75rem;
}

.inv-barcode-form-row { display: flex; flex-direction: column; gap: 0.35rem; }

/* Bin location editable */
.inv-bin-wrap {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.inv-bin-edit-btn {
  background: none;
  border: none;
  color: var(--ink-muted);
  cursor: pointer;
  padding: 0.15rem;
  border-radius: 4px;
  display: flex;
  align-items: center;
  transition: color 0.15s;
}

.inv-bin-edit-btn:hover { color: var(--accent); }

.inv-note-icon-btn {
  background: none;
  border: none;
  color: var(--ink-muted);
  cursor: pointer;
  padding: 0.1rem 0.2rem;
  margin-left: 0.15rem;
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  transition: color 0.15s;
}

.inv-note-icon-btn:hover { color: var(--accent); }

.modal-note-body {
  padding: 1.25rem 1.5rem;
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--ink);
  white-space: pre-wrap;
  word-break: break-word;
}

.modal-note-tags-section {
  padding: 0 1.5rem 1.25rem;
  border-top: 1px solid var(--surface-2);
}

.modal-note-tags-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-top: 1rem;
  margin-bottom: 0.6rem;
}

.modal-note-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.inv-tag-badge {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.2rem 0.6rem;
  border-radius: 10px;
  background: var(--info-badge-bg);
  color: var(--info-badge-text);
}

.modal-note-tags-empty {
  font-size: 0.8rem;
  color: var(--ink-muted);
}

.modal-note-form { padding: 1.25rem 1.5rem; }

.inv-note-textarea {
  width: 100%;
  padding: 0.6rem 0.875rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.85rem;
  font-family: var(--font-body);
  color: var(--ink);
  resize: vertical;
  min-height: 90px;
  background: var(--surface);
  transition: border-color 0.15s;
  margin-top: 0.5rem;
}

.inv-note-textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--white);
}

/* Description rich-text box (added 2026-08-10) — a contenteditable div
   styled to look like every other .inv-note-textarea. Default height
   is intentionally modest (matches the old 4-row <textarea> it
   replaced); #taskDescExpandBtn toggles .task-desc-editable--expanded
   for a much taller view. Neither state is ever persisted — every time
   the task modal opens, it starts back at the default collapsed size,
   per Dylan's explicit ask (no "remembers how tall I dragged it last
   time" behavior). */
.task-desc-editable {
  max-height: 160px;
  overflow-y: auto;
  cursor: text;
  line-height: 1.45;
}
.task-desc-editable--expanded {
  max-height: 420px;
}
.task-desc-editable:empty:before {
  content: attr(data-placeholder);
  color: var(--ink-muted);
}
/* Pasted rich content needs its own sizing — browsers paste real <h1>
   tags at their native (huge) size otherwise, which would blow out this
   small box. Scaled down to something sane for a task description,
   not a full document. */
.task-desc-editable h1 { font-size: 1.15rem; font-weight: 700; margin: 0.5rem 0 0.25rem; }
.task-desc-editable h2 { font-size: 1.05rem; font-weight: 700; margin: 0.5rem 0 0.25rem; }
.task-desc-editable h3 { font-size: 0.95rem; font-weight: 600; margin: 0.4rem 0 0.2rem; }
.task-desc-editable p { margin: 0 0 0.5rem; }
.task-desc-editable ul, .task-desc-editable ol { margin: 0 0 0.5rem; padding-left: 1.25rem; }
.task-desc-editable a { color: var(--accent); text-decoration: underline; }

.modal-note-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: 0.875rem;
}

/* Sticky action row for taller modals (added 2026-07-22 for the Review &
   Send modal, which grew a preview pane) — scoped to its own modifier
   classes rather than changing the base .modal-card/.modal-note-form/
   .modal-note-actions rules, so Bad Debt and Add Customer's shorter
   modals are completely unaffected. */
.modal-card--scrollable {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-note-form--scroll {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
/* Added 2026-08-07 — for modals that skip the .modal-note-form wrapper
   entirely (its 1.25rem 1.5rem padding is what normally keeps
   .modal-note-actions off the card's edges). The agent profile quick-view
   modal (advisor.html/assistant.html/marketing-office.html) is the first
   case: its body content has its own one-off inline padding that doesn't
   extend to the actions row below it, leaving Close/"Edit full profile"
   flush against the bottom (and side) edges of the card — flagged
   directly by Dylan. Scoped modifier rather than changing the base rule,
   same reasoning as --sticky above. */
.modal-note-actions--padded {
  padding: 0 1.25rem 1.25rem;
}

.modal-note-actions--sticky {
  flex-shrink: 0;
  border-top: 1px solid var(--surface-2);
  padding: 1rem 1.5rem;
  margin-top: 0;
}

.inv-bin-edit-form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.625rem 0;
  flex-wrap: wrap;
}

/* =============================================
   ADMIN ACCESS SETTINGS PAGE
   ============================================= */

.admin-users-list {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
}

.admin-user-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 1.25rem 1.5rem;
  box-shadow: var(--shadow);
}

.admin-user-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
  gap: 1rem;
  flex-wrap: wrap;
}

.admin-user-email {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink);
}

/* Profile photos (added 2026-08-10) — same 32px circular treatment as
   the topbar avatar elsewhere; a plain initial-letter circle stands in
   when no photo's on file (avatar_url comes from the Worker's
   /users/roster-info, same source Tasks' assignee avatars use). */
.admin-user-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.admin-user-avatar--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  color: var(--ink-muted);
  font-size: 0.8rem;
  font-weight: 600;
}

.admin-user-meta {
  font-size: 0.775rem;
  color: var(--ink-muted);
  margin-top: 0.15rem;
}

.admin-user-role-wrap {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}

.admin-role-badge {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.2rem 0.625rem;
  border-radius: 20px;
}

.admin-role-admin {
  background: var(--accent-soft);
  color: var(--accent-dark);
}

.admin-role-user {
  background: var(--surface-2);
  color: var(--ink-muted);
}

.admin-pages-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.875rem;
}

.admin-page-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.875rem;
  border-radius: 20px;
  border: 1.5px solid var(--surface-2);
  background: var(--surface);
  font-size: 0.8rem;
  color: var(--ink-muted);
  cursor: pointer;
  transition: all 0.15s;
  user-select: none;
}

.admin-page-toggle.active {
  background: var(--success-soft);
  border-color: var(--success);
  color: var(--success-text);
  font-weight: 500;
}

.admin-page-toggle input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: var(--success);
  cursor: pointer;
}

.admin-bulk-row {
  display: flex;
  gap: 0.5rem;
}

.admin-empty-section {
  color: var(--ink-muted);
  font-size: 0.85rem;
  padding: 1rem;
  background: var(--surface);
  border-radius: var(--radius);
  text-align: center;
}

/* Admin page permission chips (read-only view) */
.admin-pages-view {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.5rem;
}

.admin-page-chip {
  font-size: 0.775rem;
  font-weight: 500;
  padding: 0.25rem 0.7rem;
  border-radius: 20px;
  border: 1.5px solid transparent;
}

.admin-page-chip.granted {
  background: var(--success-soft);
  border-color: var(--success);
  color: var(--success-text);
}

.admin-page-chip.denied {
  background: var(--surface);
  border-color: var(--surface-2);
  color: var(--ink-muted);
}

/* =============================================
   INVENTORY REPORT PAGE
   ============================================= */

.inv-report-filters {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}

.inv-report-filters select,
.inv-report-filters input[type="text"],
.inv-report-filters input[type="date"] {
  font-size: 0.85rem;
  font-family: var(--font-body);
  padding: 0.45rem 0.75rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  outline: none;
  transition: border-color 0.15s;
}

.inv-report-filters select:focus,
.inv-report-filters input:focus { border-color: var(--accent); }

.inv-report-stats {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}

.inv-report-stat {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.75rem 1.125rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 80px;
  cursor: pointer;
  border: 1.5px solid transparent;
  transition: border-color 0.15s, transform 0.1s;
  user-select: none;
}

.inv-report-stat:hover { border-color: var(--surface-2); }
.inv-report-stat:active { transform: scale(0.97); }

.inv-report-stat.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* Added 2026-07-21 — the COGS $ impact tile isn't clickable (a dollar
   total isn't a single event_type to filter by like the others), so it
   opts out of the pointer/hover/active affordances the clickable tiles
   use, and gets a small accent border to read as the "headline" metric. */
.inv-report-stat-cogs {
  cursor: default;
  border-left: 3px solid var(--accent);
}
.inv-report-stat-cogs:hover { border-color: transparent; border-left-color: var(--accent); }
.inv-report-stat-cogs:active { transform: none; }

.inv-report-stat-val {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
}

.inv-report-stat-label {
  font-size: 0.72rem;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}

/* Added 2026-07-21 — per-row percent-change indicator next to New value. */
.inv-report-pct-badge {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--ink-muted);
  background: var(--surface);
  padding: 0.08rem 0.4rem;
  border-radius: 999px;
  white-space: nowrap;
}
.inv-report-pct-new {
  color: var(--success-text);
  background: var(--success-soft);
}

.inv-report-table-wrap {
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow-x: auto;
}

.inv-report-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.inv-report-table thead th {
  background: var(--surface);
  padding: 0.75rem 1rem;
  text-align: left;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  border-bottom: 1px solid var(--surface-2);
  white-space: nowrap;
}

.inv-report-table tbody tr {
  border-bottom: 1px solid var(--surface);
  transition: background 0.1s;
}

.inv-report-table tbody tr:last-child { border-bottom: none; }
.inv-report-table tbody tr:hover { background: var(--surface); }

.inv-report-table tbody td {
  padding: 0.75rem 1rem;
  vertical-align: middle;
}

.inv-report-event-badge {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.2rem 0.6rem;
  border-radius: 20px;
  white-space: nowrap;
}

.inv-report-table tbody tr { cursor: pointer; }

.inv-report-table tbody tr.inv-report-row-resolved {
  background: var(--success-bg-faint);
}
.inv-report-table tbody tr.inv-report-row-resolved:hover { background: var(--success-soft); }

.inv-report-table tbody tr.inv-report-row-cleared {
  background: var(--surface);
  opacity: 0.6;
}
.inv-report-table tbody tr.inv-report-row-cleared:hover { opacity: 0.85; }

.inv-report-row-checkbox { cursor: pointer; }

/* Inventory Monitor's table header sticky positioning — see the later
   #monitorTable thead th rule (search "anchors the .ar-col-resize-handle")
   for the actual position:sticky declaration. It used to live here as a
   separate rule, but a SECOND #monitorTable thead th rule further down
   the file (added for the column-resize drag handles, same exact
   selector) was setting position:relative — identical specificity means
   the later rule in the file wins the cascade, so that one was silently
   overwriting this one's position:sticky every time, and the header
   never actually stuck. Merged into one rule instead of two competing
   ones. position:sticky still works as the resize handle's anchor
   exactly like position:relative did — a stickily-positioned element is
   just as much a "positioned element" in the CSS sense, so it still
   establishes a containing block for the handle's position:absolute. */
#monitorTableWrap {
  /* .inv-report-table-wrap's own overflow-x:auto (needed for horizontal
     scroll on wide/resized columns) forces its computed overflow-y to
     auto too, per the CSS Overflow spec — no way to opt out — which
     makes the wrap itself, not the page, the nearest scrolling ancestor
     for any position:sticky descendant. This override removes
     overflow-x from THIS specific wrap (ID beats the shared class), so
     it's no longer a scroll container in either axis — position:sticky
     below then correctly resolves against the real page/viewport.
     Tradeoff, accepted deliberately over building a second JS-synced
     header row: if columns are dragged wide enough to exceed the
     viewport, the WHOLE PAGE scrolls sideways to show them (topbar
     included, since its own position:sticky only overrides `top`, not
     `left`) rather than just the table area. */
  overflow-x: visible;
}

.inv-report-solved-badge {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.15rem 0.5rem;
  border-radius: 20px;
  background: var(--success-soft);
  color: var(--success-text);
  white-space: nowrap;
}

.inv-report-cleared-badge {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.15rem 0.5rem;
  border-radius: 20px;
  background: var(--surface-2);
  color: var(--ink-muted);
  white-space: nowrap;
}

.inv-report-inline-link {
  background: none;
  border: none;
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}

.inv-report-bulk-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 0.6rem 0.875rem;
  margin-bottom: 0.875rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
}

.inv-report-legacy-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: var(--warn-soft);
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin-bottom: 0.875rem;
  font-size: 0.85rem;
  color: var(--ink);
}

/* =============================================
   MARKETING FUNNEL
   ============================================= */

.funnel-stage {
  margin-bottom: 1.25rem;
}

.funnel-stage-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 0.4rem;
}

.funnel-stage-name {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
}

.funnel-channel-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.35rem;
}

.funnel-channel-label {
  width: 70px;
  flex-shrink: 0;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-muted);
}

.funnel-track {
  flex: 1;
  height: 22px;
  background: var(--surface-2);
  border-radius: 6px;
  overflow: hidden;
}

.funnel-fill {
  height: 100%;
  border-radius: 6px;
  transition: width 0.3s ease;
  min-width: 2px;
}

.funnel-fill.organic { background: var(--success); }
.funnel-fill.paid     { background: var(--accent); }
.funnel-fill.other    { background: var(--low); }
.funnel-fill.all      { background: var(--ink-soft); }

.funnel-channel-value {
  width: 64px;
  flex-shrink: 0;
  text-align: right;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink);
}

/* Per-channel step-over-step % (Split view only), added 2026-07-31 —
   sits inline at the end of each channel row, separate from the existing
   .funnel-dropoff line which only ever showed the blended/combined %. */
.funnel-channel-pct {
  width: 52px;
  flex-shrink: 0;
  text-align: right;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--ink-muted);
}

/* Stage cards + arrows row (added 2026-07-31) — deliberately its own
   horizontally-scrolling flex row instead of the auto-fill .kpi-grid the
   revenue cards below still use. Auto-fill wrapping is fine for cards
   with no inherent order, but arrows between wrapped rows would land in
   nonsensical places, so this row never wraps — it scrolls instead. */
.funnel-stage-row {
  display: flex;
  align-items: stretch;
  flex-wrap: wrap; /* changed 2026-07-31 from horizontal-scroll-only to wrapping, per Dylan — the Steps filter can now add several more cards, so this needed to grow vertically instead of endlessly scrolling sideways */
  gap: 0.6rem;
}
.funnel-stage-row .funnel-stage-card {
  flex: 1 1 155px;
  min-width: 155px;
}
.funnel-stage-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 20px;
  color: var(--ink-muted);
}

/* Graph view (funnel-shape or bar) — same container for both, added
   2026-07-31. A plain SVG scaled to its container via viewBox, matching
   the hand-rolled-SVG convention already used elsewhere in the portal
   (see js/integrations-map.js) rather than pulling in a charting library
   for something this contained. */
.funnel-graph-svg {
  width: 100%;
  height: auto;
  max-height: 320px;
  display: block;
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* Trend chart empty state (added 2026-07-31) */
.funnel-trend-empty {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--ink-muted);
  font-size: 0.85rem;
}

/* Reorderable Funnel page sections (added 2026-07-31) — up/down arrows,
   not drag-and-drop, same mechanism already used for home page card
   reordering. Order is saved per-user (user_funnel_layout). */
.funnel-section {
  margin-bottom: 2rem;
}
.funnel-section-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}
.funnel-section-title {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.funnel-source-legend {
  display: flex;
  gap: 0.85rem;
  font-size: 0.72rem;
  color: var(--ink-muted);
  margin-right: auto;
  margin-left: 1rem;
}
.funnel-source-legend span { display: inline-flex; align-items: center; gap: 0.3rem; }
.funnel-source-legend i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.funnel-section-toolbar-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.funnel-reorder-arrows {
  display: flex;
  gap: 0.25rem;
}
.funnel-reorder-arrows button {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  border: 1.5px solid var(--surface-2);
  background: var(--white);
  color: var(--ink-soft);
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.funnel-reorder-arrows button:hover { background: var(--surface); border-color: var(--ink-soft); }
.funnel-reorder-arrows button:disabled { opacity: 0.35; cursor: default; }
.funnel-reorder-arrows button:disabled:hover { background: var(--white); border-color: var(--surface-2); }

/* Trend chart hover tooltip (added 2026-07-31) */
.funnel-trend-chart-inner {
  position: relative;
}
.funnel-trend-tooltip {
  position: absolute;
  z-index: 5;
  pointer-events: none; /* never intercepts the mousemove tracking it on the SVG below it */
  background: var(--white);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.6rem 0.75rem;
  min-width: 150px;
  font-size: 0.78rem;
}
.funnel-trend-tooltip-date {
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 0.35rem;
}
.funnel-trend-tooltip-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  color: var(--ink-soft);
  line-height: 1.5;
}
.funnel-trend-tooltip-row span:last-child {
  font-weight: 600;
  color: var(--ink);
}
.funnel-trend-tooltip-divider {
  border-top: 1px solid var(--surface-2);
  margin: 0.35rem 0;
}
.funnel-trend-tooltip-label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-muted);
  margin-bottom: 0.15rem;
}

.funnel-dropoff {
  font-size: 0.7rem;
  color: var(--ink-muted);
  margin: 0.1rem 0 0.75rem 82px;
}

.funnel-caveat-box {
  background: var(--warn-soft);
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin-top: 1.5rem;
  line-height: 1.5;
}

.funnel-caveat-box strong { color: var(--ink); }

.funnel-legend {
  display: flex;
  gap: 1.25rem;
  margin-bottom: 1.25rem;
  font-size: 0.75rem;
  color: var(--ink-muted);
}

.funnel-legend-item {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.funnel-legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: inline-block;
}

.funnel-legend-dot.organic { background: var(--success); }
.funnel-legend-dot.paid     { background: var(--accent); }
.funnel-legend-dot.other    { background: var(--low); }

/* =============================================
   KPI INFO TOOLTIP (used on the Marketing Funnel page)
   ============================================= */

.kpi-info {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--ink-muted);
  font-size: 0.62rem;
  font-weight: 700;
  cursor: help;
}

.kpi-info:hover, .kpi-info:focus {
  background: var(--accent);
  color: var(--on-accent);
}

/* Redesigned 2026-07-31 — was position:absolute inside each card
   (.kpi-tooltip), shown via pure CSS :hover. Replaced with ONE shared
   position:fixed tooltip (see initFunnelKpiTooltips() in funnel.js),
   positioned and clamped to the viewport in JS. Fixed positioning is
   immune to any ancestor's overflow setting, which is what was causing
   both the clipping and the rightmost-card jitter before. */
.kpi-tooltip-fixed {
  display: none;
  position: fixed;
  width: 230px;
  background: var(--chrome-dark-bg);
  color: var(--chrome-dark-text);
  font-size: 0.72rem;
  font-weight: 400;
  line-height: 1.45;
  text-transform: none;
  letter-spacing: normal;
  padding: 0.65rem 0.75rem;
  border-radius: 8px;
  box-shadow: var(--shadow-lg);
  z-index: 500;
  text-align: left;
  pointer-events: none;
}

/* =============================================
   DELAY ORDERS PAGE
   ============================================= */

.delay-empty-state {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--ink-muted);
  font-size: 0.875rem;
}

.delay-muted { color: var(--ink-muted); }

.delay-badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.2rem 0.6rem;
  border-radius: 10px;
  margin-right: 0.3rem;
}

.delay-badge-bin { background: var(--info-badge-bg); color: var(--info-badge-text); }
.delay-badge-paper { background: var(--warn-soft); color: var(--warn-text-alt); }
.delay-badge-ready { background: var(--success-soft); color: var(--success-text); }

.delay-tags-input {
  min-height: unset;
  resize: none;
}

.delay-count-label {
  font-size: 0.8rem;
  color: var(--ink-muted);
  font-weight: 600;
  margin-bottom: 0.6rem;
}

.delay-notes-cell,
.delay-tags-cell {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 0.8rem;
  color: var(--ink-soft);
  cursor: pointer;
  border-radius: 6px;
  padding: 0.25rem 0.35rem;
  margin: -0.25rem -0.35rem;
  transition: background 0.15s;
}

.delay-notes-cell:hover,
.delay-tags-cell:hover {
  background: var(--surface);
}

/* Highlights the exact SKU text within a note that the Linkable SKU column
   matched against (added 2026-07-14) — lets staff see at a glance what the
   portal is referencing instead of re-reading the whole note. Uses <mark>
   for the semantic "this text is relevant" meaning, styled with the theme's
   existing warn/amber tokens rather than a new one-off color. */
.delay-note-sku-highlight {
  background: var(--warn-soft);
  color: var(--ink);
  font-weight: 700;
  padding: 0.03rem 0.2rem;
  border-radius: 4px;
}

.delay-tags-cell {
  white-space: normal;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  align-items: flex-start;
}

.dash-table td:has(.delay-notes-cell),
.dash-table td:has(.delay-tags-cell) {
  white-space: normal;
}

/* Delay/Pickup tables: separate border model (not the shared .dash-table
   default) so individual rows can have a fully rounded border — collapsed
   borders clip radius at cell boundaries. Every cell gets a transparent
   1.5px border on all sides so highlighting a row later is just a color
   swap, not a layout change. */
/* Delay/Pickup/CCM tables: separate border model (not the shared
   .dash-table default) so individual rows can have a fully rounded border —
   collapsed borders clip radius at cell boundaries. Every cell gets a
   transparent 1.5px border on all sides so highlighting a row later is
   just a color swap, not a layout change. */
#delayTable, #pickupTable, #ccmTable {
  border-collapse: separate;
  border-spacing: 0 3px;
}

#delayTable td, #pickupTable td, #ccmTable td {
  vertical-align: top;
  border-style: solid;
  border-width: 1.5px;
  border-color: transparent transparent var(--surface-2) transparent;
}

#delayTable td:first-child, #pickupTable td:first-child, #ccmTable td:first-child {
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
}
#delayTable td:last-child, #pickupTable td:last-child, #ccmTable td:last-child {
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
}

/* Consumer Choice Medical orders (2026-07-13) — distinct blue marker
   wherever they show up, across all three tabs. Declared before the ready
   highlight below so a row that's somehow both CCM and ready shows the
   green ready state (more actionable/time-sensitive) rather than blue. */
.delay-order-number--ccm { color: var(--ccm-accent); }
.dash-table tr.delay-row--ccm td { border-color: var(--ccm-accent); }
.dash-table tr.delay-row--ccm:hover td { border-color: var(--ccm-accent); }

/* Ready for Pickup tab — order created more than 2 days ago (added
   2026-07-20, Dylan's request). Uses --warn-soft, the portal's shared
   warning-yellow token, since this is a "needs attention" signal rather
   than a distinct one-off color like the CCM/ready highlights above. */
.dash-table tr.delay-row--stale-pickup td {
  background: var(--warn-soft);
  border-color: var(--warn-border-alt);
}
.dash-table tr.delay-row--stale-pickup:hover td { background: var(--warn-soft); }

/* Whole-row highlight when at least one outstanding SKU has arrived —
   same intent as the old sheet's cyan "INVENTORY RECEIVED" highlight.
   Uses its own (more saturated) colors rather than --success-soft/--success —
   those tokens are shared with Campaign Dashboard score pills and Inventory
   Assistant's discrepancy badges, and bumping them there wasn't asked for. */
.dash-table tr.delay-row--ready td {
  background: var(--success-bg-strong);
  border-color: var(--success-strong);
}
.dash-table tr.delay-row--ready:hover td { background: var(--success-bg-strong); }

/* "Mentions READY" row highlight (added 2026-07-14) — plain case-insensitive
   text match on "ready" anywhere in the note or tags (see
   readyMentionRowClass in delay-orders.js), NOT the same signal as
   delay-row--ready above (that one means stock has actually arrived for a
   linked SKU). Deliberately more saturated than delay-row--ready and
   declared after it, so it wins visually if a row is ever both — per
   Dylan, this text-match signal is the more important one to notice.
   Delay tab only. */
.dash-table tr.delay-row--ready-mention td {
  background: var(--success-bg-stronger);
  border-color: var(--success-text);
}
.dash-table tr.delay-row--ready-mention:hover td { background: var(--success-bg-stronger); }

/* Duplicate scrollbar above the table, synced to the real one below, so
   horizontal scrolling doesn't require scrolling all the way down first. */
.dash-table-scroll-top {
  overflow-x: auto;
  overflow-y: hidden;
  height: 16px;
  margin-bottom: 4px;
}
.dash-table-scroll-top > div {
  height: 1px;
}

.delay-customer-name {
  cursor: default;
}

.dash-search-input {
  padding: 0.5rem 0.875rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.85rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--white);
  min-width: 260px;
  transition: border-color 0.15s;
}

.dash-search-input:focus {
  outline: none;
  border-color: var(--accent);
}

.delay-order-number {
  font-size: 1.1rem;
  font-weight: 700;
}

.delay-count-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.6rem;
  flex-wrap: wrap;
}
.delay-count-row .delay-count-label { margin-bottom: 0; }

.delay-linkable-note {
  font-size: 0.8rem;
  color: var(--success);
  font-weight: 600;
}

/* Delay Orders sync line (2026-09-25): slim freshness readout under the heading. */
.delay-fresh-strip {
  font-size: 0.72rem;
  color: var(--ink-muted);
  margin-top: 0.3rem;
}
.delay-sync-status {
  font-size: 0.72rem;
  color: var(--ink-muted);
  margin-top: 0.15rem;
}
.delay-sync-status--warn { color: var(--warn-text-alt); }

.delay-nav {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-muted);
}

.delay-nav-btn {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  border: 1.5px solid var(--surface-2);
  background: var(--white);
  color: var(--ink);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.delay-nav-btn:hover { background: var(--surface); border-color: var(--ink-soft); }

.dash-table tr.delay-row--flash td {
  box-shadow: inset 0 0 0 2px var(--accent);
  transition: box-shadow 0.2s;
}

/* Sticky toolbar (search, refresh, counts, ready-nav) — stays visible while
   scrolling down a long table. Offset matches the topbar's own sticky
   height (58px) so they stack cleanly instead of overlapping. */
.delay-sticky-toolbar {
  position: sticky;
  top: 58px;
  z-index: 50;
  background: var(--surface);
  padding: 0.75rem 1.5rem;
  border-bottom: 1px solid var(--surface-2);
  margin-bottom: 0.75rem;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
}

.delay-sticky-toolbar .dash-controls {
  justify-content: flex-end;
}

.delay-sticky-toolbar .delay-count-row {
  margin-bottom: 0;
}

.delay-sticky-toolbar .delay-count-label {
  margin-bottom: 0;
}

#delayTable th, #pickupTable th, #ccmTable th,
#delayTable td, #pickupTable td, #ccmTable td {
  padding-left: 0.6rem;
  padding-right: 0.6rem;
}

/* Fixed column widths for the Delay/Pickup/CCM tables specifically (not
   the shared .dash-table default). Narrow, short-content columns (Order,
   ETD, Status, etc.) get a fixed pixel width so they don't stretch and
   leave a big gap on a wide/uncapped page — only the genuinely flexible
   text columns (Notes, Tags, Linkable SKU) use percentages and soak up
   whatever width is left over. */
/* A little side padding so the first/last column don't sit flush against
   the card edge — scoped to these three tables only. */
#delayTableWrap, #pickupTableWrap, #ccmTableWrap {
  padding: 0 0.75rem;
}

/* Delay + READY tabs (same columns). Reworked 2026-09-29 for a portrait
   (~1080px) screen: the six short columns are fixed and slim (Customer
   wraps instead of taking 190px), and Notes / Tags / Linkable SKU share
   everything left over. Their percentages add up past 100% on purpose —
   with table-layout: fixed, Chrome then splits the leftover width in the
   ratio 3 : 2 : 3, at any screen width. */
#delayTable, #readyTable { table-layout: fixed; }
#delayTable th:nth-child(1), #delayTable td:nth-child(1),
#readyTable th:nth-child(1), #readyTable td:nth-child(1) { width: 92px; }
#delayTable th:nth-child(2), #delayTable td:nth-child(2),
#readyTable th:nth-child(2), #readyTable td:nth-child(2) { width: 104px; }
#delayTable th:nth-child(3), #delayTable td:nth-child(3),
#readyTable th:nth-child(3), #readyTable td:nth-child(3) { width: 104px; white-space: normal; overflow-wrap: anywhere; }
#delayTable th:nth-child(4), #delayTable td:nth-child(4),
#readyTable th:nth-child(4), #readyTable td:nth-child(4) { width: 76px; white-space: normal; }
#delayTable th:nth-child(5), #delayTable td:nth-child(5),
#readyTable th:nth-child(5), #readyTable td:nth-child(5) { width: 30%; }
#delayTable th:nth-child(6), #delayTable td:nth-child(6),
#readyTable th:nth-child(6), #readyTable td:nth-child(6) { width: 20%; }
#delayTable th:nth-child(7), #delayTable td:nth-child(7),
#readyTable th:nth-child(7), #readyTable td:nth-child(7) { width: 30%; white-space: normal; }
#delayTable th:nth-child(8), #delayTable td:nth-child(8),
#readyTable th:nth-child(8), #readyTable td:nth-child(8) { width: 72px; }
#delayTable th:nth-child(9), #delayTable td:nth-child(9),
#readyTable th:nth-child(9), #readyTable td:nth-child(9) { width: 84px; }

/* Order cell: the number on top, its two icons (line items, edit) below —
   keeps the Order column narrow. */
.delay-order-actions {
  display: flex;
  gap: 0.15rem;
  margin-top: 0.2rem;
}
.delay-order-actions .inv-note-icon-btn { margin-left: 0; padding: 0.2rem; }
/* The line-items button is a labelled pill so it stands out (Dylan,
   2026-09-29); the pencil beside it stays a plain icon. */
.delay-items-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.45rem;
  font-size: 0.72rem;
  font-weight: 600;
  font-family: inherit;
  color: var(--accent);
  background: var(--surface);
  border: 1px solid var(--surface-2);
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.15s;
}
.delay-items-btn:hover { border-color: var(--accent); }

/* Long tags and SKU pills wrap inside their column instead of spilling
   into the next one. */
.delay-tags-cell .inv-tag-badge,
.delay-sku-pill {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
  box-sizing: border-box;
}

/* Line items popup (added 2026-09-29) — grouped like Shopify's order page. */
.modal-card.delay-items-card { max-width: 600px; }
.delay-items-body { padding: 0.75rem 1.5rem 1.25rem; }
.delay-items-shopify-link { font-size: 0.8rem; display: inline-block; margin-bottom: 0.5rem; }
.delay-items-message { font-size: 0.85rem; margin: 0.5rem 0; }
.delay-items-group {
  border: 1px solid var(--surface-2);
  border-radius: 10px;
  padding: 0.5rem 0.75rem;
  margin-top: 0.75rem;
}
.delay-items-group-head {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
  padding: 0.25rem 0 0.4rem;
}
.delay-items-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--surface-2);
}
.delay-items-img {
  width: 48px;
  height: 48px;
  flex: 0 0 48px;
  object-fit: contain;
  border-radius: 8px;
  background: var(--surface);
  border: 1px solid var(--surface-2);
}
.delay-items-img--none {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.6rem;
  color: var(--ink-muted);
  text-align: center;
}
.delay-items-info { flex: 1; min-width: 0; }
.delay-items-title { font-size: 0.85rem; color: var(--ink); overflow-wrap: anywhere; }
.delay-items-meta { font-size: 0.75rem; color: var(--ink-muted); overflow-wrap: anywhere; }
.delay-items-qty { font-size: 0.85rem; color: var(--ink-soft); white-space: nowrap; }
.delay-items-status { display: inline-flex; flex: 0 0 auto; }
.delay-items-status--unfulfilled { color: var(--warn); }
.delay-items-status--fulfilled { color: var(--success-text); }
.delay-items-status--removed { color: var(--ink-muted); }
.delay-items-group--removed .delay-items-title { text-decoration: line-through; color: var(--ink-muted); }
.delay-items-chip {
  display: inline-block;
  margin-top: 0.2rem;
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.05rem 0.4rem;
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--ink-soft);
}
.delay-items-chip--warn { background: var(--warn-soft); color: var(--warn-text-alt); }

#pickupTable { table-layout: fixed; }
#pickupTable th:nth-child(1), #pickupTable td:nth-child(1) { width: 110px; }
#pickupTable th:nth-child(2), #pickupTable td:nth-child(2) { width: 190px; overflow: hidden; text-overflow: ellipsis; }
#pickupTable th:nth-child(3), #pickupTable td:nth-child(3) { width: 130px; }
#pickupTable th:nth-child(4), #pickupTable td:nth-child(4) { width: 40%; }
#pickupTable th:nth-child(5), #pickupTable td:nth-child(5) { width: 36%; }

#ccmTable { table-layout: fixed; }
#ccmTable th:nth-child(1), #ccmTable td:nth-child(1) { width: 110px; }
#ccmTable th:nth-child(2), #ccmTable td:nth-child(2) { width: 190px; overflow: hidden; text-overflow: ellipsis; }
#ccmTable th:nth-child(3), #ccmTable td:nth-child(3) { width: 42%; }
#ccmTable th:nth-child(4), #ccmTable td:nth-child(4) { width: 36%; }

/* Corollaries of the legacy Google Sheet's conditional format rules. */
.delay-badge-urgent { background: var(--cyan-bg); color: var(--cyan-text); }
.delay-badge-cancelled { background: var(--danger-soft); color: var(--danger); }

.delay-etd-overdue {
  background: var(--danger-bg-soft);
  color: var(--danger-text-strong);
  font-weight: 600;
}

.delay-etd-missing {
  color: var(--warn);
  font-style: italic;
}

/* Let Status column badges wrap onto multiple lines instead of overflowing
   the fixed column width now that there can be several at once. */
#delayTable td:nth-child(8) { white-space: normal; }

.delay-checkbox-col { width: 4%; text-align: center; }
.delay-checkbox-col input, .delay-row-checkbox { cursor: pointer; }
/* Header checkbox alignment fix (2026-07-24) — .dash-table th's own
   text-align:left (class+element, higher specificity) was beating
   .delay-checkbox-col's text-align:center (class only) on the <th>
   specifically, so every select-all checkbox sat left-aligned in its
   header cell while each row's own checkbox (a <td>, no competing
   text-align rule there) stayed centered. Confirmed via computed-style
   diff between the header and a body cell. Portal-wide, not AR-scoped,
   since Delay Orders' two select-all checkboxes share this same class
   and had the identical bug. */
.dash-table th.delay-checkbox-col { text-align: center; }

/* Delay Orders per-row one-click actions (Sue, 2026-10-16). "No stock" only
   shows on green rows — that's the highlight it takes off. */
.dash-table th.delay-actions-col { text-align: center; }
td.delay-actions-col { text-align: center; }
.delay-row-action {
  display: block;
  width: 100%;
  margin: 0.15rem 0;
  padding: 0.25rem 0.4rem;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: normal;
  line-height: 1.2;
  border-radius: 8px;
  border: 1px solid var(--ink-muted);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
}
.delay-row-action:hover { background: var(--surface-2); }
.delay-row-action:disabled { opacity: 0.6; cursor: wait; }
.delay-row-action--nostock { display: none; }
tr.delay-row--ready .delay-row-action--nostock { display: block; }
.delay-row-action--ready { border-color: var(--success); color: var(--success); }

.delay-dismissed-badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.2rem 0.5rem;
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--ink-soft);
  line-height: 1.4;
  text-align: center;
}

.delay-dismissed-undo {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--accent, var(--accent));
  text-decoration: underline;
  cursor: pointer;
}

.delay-bulk-bar {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding-top: 0.5rem;
  margin-top: 0.25rem;
  border-top: 1px dashed var(--surface-2);
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.delay-bulk-clear {
  background: none;
  border: none;
  color: var(--ink-muted);
  font-size: 0.8rem;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
}
.delay-bulk-clear:hover { color: var(--ink); }

.delay-filter-toggle {
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  border: 1.5px solid var(--surface-2);
  background: var(--white);
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.delay-filter-toggle:hover { border-color: var(--cyan-border-hover); }
.delay-filter-toggle.active {
  background: var(--cyan-bg);
  border-color: var(--cyan-border);
  color: var(--cyan-text);
}

/* READY toggle uses green instead of the default cyan, matching the
   dark-green delay-row--ready-mention row highlight it filters for. */
.delay-filter-toggle--ready:hover { border-color: var(--success-bg-stronger); }
.delay-filter-toggle--ready.active {
  background: var(--success-soft);
  border-color: var(--success);
  color: var(--success-text);
}

/* ============================================================
   Hover tooltips (added 2026-07-15, made dynamic 2026-07-15) — a single
   shared, JS-positioned element (see auth.js: showDynamicTooltip()),
   not a CSS ::after per element. A fixed "always above, centered" CSS
   tooltip has no way to know it's about to run off the top/side of the
   screen — this measures the real viewport and the hovered element's
   real position on every hover, flips above/below and clamps left/right
   so it always stays fully on-screen no matter how close to an edge the
   trigger is. Being `position: fixed` and clamped within the viewport,
   it also can't ever widen the page's scrollable area (the earlier bug
   with the CSS ::after approach).
   `.tt-below` on a trigger just sets the PREFERRED side (still flips to
   above if there's truly no room below) — used for table headers/rows
   inside .dash-table-wrap's scroll area, where "above" has less room.
   Suppressed entirely via body.tooltips-off, toggled by the "Tooltips"
   switch at the top of the Delay Orders page (delay-orders.js,
   initTooltipToggle()). State persists per-browser via localStorage,
   same pattern as the refresh-reminder snooze.
   ============================================================ */
.dynamic-tooltip {
  position: fixed;
  display: none;
  background: var(--chrome-dark-bg);
  color: var(--chrome-dark-text);
  font-size: 0.72rem;
  font-weight: 500;
  line-height: 1.4;
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  white-space: normal;
  width: max-content;
  max-width: 230px;
  text-align: left;
  z-index: 9999;
  box-shadow: var(--shadow-lg);
  pointer-events: none;
}

.dynamic-tooltip.visible {
  display: block;
  animation: tooltipFadeIn 0.12s ease;
}

@keyframes tooltipFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* "Tooltips" on/off switch — injected into the topbar of every page via
   auth.js (injectTooltipToggle), same pattern as the admin button. */
.tooltip-toggle-btn {
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  border: 1.5px solid var(--surface-2);
  background: var(--white);
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.tooltip-toggle-btn:hover { border-color: var(--accent); }
.tooltip-toggle-btn.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

/* Settings dropdown (added 2026-07-15) — replaces the old admin-only
   topbar icon link. Injected via auth.js (injectSettingsMenu). */
.settings-menu-wrap {
  position: relative;
}

/* Topbar avatars (added 2026-08-12 session 3) — small overlapping circle
   stack, same 32px sizing language as .settings-menu-btn right next to
   it. Active/away is conveyed by opacity + the small dot rather than a
   second color, so it still reads fine for anyone colorblind. */
.topbar-avatars-wrap {
  display: flex;
  align-items: center;
  gap: 0;
}

/* Added 2026-08-12 follow-up — .topbar-right has its own `gap: 1rem`
   between flex children, which sits between this wrap and .user-badge
   on top of any margin here. -1rem cancels that gap; the extra -8px on
   top of it is the actual overlap, matching the -8px already used
   between individual avatars inside the stack. Only applied when
   non-empty, via JS toggling this class, so .user-badge doesn't shift
   on days nobody else is active. */
.topbar-avatars-wrap--has-content {
  margin-right: calc(-1rem - 8px);
}

.topbar-avatar {
  position: relative;
  z-index: 1;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  overflow: visible;
  border: 2px solid var(--white);
  margin-left: -8px;
  opacity: 0.45;
  transition: opacity 0.15s;
  flex-shrink: 0;
}

.topbar-avatar:first-child { margin-left: 0; }

.topbar-avatar--active { opacity: 1; }

.topbar-avatar--active::after {
  content: '';
  position: absolute;
  bottom: -1px;
  right: -1px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--success);
  border: 1.5px solid var(--white);
}

.topbar-avatar img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

.topbar-avatar-initial {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
  color: var(--ink-muted);
  font-size: 0.7rem;
  font-weight: 700;
}

.settings-menu-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.settings-menu-btn:hover { color: var(--accent); background: var(--accent-soft); }

.settings-menu-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 0.4rem;
  min-width: 180px;
  z-index: 200;
}
.settings-menu-dropdown.open { display: block; }

.settings-menu-item {
  display: block;
  padding: 0.55rem 0.75rem;
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  transition: background 0.15s;
}
.settings-menu-item:hover { background: var(--surface-2); }

/* Modifier for a <button>-based dropdown item (2026-07-24, added for the
   Dark mode toggle) -- .settings-menu-item's own rules already cover
   spacing/font/hover, this just resets the browser's default button
   chrome (border/background/width/text-align/font-family/cursor) so it
   matches the <a>-based items exactly. */
.settings-menu-item--button {
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  font-family: var(--font-body);
  cursor: pointer;
}

.settings-menu-divider {
  height: 1px;
  background: var(--surface-2);
  margin: 0.3rem 0.2rem;
}

/* Tasks topbar icon (added 2026-08-10) — an <a>, not a <button> like the
   other settings-menu-btn icons, so it needs its own text-decoration
   reset, same as .topbar-back-btn above. Badge reuses .notif-bell-badge
   below as-is. */
.tasks-icon-btn { text-decoration: none; }

/* Notification bell (added 2026-07-30) — reuses the settings-menu-wrap/
   btn/dropdown classes above for the icon button and dropdown shell, plus
   these bell-specific additions for the badge and per-row layout. */
.notif-bell-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--danger);
  color: white;
  font-size: 0.65rem;
  font-weight: 700;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.notif-bell-dropdown {
  min-width: 280px;
  max-width: 340px;
}

/* Topbar ☰ menu (2026-09-24) — auth.js injectTopbarMenu() MOVES the real
   Tasks / Settings / bug / Tooltips / Sign out buttons (and the bell on a
   tight screen) into this panel, so everything below restyles those same
   elements as rows. Their own dropdowns open in place under the row
   (accordion) rather than flying out sideways, which stays on-screen at any
   width. Deliberately NOT .settings-menu-dropdown: closeOtherTopbarDropdowns()
   closes every one of those, which would close this panel when a submenu
   inside it opens. */
.topbar-menu-panel {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: min(300px, calc(100vw - 2rem));
  max-height: calc(100vh - 80px);
  overflow-y: auto;
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 0.4rem;
  z-index: 200;
}
.topbar-menu-panel.open { display: block; }
.topbar-menu-label { display: none; }
.topbar-menu-panel .topbar-menu-label { display: inline; }

.topbar-menu-panel .settings-menu-btn,
.topbar-menu-panel .tooltip-toggle-btn,
.topbar-menu-panel .btn-signout {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.6rem;
  width: 100%;
  height: auto;
  padding: 0.55rem 0.75rem;
  border: none;
  border-radius: 6px;
  background: none;
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.topbar-menu-panel .settings-menu-btn svg { flex-shrink: 0; color: var(--ink-muted); }
.topbar-menu-panel .settings-menu-btn:hover,
.topbar-menu-panel .tooltip-toggle-btn:hover { background: var(--surface-2); color: var(--ink); }
.topbar-menu-panel .tooltip-toggle-btn.active { color: var(--accent); }
.topbar-menu-panel .btn-signout:hover { background: var(--surface-2); color: var(--danger); }
/* A row's count sits at its right end instead of on the icon's corner. */
.topbar-menu-panel .notif-bell-badge { position: static; margin-left: auto; order: 1; }
.topbar-menu-panel .settings-menu-dropdown {
  position: static;
  min-width: 0;
  max-width: none;
  margin: 0.15rem 0 0.35rem 1.1rem;
  padding: 0.2rem;
  box-shadow: none;
  background: var(--surface);
}

.notif-bell-empty {
  padding: 0.75rem;
  font-size: 0.82rem;
  color: var(--ink-muted);
  text-align: center;
}

.notif-bell-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem;
  border-radius: 6px;
}
.notif-bell-row:hover { background: var(--surface-2); }

.notif-bell-row-main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.25rem 0.4rem;
  text-decoration: none;
  color: var(--ink);
  min-width: 0;
}
.notif-bell-row-label {
  font-size: 0.82rem;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.notif-bell-row-label-group {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  overflow: hidden;
}
.notif-bell-row-count {
  flex-shrink: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--danger);
  background: var(--danger-soft);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
}

/* Agent notification rows — David/Zipp's own photo instead of the
   generic red count pill (added 2026-08-07, per Dylan's ask). Small,
   circular, same visual language as .agent-avatar-placeholder's
   initials fallback but sized for this compact dropdown context. */
.notif-bell-row-avatar {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.notif-bell-row-avatar--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.65rem;
  font-weight: 700;
}

.notif-bell-row-actions {
  display: flex;
  gap: 0.2rem;
  flex-shrink: 0;
}
.notif-bell-dismiss-btn {
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--ink-muted);
  background: var(--surface);
  border: none;
  border-radius: 5px;
  padding: 0.2rem 0.4rem;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.notif-bell-dismiss-btn:hover { background: var(--surface-2); color: var(--ink); }

/* Shared table zoom control (added 2026-07-15) — see js/table-zoom.js.
   One instance of this markup gets injected into every element with class
   "table-zoom-controls" already present in a page's toolbar. */
.table-zoom-controls {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.table-zoom-btn {
  width: 26px;
  height: 26px;
  border: 1.5px solid var(--surface-2);
  background: var(--white);
  border-radius: 6px;
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, border-color 0.15s;
}
.table-zoom-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.table-zoom-btn:disabled { opacity: 0.35; cursor: default; }

.table-zoom-readout {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-muted);
  min-width: 2.6em;
  text-align: center;
}

.table-zoom-reset {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--ink-muted);
  background: none;
  border: none;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
}
.table-zoom-reset:hover { color: var(--ink); }

/* Linkable SKU column — re-added 2026-07-13 so Dylan can spot-check which
   SKU(s) the portal thinks are ready to link, alongside their live
   Individual-variant on-hand/available numbers. */
.delay-sku-pill {
  display: inline-block;
  font-size: 0.76rem;
  padding: 0.15rem 0.5rem;
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  margin: 0.1rem 0.2rem 0.1rem 0;
  border: 1px solid var(--surface-2);
}

.delay-sku-pill--none {
  color: var(--ink-muted);
  font-style: italic;
  border-style: dashed;
}

.delay-sku-pill--ready {
  background: var(--success-soft);
  border-color: var(--success-border-soft);
  color: var(--success-text);
}

.delay-search-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.delay-search-wrap .dash-search-input {
  padding-right: 2rem;
}

/* Datalist-backed search inputs (added 2026-08-12, session 8 — the
   Inventory Monitor vendor filters) get extra right padding, and their
   clear button sits further left — browsers draw a small native
   dropdown-arrow indicator for <input list="...">, right where the
   plain-search clear button normally sits, and the two were overlapping. */
.delay-search-wrap .dash-search-input[list] {
  padding-right: 3.4rem;
}
.delay-search-wrap .dash-search-input[list] + .delay-search-clear {
  right: 1.5rem;
}

.delay-search-clear {
  position: absolute;
  right: 0.5rem;
  top: 50%;
  transform: translateY(-50%);
  border: none;
  background: none;
  color: var(--ink-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.15rem 0.3rem;
  border-radius: 4px;
}
.delay-search-clear:hover { color: var(--ink); background: var(--surface-2); }

.delay-sku-link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
}
.delay-sku-link:hover { text-decoration: underline; }

.delay-back-to-top-btn {
  background: var(--accent);
  color: var(--on-accent);
  border: 1.5px solid var(--accent);
  border-radius: var(--radius);
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.delay-back-to-top-btn:hover {
  background: var(--accent-dark);
  border-color: var(--accent-dark);
}

/* ============================================================
   Accounts Receivable page (2026-07-14)
   ============================================================ */

/* Tighter cell padding than the shared .dash-table default (2026-07-14) —
   the Active Orders table has 11 columns including a toggle and an
   actions button, which were getting clipped at the default 1rem
   horizontal padding on smaller/laptop displays. Scoped to these two
   tables specifically so other dash-tables sitewide are unaffected.
   Squeezed further same day after Dylan's screenshot showed it was still
   clipping — the AP Email column (long institutional addresses) and the
   inline Status <select> (styled for standalone toolbar use, with its
   own generous internal padding) turned out to be the real space hogs,
   not just the td padding. */
#arActiveTable th, #arActiveTable td,
#arHistoryTable th, #arHistoryTable td {
  padding: 0.3rem 0.4rem;
}
#arActiveTable, #arHistoryTable {
  font-size: 0.76rem;
}

/* AP Email truncates with an ellipsis + native title-attribute tooltip
   (set in accounts-receivable.js) instead of forcing the column to its
   full nowrap width — some institutional addresses are 40+ characters. */
#arActiveTable td.ar-email-cell,
#arHistoryTable td.ar-email-cell {
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Same truncate-with-tooltip treatment for PO# (added 2026-07-14, second
   squeeze pass) — applied to the inline <span> (see arPoCell() in
   accounts-receivable.js) rather than the <td> itself, so the underlying
   text node is untouched and fully selectable/copyable even though it's
   visually clipped. */
.ar-truncate {
  display: inline-block;
  max-width: 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

/* Compact variant of .ar-status-filter for the inline per-row dropdown —
   the standalone toolbar filter needs comfortable click targets, but the
   same padding repeated 50+ times down a column adds up fast. */
.ar-status-select-inline {
  padding: 0.15rem 0.3rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.74rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--white);
  max-width: 110px;
}

.ar-metrics-row {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.ar-outstanding-metric {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  background: var(--white);
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 0.6rem 1.1rem;
  min-width: 160px;
}
.ar-outstanding-metric--pastdue {
  border-color: var(--danger-border-soft);
  background: var(--danger-bg-faint);
}
.ar-outstanding-metric--pastdue .ar-outstanding-value { color: var(--danger); }
.ar-outstanding-label {
  font-size: 0.75rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.ar-outstanding-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--ink);
}

.ar-status-filter {
  padding: 0.5rem 0.75rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.8rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--white);
}

/* Invoice Sent row highlight (Active Orders tab, added 2026-07-22) —
   deliberately light blue, not green/success-colored, since green could
   read as "paid" which this status is not. Purely a visual flag that an
   invoice has gone out. */
.ar-row-invoice-sent td {
  background: var(--info-soft);
}
.ar-row-invoice-sent:hover td {
  background: var(--info-soft-hover);
}
.ar-row-past-due td {
  background: var(--danger-soft);
}
.ar-row-past-due:hover td {
  background: var(--danger-bg-soft);
}

/* Simple toggle switch for the Invoice Paid column — deliberately its own
   control, separate from any Shopify paid-status display, since the two
   are independent (see accounts-receivable.js header note). */
.ar-toggle {
  position: relative;
  display: inline-block;
  width: 38px;
  height: 22px;
}
.ar-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
}
.ar-toggle-slider {
  position: absolute;
  cursor: pointer;
  top: 0; left: 0; right: 0; bottom: 0;
  background: var(--surface-2);
  border-radius: 999px;
  transition: background 0.15s;
}
.ar-toggle-slider::before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 3px;
  bottom: 3px;
  background: var(--white);
  border-radius: 50%;
  transition: transform 0.15s;
}
.ar-toggle input:checked + .ar-toggle-slider {
  background: var(--success-strong);
}
.ar-toggle input:checked + .ar-toggle-slider::before {
  transform: translateX(16px);
}

/* Per-order automation pause button (added 2026-07-29, sizing fixed
   same day — .delay-nav-btn is hard-locked to a 26x26px icon box, fine
   for the single-glyph buttons (📄/✉/⋯) it was designed for, but
   "Automate"/"Manual" text was wrapping and getting clipped by that
   fixed height, confirmed via a real screenshot. Overriding width/
   padding/white-space/font-size here rather than touching .delay-nav-btn
   itself, which every other icon button in this file still depends on
   staying exactly 26x26.) "Manual" (paused) also gets a warn tint so a
   paused-out order is easy to spot at a glance in a table full of
   otherwise-identical rows. */
.ar-automation-pause-btn {
  width: auto;
  height: 26px;
  padding: 0 0.5rem;
  font-size: 0.72rem;
  white-space: nowrap;
  line-height: 24px;
}
.ar-automation-pause-btn.ar-automation-paused {
  background: var(--warn-soft);
  color: var(--warn-text);
  border-color: var(--warn);
}

/* Task modal's Delete button (fixed 2026-08-07) — same root cause as
   .ar-automation-pause-btn just above: .delay-nav-btn is hard-locked to
   a 26x26px icon box, fine for single-glyph buttons, but "🗑 Delete" has
   real text alongside the icon and was overflowing/clipping (confirmed
   via Dylan's screenshot). Same fix shape — override width/padding/
   white-space/font-size here, leave .delay-nav-btn itself untouched. */
.tasks-delete-btn {
  width: auto;
  height: 26px;
  padding: 0 0.6rem;
  font-size: 0.78rem;
  white-space: nowrap;
  line-height: 24px;
}

/* Mark Paid button (Active Orders row) — added 2026-07-22, replaces the
   old ar-toggle checkbox on this row (ar-toggle itself is untouched —
   still used by the automation-mode toggle in the AR topbar). */
/* Last Email badge, made clickable (added 2026-07-29) — a plain,
   unstyled button wrapper so the badge inside still looks exactly like
   the read-only version did, just with a pointer cursor and a subtle
   hover cue that it's clickable. */
.ar-last-email-btn {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
}
.ar-last-email-btn:hover .delay-badge { filter: brightness(1.1); }
.ar-last-email-btn:hover .delay-muted { text-decoration: underline; }

/* Email History modal list (added 2026-07-29) */
.ar-email-history-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.ar-email-history-row {
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 0.6rem 0.75rem;
}
.ar-email-history-row-top {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.ar-email-history-time {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--ink-muted);
  white-space: nowrap;
}
.ar-email-history-row-detail {
  margin-top: 0.4rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

/* Order Detail modal (added 2026-07-30) — the Shopify-order quick-view popup */
.ar-order-detail-synced {
  font-size: 0.78rem;
  color: var(--ink-muted);
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--surface-2);
}
.ar-order-detail-section {
  margin-bottom: 1.1rem;
}
.ar-order-detail-section h3 {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 0.5rem 0;
}
.ar-order-detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem 1rem;
  font-size: 0.85rem;
  color: var(--ink);
}
.ar-order-detail-items {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
}
.ar-order-detail-items th {
  text-align: left;
  padding: 0.4rem 0.5rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border-bottom: 1px solid var(--surface-2);
}
.ar-order-detail-items td {
  padding: 0.5rem;
  border-bottom: 1px solid var(--surface);
  color: var(--ink-soft);
  vertical-align: top;
}
.ar-order-detail-items tr:last-child td { border-bottom: none; }

.ar-mark-paid-btn {
  font-size: 0.78rem;
  padding: 0.3rem 0.65rem;
}
/* Generic block-style choice button for a modal presenting 2-3 options —
   originally built just for the Mark Paid modal (hence ar-mark-paid-option),
   renamed ar-modal-option once the Send Email chooser modal needed the
   exact same look. */
.ar-modal-option {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.5rem;
}
.ar-modal-option:last-child { margin-bottom: 0; }
.ar-modal-option span {
  display: block;
  font-weight: 400;
  font-size: 0.78rem;
  color: var(--ink-soft);
  margin-top: 0.15rem;
}
.ar-mark-paid-warning {
  background: var(--danger-soft);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  color: var(--danger-text);
  font-size: 0.82rem;
}

/* Extra recipient rows (To/CC) in the Review & Send modal, added
   2026-07-23 — one row per additional email, rendered by
   renderArSendModalExtras() in js/accounts-receivable.js. */
.ar-send-extra-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.ar-send-extra-remove {
  border: none;
  background: none;
  color: var(--ink-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.15rem 0.4rem;
  border-radius: 4px;
  flex-shrink: 0;
}
.ar-send-extra-remove:hover { color: var(--danger); background: var(--surface-2); }

/* AP Email copy-to-clipboard button (added 2026-07-23) */
.ar-copy-btn {
  border: none;
  background: none;
  color: var(--ink-muted);
  cursor: pointer;
  font-size: 0.85rem;
  padding: 0.1rem 0.25rem;
  border-radius: 4px;
  flex-shrink: 0;
  line-height: 1;
}
.ar-copy-btn:hover { background: var(--surface-2); color: var(--ink); }

/* Remittance Review tab — pairing highlight for a remittance that covers
   more than one order (added 2026-07-23). Applied ONLY when a remittance
   has 2+ linked orders in view (renderArRemittanceTable's groupColorIdx
   logic) — a single-order remittance gets no tint at all, so a highlight
   here always means "these rows are paired," never anything else.
   Deliberately pastel/muted, distinct from the status badges' own colors
   so the two visual systems don't compete. */
.ar-remittance-group-a td { background: var(--remit-a-bg); }
.ar-remittance-group-a:hover td { background: var(--remit-a-bg-hover); }
.ar-remittance-group-b td { background: var(--remit-b-bg); }
.ar-remittance-group-b:hover td { background: var(--remit-b-bg-hover); }
.ar-remittance-group-c td { background: var(--remit-c-bg); }
.ar-remittance-group-c:hover td { background: var(--remit-c-bg-hover); }
.ar-remittance-group-d td { background: var(--remit-d-bg); }
.ar-remittance-group-d:hover td { background: var(--remit-d-bg-hover); }

/* Column resize (added 2026-07-23, overlap fix + shared-border resize
   2026-07-23; extended to Draft Order Creation's Needs Review/History
   tables 2026-08-11) — scoped to just these 7 tables by ID, not the
   shared .dash-table class, so no other page's tables are affected.
   table-layout: fixed is required for a manually-set <th> width to
   actually stick rather than the browser re-computing column widths from
   content on every render. width:100% keeps the table's total width
   bounded to its container — this is what lets column resize "borrow"
   width from the neighboring column instead of growing the whole table
   (see initArColumnResize()/handleArColumnResizeMove() in the JS). */
#arActiveTable, #arHistoryTable, #arCustomersTable, #arRemittanceTable, #arPendingTable,
#doReviewTable, #doHistoryTable {
  table-layout: fixed;
  width: 100%;
}
#arActiveTable th, #arHistoryTable th, #arCustomersTable th, #arRemittanceTable th, #arPendingTable th,
#doReviewTable th, #doHistoryTable th {
  position: relative;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The actual fix for content overlapping into the next column (e.g. the
   Status <select> spilling into Total) — a fixed-width column doesn't
   automatically clip its own content; without this, anything wider than
   its cell (a <select>, a badge, long text) visually overflows into
   whatever's next instead of just getting cut off at the boundary. */
#arActiveTable td, #arHistoryTable td, #arCustomersTable td, #arRemittanceTable td, #arPendingTable td,
#doReviewTable td, #doHistoryTable td {
  overflow: hidden;
}
/* The trailing actions column (Invoice PDF / email / "..." buttons, etc.)
   is deliberately EXEMPT from that clipping — added 2026-07-23 after
   Dylan found the action buttons getting cut off by default. Unlike a
   text/badge cell, clipping an interactive button means it becomes
   unclickable, not just visually truncated, so this column is always
   allowed to overflow rather than risk that. It's also always the LAST
   column in every one of these tables, so overflowing to the right never
   overlaps another column's content. */
#arActiveTable td:last-child, #arHistoryTable td:last-child, #arCustomersTable td:last-child,
#arRemittanceTable td:last-child, #arPendingTable td:last-child,
#doReviewTable td:last-child, #doHistoryTable td:last-child {
  overflow: visible;
}
.ar-col-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  user-select: none;
  z-index: 2;
}
.ar-col-resize-handle:hover, .ar-col-resize-handle:active {
  background: var(--accent-soft);
}

/* =============================================
   PRODUCT LOOKUP (added 2026-07-16)
   ============================================= */

.pl-search-row {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  margin-bottom: 1.5rem;
}

.pl-suggestions {
  position: absolute;
  z-index: 20;
  margin-top: 0.4rem;
  width: 100%;
  max-width: 640px;
  background: var(--white);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  max-height: 360px;
  overflow-y: auto;
}

.pl-suggestion-row {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.55rem 0.75rem;
  cursor: pointer;
  border-bottom: 1px solid var(--surface-2);
}
.pl-suggestion-row:last-child { border-bottom: none; }
.pl-suggestion-row:hover { background: var(--surface); }

.pl-suggestion-thumb {
  width: 34px; height: 34px; border-radius: 6px; background: var(--surface-2);
  flex-shrink: 0; overflow: hidden; display: flex; align-items: center; justify-content: center;
}
.pl-suggestion-thumb img { width: 100%; height: 100%; object-fit: cover; }

.pl-suggestion-title { font-size: 0.875rem; font-weight: 500; color: var(--ink); }
.pl-suggestion-sub { font-size: 0.75rem; color: var(--ink-muted); }
.pl-suggestion-empty { padding: 0.75rem; font-size: 0.85rem; color: var(--ink-muted); }

.pl-metrics-dropdown { position: relative; flex-shrink: 0; }

.pl-metrics-btn {
  display: flex; align-items: center; gap: 0.4rem;
  background: var(--white); border: 1.5px solid var(--surface-2); border-radius: var(--radius);
  padding: 0.6rem 0.9rem; font-size: 0.85rem; color: var(--ink-soft); box-shadow: var(--shadow);
}
.pl-metrics-btn:hover { border-color: var(--accent); color: var(--ink); }

.pl-metrics-menu {
  position: absolute; right: 0; top: calc(100% + 0.4rem); z-index: 20;
  background: var(--white); border: 1px solid var(--surface-2); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 0.6rem 0.75rem; min-width: 240px;
}
.pl-metrics-option {
  display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--ink-soft);
  padding: 0.3rem 0; cursor: pointer;
}
.pl-metrics-search {
  width: 100%; font-family: var(--font-body); font-size: 0.82rem;
  padding: 0.4rem 0.55rem; border: 1.5px solid var(--surface-2); border-radius: 6px;
  margin-bottom: 0.4rem; outline: none;
}
.pl-metrics-search:focus { border-color: var(--accent); }
.pl-metrics-group { }
.pl-metrics-section-label {
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.03em; font-weight: 600;
  color: var(--ink-muted); margin: 0.6rem 0 0.2rem;
}
.pl-metrics-menu { max-height: 360px; overflow-y: auto; }

.pl-empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.75rem; padding: 4rem 1rem; color: var(--ink-muted); text-align: center;
}

.pl-product-header {
  display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap;
}
.pl-product-title { font-size: 1.4rem; font-weight: 600; cursor: pointer; }
.pl-shopify-link { font-size: 0.8rem; color: var(--accent); }

.pl-cards-grid, .pl-cards-subgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
}
.pl-cards-grid { margin-bottom: 1rem; }

.pl-variant-block { grid-column: 1 / -1; margin-bottom: 0.5rem; }
.pl-variant-heading {
  font-size: 0.9rem; font-weight: 600; color: var(--ink-soft);
  margin: 0.75rem 0 0.5rem; padding-top: 0.75rem; border-top: 1px dashed var(--surface-2);
}

.pl-card {
  background: var(--white); border: 1px solid var(--surface-2); border-radius: var(--radius);
  padding: 0.9rem 1rem; box-shadow: var(--shadow);
}
.pl-card-wide { grid-column: 1 / -1; }

.pl-card-label {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ink-muted); margin-bottom: 0.4rem; font-weight: 600;
}

.pl-card-vendor { display: flex; align-items: center; gap: 0.6rem; }
.pl-vendor-icon { width: 32px; height: 32px; object-fit: contain; border-radius: 4px; }
.pl-vendor-icon--fallback {
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  background: var(--surface-2); border-radius: 4px; font-size: 1rem;
}

.pl-product-photo { width: 100%; max-width: 160px; border-radius: 8px; object-fit: cover; }
.pl-no-photo {
  width: 100%; max-width: 160px; height: 100px; border-radius: 8px; background: var(--surface-2);
  display: flex; align-items: center; justify-content: center; color: var(--ink-muted); font-size: 0.8rem;
}

.pl-sku-value { font-family: monospace; font-size: 0.9rem; }

.pl-inv-grid { display: flex; gap: 1.25rem; }
.pl-inv-grid > div { display: flex; flex-direction: column; align-items: center; gap: 0.15rem; }
.pl-inv-num { font-size: 1.15rem; font-weight: 600; }
.pl-inv-caption { font-size: 0.7rem; color: var(--ink-muted); }

.pl-inv-warn-badge {
  display: inline-block; font-size: 0.65rem; font-weight: 600; text-transform: none;
  color: var(--warn); background: var(--warn-soft); border-radius: 999px; padding: 0.1rem 0.5rem;
  margin-left: 0.4rem; cursor: help;
}
.pl-inv-note {
  display: inline-block; font-size: 0.65rem; font-weight: 500; text-transform: none;
  color: var(--ink-muted); margin-left: 0.4rem; cursor: help; border-bottom: 1px dotted var(--ink-muted);
}
.pl-inv-component-row { margin-bottom: 0.6rem; padding-bottom: 0.6rem; border-bottom: 1px dashed var(--surface-2); }
.pl-inv-component-row:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; }
.pl-inv-component-sku { font-family: monospace; font-size: 0.78rem; color: var(--ink-soft); margin-bottom: 0.3rem; }

.pl-editable { cursor: pointer; border-bottom: 1px dashed transparent; }
.pl-editable:hover { border-bottom-color: var(--accent); }
.pl-none-set { color: var(--ink-muted); font-style: italic; font-size: 0.85rem; }

.pl-inline-input {
  width: 100%; font-family: var(--font-body); font-size: 0.85rem; padding: 0.35rem 0.5rem;
  border: 1.5px solid var(--accent); border-radius: 6px; margin-bottom: 0.35rem;
}
textarea.pl-inline-input { min-height: 70px; resize: vertical; }
.pl-inline-save, .pl-inline-cancel {
  font-size: 0.75rem; padding: 0.3rem 0.6rem; border-radius: 6px; border: none; margin-right: 0.4rem;
}
.pl-inline-save { background: var(--accent); color: var(--on-accent); }
.pl-inline-cancel { background: var(--surface-2); color: var(--ink-soft); }

.pl-ref-list { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.pl-ref-chip {
  display: flex; align-items: center; gap: 0.4rem; background: var(--surface);
  border: 1px solid var(--surface-2); border-radius: 999px; padding: 0.25rem 0.6rem 0.25rem 0.25rem;
  font-size: 0.78rem; cursor: pointer;
}
.pl-ref-chip:hover { border-color: var(--accent); }
.pl-ref-chip img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; }

.pl-mf-row {
  display: flex; justify-content: space-between; gap: 1rem; padding: 0.4rem 0;
  border-bottom: 1px solid var(--surface-2); font-size: 0.85rem;
}
.pl-mf-row:last-child { border-bottom: none; }
.pl-mf-label { color: var(--ink-muted); flex-shrink: 0; }

/* ---- Tabs ---- */
.pl-toolbar-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; margin-bottom: 1.25rem; flex-wrap: wrap;
}
.pl-tabs { display: flex; gap: 0.4rem; }
.pl-tab {
  background: transparent; border: none; padding: 0.5rem 0.9rem; font-size: 0.88rem;
  font-weight: 500; color: var(--ink-muted); border-radius: var(--radius);
  border-bottom: 2px solid transparent;
}
.pl-tab:hover { color: var(--ink); background: var(--surface-2); }
.pl-tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* ---- Selected-metafields chip list (Display options dropdown) ---- */
#plMetricsSelectedList {
  padding-bottom: 0.4rem; margin-bottom: 0.4rem; border-bottom: 1px solid var(--surface-2);
}
.pl-metrics-selected-label {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em; font-weight: 600;
  color: var(--ink-muted); margin-bottom: 0.3rem;
}
.pl-metrics-selected-chip {
  display: inline-flex; align-items: center; gap: 0.35rem; background: var(--accent-soft);
  color: var(--accent-dark); border-radius: 999px; padding: 0.15rem 0.3rem 0.15rem 0.6rem;
  font-size: 0.75rem; margin: 0 0.3rem 0.3rem 0;
}
.pl-metrics-chip-remove {
  background: transparent; border: none; color: var(--accent-dark); font-size: 0.95rem;
  line-height: 1; padding: 0.1rem 0.3rem; border-radius: 50%;
}
.pl-metrics-chip-remove:hover { background: var(--accent); color: var(--on-accent); }

/* ---- Missing Metafields tab ---- */
.pl-missing-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; margin-bottom: 1.25rem;
}
.pl-missing-toolbar-actions { display: flex; gap: 0.6rem; }
.pl-missing-section-title { font-size: 0.95rem; font-weight: 600; margin: 1.25rem 0 0.6rem; }
.pl-missing-section-title:first-child { margin-top: 0; }
.pl-missing-truncated-warning {
  background: var(--warn-soft); color: var(--warn-text); border-radius: var(--radius);
  padding: 0.6rem 0.9rem; font-size: 0.82rem; margin-bottom: 1rem;
}
.pl-missing-table { display: flex; flex-direction: column; gap: 0.6rem; }
.pl-missing-row {
  display: flex; align-items: flex-start; gap: 0.9rem; background: var(--white);
  border: 1px solid var(--surface-2); border-radius: var(--radius); padding: 0.75rem 1rem;
  box-shadow: var(--shadow);
}
.pl-missing-row-thumb {
  width: 44px; height: 44px; border-radius: 6px; background: var(--surface-2);
  flex-shrink: 0; overflow: hidden;
}
.pl-missing-row-thumb img { width: 100%; height: 100%; object-fit: cover; }
.pl-missing-row-info { min-width: 180px; flex-shrink: 0; }
.pl-missing-row-title { font-size: 0.88rem; font-weight: 500; }
.pl-missing-row-sub { font-size: 0.76rem; color: var(--ink-muted); font-family: monospace; }
.pl-missing-row-fields { flex: 1; display: flex; flex-direction: column; gap: 0.4rem; }
.pl-missing-field-row { display: flex; align-items: center; gap: 0.6rem; font-size: 0.82rem; }
.pl-missing-field-label { color: var(--ink-muted); min-width: 140px; flex-shrink: 0; }

/* =============================================
   CUSTOMER SERVICE ASSISTANT
   ============================================= */

.btn-sm { padding: 0.4rem 0.75rem; font-size: 0.8rem; }

.cs-tabs {
  display: flex; gap: 0.25rem; border-bottom: 1px solid var(--surface-2);
  margin-bottom: 1.25rem;
}
.cs-tab {
  background: none; border: none; padding: 0.7rem 1.1rem; font-size: 0.88rem;
  font-weight: 500; color: var(--ink-muted); cursor: pointer; border-bottom: 2px solid transparent;
  font-family: var(--font-body); transition: color 0.15s, border-color 0.15s;
}
.cs-tab:hover { color: var(--ink); }
.cs-tab.active { color: var(--accent); border-bottom-color: var(--accent); }

.cs-chat-layout {
  display: grid; grid-template-columns: 1fr 340px; gap: 1.25rem; align-items: start;
}
@media (max-width: 900px) { .cs-chat-layout { grid-template-columns: 1fr; } }

.cs-chat-container { height: calc(100vh - 320px); min-height: 460px; }

.cs-chat-image {
  display: block; max-width: 220px; border-radius: 8px; margin-bottom: 0.5rem;
}

.cs-thumbs { display: flex; gap: 0.4rem; margin-top: 0.6rem; }
.cs-thumb {
  background: none; border: 1px solid var(--surface-2); border-radius: 6px;
  padding: 0.2rem 0.5rem; font-size: 0.85rem; cursor: pointer; opacity: 0.6;
  transition: opacity 0.15s, border-color 0.15s;
}
.cs-thumb:hover { opacity: 1; }
.cs-thumb.active { opacity: 1; border-color: var(--accent); background: var(--accent-soft); }

.cs-attach-preview {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 1.25rem;
  border-top: 1px solid var(--surface-2);
}
.cs-attach-preview img { height: 44px; border-radius: 6px; }
.cs-attach-preview button {
  background: var(--surface-2); border: none; border-radius: 50%; width: 22px; height: 22px;
  cursor: pointer; font-size: 0.75rem;
}

.cs-order-panel {
  background: var(--white); border-radius: var(--radius-lg); box-shadow: var(--shadow);
  padding: 1rem; height: calc(100vh - 320px); min-height: 460px; overflow-y: auto;
}
.cs-order-panel-header {
  font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--ink-muted); margin-bottom: 0.75rem;
}
.cs-order-manual { display: flex; gap: 0.4rem; margin-bottom: 1rem; }
.cs-order-manual input {
  flex: 1; padding: 0.4rem 0.6rem; border: 1.5px solid var(--surface-2); border-radius: var(--radius);
  font-size: 0.8rem; font-family: var(--font-body);
}
.cs-order-empty { color: var(--ink-muted); font-size: 0.82rem; line-height: 1.5; }
.cs-order-name { font-size: 1.05rem; font-weight: 600; margin-bottom: 0.6rem; color: var(--ink); }
.cs-order-row {
  display: flex; justify-content: space-between; gap: 0.5rem; font-size: 0.82rem;
  padding: 0.3rem 0; border-bottom: 1px solid var(--surface); color: var(--ink-soft);
}
.cs-order-row span:first-child { color: var(--ink-muted); }
.cs-order-tags { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.6rem 0; }
.cs-tag-pill {
  background: var(--surface-2); color: var(--ink-soft); font-size: 0.72rem;
  padding: 0.15rem 0.5rem; border-radius: 999px;
}
.cs-order-section-label {
  font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--ink-muted); margin: 0.9rem 0 0.4rem;
}
.cs-order-items { font-size: 0.82rem; color: var(--ink-soft); display: flex; flex-direction: column; gap: 0.3rem; }
.cs-order-sku { font-family: monospace; font-size: 0.72rem; color: var(--ink-muted); }
.cs-order-note {
  font-size: 0.8rem; color: var(--ink-soft); background: var(--surface); border-radius: var(--radius);
  padding: 0.6rem 0.75rem; line-height: 1.5;
}
/* Copy-to-clipboard buttons in the order panel (2026-09-17 s4) — sized to sit
   inline beside the order number / email without changing row height. */
.hz-copy-btn {
  background: none; border: none; cursor: pointer; padding: 0 0.15rem;
  font-size: 0.8rem; color: var(--ink-muted); vertical-align: middle;
}
.hz-copy-btn:hover { color: var(--ink); }
/* Recent-order rows in the panel (s4) — button-as-row, matching the item rows'
   type scale; the whole row is the click target. */
.hz-recent-order {
  display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem;
  width: 100%; background: none; border: none; padding: 0.25rem 0.2rem; cursor: pointer;
  font-size: 0.82rem; color: var(--ink-soft); font-family: var(--font-body);
  border-radius: var(--radius); text-align: left;
}
.hz-recent-order:hover { background: var(--surface); }

.cs-panel-card {
  background: var(--white); border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: 1.25rem;
}
.cs-panel-card-header {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem;
}
.cs-panel-card-header h2 { font-size: 1.05rem; font-weight: 600; color: var(--ink); }

.cs-saved-list { display: flex; flex-direction: column; gap: 0.6rem; }
.cs-saved-item {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  border: 1px solid var(--surface-2); border-radius: var(--radius); padding: 0.75rem 1rem;
}
.cs-saved-item-label { font-size: 0.9rem; font-weight: 500; color: var(--ink); }
.cs-saved-item-meta { font-size: 0.76rem; color: var(--ink-muted); margin-top: 0.2rem; }

.cs-ratings-filters { display: flex; align-items: flex-end; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap; }
.cs-ratings-filters label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.78rem; color: var(--ink-muted); }
.cs-ratings-filters input[type="date"] {
  padding: 0.4rem 0.6rem; border: 1.5px solid var(--surface-2); border-radius: var(--radius); font-size: 0.82rem;
}
.cs-ratings-table-wrap { overflow-x: auto; }
.cs-ratings-table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
.cs-ratings-table th {
  text-align: left; padding: 0.5rem 0.75rem; border-bottom: 2px solid var(--surface-2);
  color: var(--ink-muted); font-weight: 600; font-size: 0.72rem; text-transform: uppercase;
}
.cs-ratings-table td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--surface); vertical-align: top; }
.cs-ratings-truncate { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.cs-docs-hint { font-size: 0.82rem; color: var(--ink-muted); margin-bottom: 0.9rem; line-height: 1.5; }
.cs-docs-dropzone {
  border: 2px dashed var(--surface-2); border-radius: var(--radius-lg); padding: 2rem;
  text-align: center; color: var(--ink-muted); font-size: 0.88rem; cursor: pointer;
  transition: border-color 0.15s, background 0.15s; margin-bottom: 1.25rem;
}
.cs-docs-dropzone:hover, .cs-docs-dropzone.dragover { border-color: var(--accent); background: var(--accent-soft); }

/* Draft Order Creation upload dropzone — same interaction pattern as
   .cs-docs-dropzone above (Customer Service doc uploads), added
   2026-07-31. Kept as its own class rather than reusing that one since
   this dropzone is shorter (single file, not a document library) and
   scoped to a different page. */
.do-dropzone {
  border: 2px dashed var(--surface-2); border-radius: var(--radius-lg); padding: 1.25rem;
  text-align: center; color: var(--ink-muted); font-size: 0.85rem; cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.do-dropzone:hover, .do-dropzone.dragover { border-color: var(--accent); background: var(--accent-soft); }
.do-dropzone.has-file { color: var(--ink); font-weight: 500; }

/* AR automation toggle lock buttons (added 2026-07-31) — locked by
   default; clicking unlocks the adjacent checkbox for exactly one
   change, then it re-locks itself (see toggleArAutomationLockClick() /
   the top of handleArAutomationToggleChange() and
   handleArRemittanceAutomationToggleChange() in accounts-receivable.js).
   No Supabase-backed state — deliberately client-side only, per Dylan's
   call, since it resets on every page load anyway. */
.ar-lock-btn.unlocked { border-color: var(--danger); color: var(--danger); background: var(--danger-bg-faint); }
.cs-docs-list { display: flex; flex-direction: column; gap: 0.5rem; }
.cs-doc-row {
  display: flex; align-items: center; gap: 1rem; border: 1px solid var(--surface-2);
  border-radius: var(--radius); padding: 0.65rem 1rem;
}
.cs-doc-row-title { font-size: 0.88rem; font-weight: 500; color: var(--ink); flex-shrink: 0; min-width: 200px; }
.cs-doc-row-meta { font-size: 0.76rem; color: var(--ink-muted); flex: 1; }

.cs-copy-btn {
  display: inline-flex; align-items: center; gap: 0.3rem; margin-top: 0.6rem;
  background: var(--surface-2); border: none; border-radius: 6px; padding: 0.3rem 0.6rem;
  font-size: 0.76rem; font-family: var(--font-body); color: var(--ink-soft); cursor: pointer;
  transition: background 0.15s;
}
.cs-copy-btn:hover { background: var(--accent-soft); color: var(--accent-dark); }

.cs-note-bubble .chat-bubble {
  background: var(--warn-soft) !important; border: 1px dashed var(--warn) !important;
  font-size: 0.8rem;
}
.cs-note-label {
  font-size: 0.68rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--warn-text); margin-bottom: 0.4rem;
}

.cs-lookup-notice {
  align-self: center; font-size: 0.74rem; color: var(--ink-muted); background: var(--surface-2);
  border-radius: 999px; padding: 0.25rem 0.7rem; margin: 0.2rem auto;
}

.cs-order-name a { color: var(--ink); text-decoration: none; }
.cs-order-name a:hover { color: var(--accent); text-decoration: underline; }

.cs-order-note-top {
  font-size: 0.8rem; color: var(--ink-soft); background: var(--surface); border-radius: var(--radius);
  padding: 0.55rem 0.7rem; line-height: 1.5; margin-bottom: 0.75rem;
}

.cs-order-items-details summary {
  cursor: pointer; list-style: none;
}
.cs-order-items-details summary::-webkit-details-marker { display: none; }
.cs-order-items-details summary::before { content: '▸ '; }
.cs-order-items-details[open] summary::before { content: '▾ '; }

.cs-order-item-row { display: flex; align-items: center; gap: 0.5rem; }
.cs-order-item-thumb { width: 32px; height: 32px; border-radius: 6px; object-fit: cover; flex-shrink: 0; }
.cs-order-item-thumb-placeholder {
  display: flex; align-items: center; justify-content: center; background: var(--surface);
  font-size: 0.9rem;
}

.cs-bulk-bar { display: flex; gap: 0.5rem; margin-bottom: 0.9rem; }
.cs-danger-btn { color: var(--danger-text-alt); border-color: var(--danger-bg-soft); }
.cs-danger-btn:hover { background: var(--danger-bg-faint); border-color: var(--danger-text-alt); }

.cs-saved-item { position: relative; }
.cs-row-check { margin-right: 0.6rem; flex-shrink: 0; }
.cs-saved-item-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }

.cs-ratings-filters-divider { flex: 1; }
.cs-ratings-table td:first-child, .cs-ratings-table th:first-child { width: 28px; }

.cs-scale-controls {
  display: flex; align-items: center; gap: 0.3rem; background: var(--surface); border-radius: 999px;
  padding: 0.15rem 0.4rem;
}
.cs-scale-btn {
  background: none; border: none; width: 22px; height: 22px; border-radius: 50%; cursor: pointer;
  font-size: 0.95rem; color: var(--ink-soft); line-height: 1;
}
.cs-scale-btn:hover { background: var(--surface-2); }
.cs-scale-value { font-size: 0.72rem; color: var(--ink-muted); min-width: 32px; text-align: center; }

/* =============================================
   DARK MODE (added 2026-07-24)
   =============================================
   Every color the site uses is a CSS custom property defined in :root
   above (a handful of exceptions — toast/tooltips/code block — are
   deliberately fixed regardless of theme, see the --chrome-dark-*
   comment above). That means dark mode is just this one block,
   redefining those same variables on html.theme-dark — nothing else in
   this file needed to change. Toggled via js/auth.js's
   applyThemeState()/toggleTheme(), a settings-dropdown item, persisted
   per-browser via localStorage (same pattern as the Tooltips toggle).

   Known rough edges to expect on first look, not fixed here (flagging
   rather than guessing at a fix): product/logo photos with a white
   background will still show a white box; the login-page and progress-
   bar decorative gradients got a dark pass but weren't pixel-tuned;
   any print stylesheet is unaffected (assumed print is always
   light-on-white, intentionally not touched). */
html.theme-dark {
  --ink:          #e8e8f2;
  --ink-soft:     #b6b6cf;
  --ink-muted:    #9494b3;
  --surface:      #15151f;
  --surface-2:    #262636;
  --white:        #1e1e2b;
  --accent-soft:  #3d1f2c;
  --success-soft: #143621;
  --warn-soft:    #3d2e10;
  --danger-soft:  #3a1616;

  /* Lighter than the dark-mode topbar background (--white, #1e1e2b in
     this mode) so the pill still reads as its own control rather than
     blending into the bar. Unrelated to the 2026-08-07 light-mode fix
     above (light mode now uses --surface-2, a soft neutral) — dark mode
     already had good contrast with its own value and wasn't touched. */
  --growth-toggle-bg:   #34344a;
  --growth-toggle-text: rgba(255,255,255,0.45);

  /* Lighter than every fill on the card in this mode (--white #1e1e2b body,
     --surface #15151f header) so the outline reads as an edge, same role as
     the light-mode pair. */
  --pd-card-border:      #3b3b52;
  --pd-card-border-open: #55556f;

  --high-soft:    #3a1616;
  --med-soft:     #3d2e10;
  --low:          #9ca3af;
  --low-soft:     #262a30;

  --shadow:       0 1px 3px rgba(0,0,0,0.45), 0 4px 16px rgba(0,0,0,0.35);
  --shadow-lg:    0 8px 32px rgba(0,0,0,0.55);

  --success-bg-strong:    #1c3d2a;
  --success-bg-stronger:  #2f6b45;
  --success-bg-faint:     #14261c;
  --warn-text:            #f5a623;
  --warn-text-alt:        #f59e42;
  --danger-text:          #f87171;
  --danger-text-alt:      #f87171;
  --danger-text-strong:   #f87171;
  --danger-bg-soft:       #3d1f1f;
  --danger-bg-faint:      #2a1616;
  --info-badge-bg:        #232a4a;
  --info-badge-text:      #8ba3ff;
  --info-soft:            #16324a;
  --info-soft-hover:      #1c3c58;
  --cyan-bg:              #123a3d;
  --cyan-text:            #67e8f9;
  --border-dashed:        #3a3a4d;
  --bg-soft:              #20202c;

  --remit-a-bg:           #2a2140;
  --remit-a-bg-hover:     #342a52;
  --remit-b-bg:           #1a2e22;
  --remit-b-bg-hover:     #21392a;
  --remit-c-bg:           #332a15;
  --remit-c-bg-hover:     #3d3319;
  --remit-d-bg:           #182a38;
  --remit-d-bg-hover:     #1e3547;
}

/* success-text is kept as its own rule (rather than folded into the
   block above) only because its light-mode value doubles as a border
   color in one place (score-pill) where a lighter dark-mode value would
   look too washed out as a border but reads fine as text elsewhere —
   not worth splitting into two more variables for one edge case. */
html.theme-dark {
  --success-text: #4ade80;
}

/* Decorative gradients (not variable-driven, see the top-of-file
   comment on why) — dark equivalents of the same lavender→surface→pink
   and accent→periwinkle structure. */
html.theme-dark .login-page {
  background: linear-gradient(135deg, #1a1a2e 0%, #14141f 60%, #2a1420 100%);
}

/* Table row hover/zebra rely on --surface for contrast against --white
   cards — already covered by the variable redefinitions above, no
   direct override needed here.

   Native form control color-scheme (2026-07-24) — tells the browser to
   render native widgets (checkboxes, date pickers, scrollbars on some
   browsers) with their dark variants instead of forcing light-styled
   controls onto a dark page. */
html.theme-dark {
  color-scheme: dark;
}

/* pre.inv-code's fixed --chrome-dark-bg (#1a1a2e) sits almost the same
   lightness as --white's dark-mode value (#1e1e2b, the card surface it
   usually sits inside) -- barely distinguishable, unlike light mode where
   a dark code box on a white card is an obvious, deliberate contrast.
   Nudging it darker here keeps that same "distinct code box" feel. */
html.theme-dark pre.inv-code {
  background: #0d0d16;
}

/* ---- Draft Order Creation (added 2026-07-24) ---- */
.do-field-group {
  margin-bottom: 1rem;
}
.do-field-label {
  display: block;
  font-weight: 500;
  font-size: 0.85rem;
  color: var(--ink);
  margin-bottom: 0.35rem;
}
.do-input, .do-textarea {
  width: 100%;
  padding: 0.6rem 0.875rem;
  border: 1.5px solid var(--surface-2);
  border-radius: var(--radius);
  font-size: 0.85rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--surface);
  transition: border-color 0.15s;
}
.do-input:focus, .do-textarea:focus {
  outline: none;
  border-color: var(--accent);
}
.do-input--sm { max-width: 140px; }
.do-input--xs { max-width: 70px; }
.do-textarea { resize: vertical; min-height: 90px; }

.do-source-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 500;
  padding: 0.15rem 0.5rem;
  border-radius: 10px;
  vertical-align: middle;
  white-space: nowrap;
}
.do-source-badge--doc     { background: var(--success-soft); color: var(--success-text, var(--success)); }
.do-source-badge--record  { background: var(--surface-2);    color: var(--ink-soft); }
.do-source-badge--missing { background: var(--danger-soft);  color: var(--danger-text, var(--danger)); }

.do-flag-note {
  font-size: 0.8rem;
  color: var(--danger-text, var(--danger));
  margin-top: 0.35rem;
}

/* Agent avatar upload preview (Tech Room — Advisor/Assistant Agent
   Settings, added 2026-08-06 session 8) */
.agent-avatar-preview, .agent-avatar-placeholder {
  width: 64px; height: 64px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
}
.agent-avatar-placeholder {
  display: flex; align-items: center; justify-content: center; background: var(--surface-2);
  color: var(--ink-muted); font-size: 0.72rem; text-align: center;
}

/* =============================================
   ADVISOR AGENT (added 2026-08-05)
   Reuses the shared .chat-container/.chat-messages/.chat-message/
   .chat-bubble/.chat-input-wrap/.chat-input/.chat-send-btn primitives
   already used by Customer Service, Dashboard/Funnel chat, and the
   Product Assistant — those are the genuinely page-agnostic chat
   building blocks. Everything below is page-scoped chrome (tabs, panel
   card, docs dropzone) — kept as its own prefix rather than reusing the
   cs- versions on an unrelated page, same precedent as .do-dropzone
   being kept separate from .cs-docs-dropzone.
   ============================================= */

/* Layout (added 2026-08-06) — content on the left, tabs as a sticky
   pill column just to the right of it, per Dylan's ask to match the
   same side-nav direction planned for Tech Room. Page-header removed
   entirely on this page (was "Advisor Agent" / "Assistant Agent" + a
   description) — the chat's own header already shows who you're
   talking to, so a second page-level title was redundant, and removing
   it is what actually gets the chat content up near the top of the
   viewport, which was the other half of this ask. */
/* Layout (added 2026-08-06, reworked same session) — chat centers on the
   TRUE page center via a 3-column grid (1fr / chat / 1fr), with the tabs
   living in the right gutter column rather than as a flex sibling that
   shifts the whole group's center. A flex row (tried first) put the tabs
   INSIDE the centering math — content got flex:1 of whatever space was
   left after the tabs, so the chat ended up centered in that leftover
   space, not the page, landing visibly left-of-center. Grid's two 1fr
   gutters are equal by definition regardless of what's inside the right
   one, so the middle column (the chat) is always genuinely centered;
   justify-self:start on the tabs just pulls them to the near edge of
   that right gutter so they sit right beside the chat instead of out at
   the far edge of the page. Page-header removed entirely on this page
   (was "Advisor Agent"/"Assistant Agent" + a description) — the chat's
   own header already shows who you're talking to, so a second page-level
   title was redundant, and removing it is what actually gets the chat
   content up near the top of the viewport, the other half of this ask. */
.advisor-layout {
  display: grid;
  grid-template-columns: 1fr minmax(0, 900px) 1fr;
  gap: 1rem;
  align-items: start;
  padding-top: 1.25rem;
}
.advisor-content {
  grid-column: 2;
  min-width: 0;
}
.advisor-tabs {
  grid-column: 3;
  justify-self: start;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  width: 168px;
  position: sticky;
  top: 1.25rem;
}
.advisor-tab {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 0.6rem 1rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink-muted);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-body);
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.advisor-tab:hover { color: var(--ink); background: var(--surface-2); }
.advisor-tab.active { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); font-weight: 600; }

/* Single-column — no side order panel like Customer Service has, since
   there's no Shopify order context for a strategy conversation. Width/
   centering moved to .advisor-layout's grid (2026-08-06) — this used to
   self-center via max-width:900px;margin:0 auto, which centered it
   within .advisor-content's OWN leftover space (i.e., off-true-center,
   since the side tabs ate into that space asymmetrically) rather than
   the page itself. Height also superseded by the :not(.embed-mode)
   override further down, now that the page-header/horizontal-tabs this
   300px offset was sized for are gone. */
.advisor-chat-container { min-height: 480px; }

.advisor-load-earlier-wrap { display: flex; justify-content: center; padding: 0.4rem 0; }
.advisor-load-earlier-btn {
  background: var(--surface-2); border: none; border-radius: 999px; padding: 0.3rem 0.9rem;
  font-size: 0.76rem; color: var(--ink-muted); cursor: pointer; font-family: var(--font-body);
  transition: background 0.15s, color 0.15s;
}
.advisor-load-earlier-btn:hover { background: var(--accent-soft); color: var(--accent-dark); }

.advisor-panel-card {
  background: var(--white); border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: 1.25rem;
}
.advisor-panel-card-header {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem;
}
.advisor-panel-card-header h2 { font-size: 1.05rem; font-weight: 600; color: var(--ink); }

.advisor-docs-hint { font-size: 0.82rem; color: var(--ink-muted); margin-bottom: 0.9rem; line-height: 1.5; }
.advisor-docs-dropzone {
  border: 2px dashed var(--surface-2); border-radius: var(--radius-lg); padding: 2rem;
  text-align: center; color: var(--ink-muted); font-size: 0.88rem; cursor: pointer;
  transition: border-color 0.15s, background 0.15s; margin-bottom: 1.25rem;
}
.advisor-docs-dropzone:hover, .advisor-docs-dropzone.dragover { border-color: var(--accent); background: var(--accent-soft); }

.advisor-docs-list { display: flex; flex-direction: column; gap: 0.5rem; }
.advisor-doc-row {
  display: flex; align-items: center; gap: 1rem; border: 1px solid var(--surface-2);
  border-radius: var(--radius); padding: 0.65rem 1rem;
}
.advisor-doc-row-title { font-size: 0.88rem; font-weight: 500; color: var(--ink); flex-shrink: 0; min-width: 200px; }
.advisor-doc-row-meta { font-size: 0.76rem; color: var(--ink-muted); flex: 1; }

.advisor-lookup-notice {
  align-self: center; font-size: 0.74rem; color: var(--ink-muted); background: var(--surface-2);
  border-radius: 999px; padding: 0.25rem 0.7rem; margin: 0.2rem auto;
}

/* Agent memory write notice (Phase B, 2026-09-17 s2).
   Deliberately fainter than .advisor-lookup-notice and self-removing after a
   few seconds (Dylan: "very subtle/greyed out ... disappears"). A memory
   write is a durable shared side effect, so it is never silent — but it is
   also not part of the conversation, so it does not persist in the
   transcript the way a lookup notice does. Removal is done in JS
   (agentMemoryNotice); this only handles the fade. */
.agent-memory-notice {
  align-self: center; font-size: 0.7rem; font-style: italic; color: var(--ink-muted);
  opacity: 0.6; margin: 0.15rem auto; padding: 0.1rem 0.6rem;
  transition: opacity 0.5s ease;
}
.agent-memory-notice--out { opacity: 0; }

/* Per-user chat sessions bar (Phase C, 2026-09-17 s2).
   Sits between the chat header and the messages. A <select> rather than a
   second tab strip on purpose: the widget already owns a horizontal tab strip
   for AGENTS, and two competing strips inside a ~380px panel is unreadable.
   min-width:0 on the select is what stops a long chat title forcing the whole
   bar wider than the panel (flex children default to min-width:auto). */
.agent-chat-bar {
  display: flex; align-items: center; gap: 0.35rem;
  padding: 0.35rem 0.75rem;
  border-bottom: 1px solid var(--surface-2);
  /* Pressure valve for very narrow widths — buttons drop to a second line
     rather than crushing the select (s4). */
  flex-wrap: wrap;
}
.agent-chat-bar:empty { display: none; }
.agent-chat-select {
  flex: 1;
  font-size: 0.78rem; padding: 0.2rem 0.4rem;
  border: 1px solid var(--surface-2); border-radius: 5px;
  background: var(--surface); color: var(--ink);
  /* Never collapse to a bare chevron — below this the row wraps instead (s4).
     Replaces the old min-width:0, which let flex shrink it to nothing. */
  min-width: 110px;
}
.agent-chat-bar .btn-sm { padding: 0.2rem 0.45rem; font-size: 0.75rem; }
/* The global 600px mobile rule makes every .btn-secondary width:100% — correct
   for page-level action bars, wrong INSIDE the chat widget iframe, whose ~380px
   viewport matches that media query and inflated New/★/✎/🗑 into full-width
   pills (found by Dylan, s4, screenshots). Two classes outrank the media
   query's single class, so this holds at every width. */
.agent-chat-bar .btn-secondary { width: auto; flex-shrink: 0; }

/* Manage chats window (Sue, 2026-10-07) — agent-chats.js agentChatManageOpen. */
.acm-card { max-width: 620px; }
.acm-toolbar { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; padding: 0.7rem 1.5rem; border-bottom: 1px solid var(--surface-2); }
.acm-toolbar .btn-secondary { width: auto; padding: 0.2rem 0.6rem; font-size: 0.78rem; }
.acm-count { font-size: 0.78rem; color: var(--ink-muted); margin-right: auto; }
.acm-delete:not([disabled]) { color: var(--danger); border-color: var(--danger); }
.acm-list { padding: 0.4rem 1rem 1rem; }
.acm-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--surface-2); }
.acm-row .btn-secondary { width: auto; flex-shrink: 0; padding: 0.15rem 0.45rem; font-size: 0.75rem; }
.acm-row--current { background: var(--surface); border-radius: 6px; }
.acm-row--theirs { opacity: 0.6; }
.acm-title { flex: 1; min-width: 0; text-align: left; background: none; border: none; padding: 0; cursor: pointer; color: var(--ink); font-size: 0.85rem; font-family: var(--font-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acm-title:hover { color: var(--accent); }
.acm-tag { font-size: 0.7rem; color: var(--ink-muted); background: var(--surface-2); border-radius: 999px; padding: 0 0.4rem; margin-left: 0.3rem; }
.acm-date { font-size: 0.75rem; color: var(--ink-muted); flex-shrink: 0; }
.acm-empty { font-size: 0.85rem; color: var(--ink-muted); padding: 1rem 0.5rem; }

/* Idle-chat nudge (2026-09-21 s1). Replaced a blocking confirm() that the
   docked widget re-fired on every page load. Sits directly under the chat bar,
   wraps at the widget's ~380px width, and never overlays the transcript. */
.agent-chat-idle-banner {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.4rem 0.75rem;
  font-size: 0.76rem; line-height: 1.35;
  background: var(--warn-soft);
  color: var(--warn-text);
  border-bottom: 1px solid var(--surface-2);
}
.agent-chat-idle-text { flex: 1; min-width: 150px; }
.agent-chat-idle-actions { display: flex; gap: 0.3rem; flex-shrink: 0; }
.agent-chat-idle-banner .btn-secondary { width: auto; flex-shrink: 0; padding: 0.2rem 0.45rem; font-size: 0.72rem; }

/* Kit rows inside the vendor SKU mapping modal (2026-09-21 s2). Bundles are
   now offerable targets there, and they must be visibly different from a
   component with a similar name — mapping a kit's price onto a component is
   the exact bug this release fixes. */
.pc-map-bundle-chip {
  display: inline-block; padding: 0.05rem 0.3rem; border-radius: 4px;
  background: var(--accent-soft); color: var(--accent-dark);
  font-size: 0.68rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em;
  vertical-align: middle;
}
.pc-map-bundle-warn {
  margin-bottom: 0.9rem; padding: 0.6rem 0.75rem;
  background: var(--warn-soft); color: var(--warn-text);
  border-left: 3px solid var(--warn); border-radius: var(--radius);
  font-size: 0.82rem; line-height: 1.45;
}
.pc-map-bundle-warn-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  flex-wrap: wrap; margin-top: 0.45rem;
}
.pc-map-bundle-warn .btn-secondary { width: auto; flex-shrink: 0; }

/* Kit membership chip + its modal (2026-09-21 s2). The chip has to read as a
   quiet aside on a dense row — it is information, not an alarm — while still
   being obviously clickable. */
.purch-kit-chip {
  display: inline-flex; align-items: center; gap: 0.2rem;
  padding: 0.05rem 0.35rem; margin-right: 0.3rem;
  border: 1px dashed var(--pd-card-border, var(--surface-2)); border-radius: 5px;
  background: none; color: var(--ink-muted);
  font-size: 0.68rem; font-family: inherit; cursor: pointer;
}
.purch-kit-chip:hover { color: var(--accent); border-color: var(--accent); }
.pc-kitparts-kit { padding: 0.5rem 0 1rem; border-bottom: 1px solid var(--surface-2); }
.pc-kitparts-kit:last-child { border-bottom: none; }
.pc-kitparts-head { font-size: 0.9rem; margin-bottom: 0.2rem; }
.pc-kitparts-cov { font-size: 0.8rem; color: var(--ink-muted); margin-bottom: 0.5rem; }
.pc-kitparts-table { width: 100%; font-size: 0.8rem; }
.pc-kitparts-table .pc-kitparts-this { background: var(--accent-soft); }
.pc-kitparts-here { font-size: 0.66rem; color: var(--accent-dark); }
.pc-kitparts-input, .pc-kitparts-kits { width: 72px; text-align: right; }
.pc-kitparts-actions {
  display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.55rem;
  font-size: 0.8rem;
}
.pc-kitparts-actions .btn-secondary, .pc-kitparts-actions .btn-primary { width: auto; flex-shrink: 0; }
.pc-kitparts-variant { font-size: 0.72rem; color: var(--ink-muted); }

/* Sumtracker create: blocking overlay while the writes run (2026-09-21 s2).
   No cancel by design — there is no safe point to abandon a part-written PO
   from the browser. */
.pc-st-busy-overlay {
  position: fixed; inset: 0; z-index: 4000;
  display: none; align-items: center; justify-content: center;
  background: rgba(26, 26, 46, 0.55);
}
.pc-st-busy-overlay.open { display: flex; }
.pc-st-busy-card {
  display: flex; align-items: flex-start; gap: 0.9rem;
  max-width: 420px; padding: 1.1rem 1.3rem;
  background: var(--white); color: var(--ink);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
}
.pc-st-busy-title { font-weight: 600; font-size: 0.92rem; }
.pc-st-busy-step { font-size: 0.84rem; color: var(--ink-soft); margin-top: 0.2rem; }
.pc-st-busy-warn { font-size: 0.76rem; color: var(--ink-muted); margin-top: 0.5rem; line-height: 1.4; }
.pc-st-busy-spin {
  width: 22px; height: 22px; flex-shrink: 0; margin-top: 0.1rem;
  border: 2px solid var(--surface-2); border-top-color: var(--accent);
  border-radius: 50%; animation: pcStSpin 0.8s linear infinite;
}
@keyframes pcStSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .pc-st-busy-spin { animation-duration: 2.4s; } }

/* Result: a corner card that clears itself on a clean create, a normal centred
   modal when there are issues to read. */
.modal-overlay.pc-st-result-corner {
  background: none; pointer-events: none;
  align-items: flex-end; justify-content: flex-end;
  padding: 1rem;
}
.modal-overlay.pc-st-result-corner .modal-card {
  pointer-events: auto;
  max-width: 380px; width: auto;
  box-shadow: var(--shadow-lg);
}

/* Currency label on every money figure (2026-09-21 s2). Deliberately tiny and
   muted: it must be readable when you look for it and invisible when you are
   scanning a column of numbers, because it appears on literally every figure
   on the page. Non-breaking space so it never wraps away from its number. */
.pc-cur {
  font-size: 0.68em;
  color: var(--ink-muted);
  font-weight: 400;
  margin-left: 0.22em;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* A skipped kit's working, folded (2026-09-21 s2). "The kit costs more" is not
   a checkable claim without the parts list behind it. */
.pc-kitskip { margin-top: 0.3rem; }
.pc-kitskip-head { cursor: pointer; list-style: revert; }
details.pc-kitskip > summary.pc-kitskip-head::marker { color: var(--ink-muted); }
.pc-kitskip-table { width: 100%; font-size: 0.78rem; margin-top: 0.35rem; }
.pc-kitskip-variant { font-size: 0.72rem; color: var(--ink-muted); }
.pc-kitskip-foot { font-size: 0.74rem; color: var(--ink-muted); margin-top: 0.3rem; line-height: 1.4; }

/* Money + its source badge must break as whole units, never mid-figure
   (2026-09-21 s2 — the currency label split "(USD)" onto its own line). */
.purch-money-atom, .purch-src-badge { white-space: nowrap; display: inline-block; }

/* Before -> after for the components a kit conversion consumes. */
.pc-kit-consumed {
  margin-top: 0.4rem; font-size: 0.8rem; line-height: 1.6; color: var(--ink-soft);
}
.pc-kit-consumed-item { white-space: nowrap; }
/* The parts table is wider than the notice it sits in — scroll it rather than
   let it clip (Dylan, 2026-09-21 s2). */
.pc-kitskip-scroll { overflow-x: auto; max-width: 100%; }
.pc-kitskip-table { min-width: 520px; }

/* Product thumbnail on any SKU line. Sized inline by pcSkuThumb; this only
   handles the look and the empty-state placeholder, which keeps the column
   width steady when a product has no image. */
.pc-skuthumb {
  display: inline-block; vertical-align: middle;
  object-fit: contain; border-radius: 5px; background: var(--surface-2);
}
.pc-skuthumb--none { background: var(--surface-2); opacity: 0.45; }

/* The unit-cost cell carries a figure, a currency label, a source badge and
   two icon buttons. With the currency label added they started wrapping
   mid-badge (Dylan's screenshot). Keep each token whole and let the CELL wrap
   between them instead of inside them. */
.purch-item-qty-cost {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.15rem 0.3rem;
  line-height: 1.5;
}
.purch-item-qty-cost > span { white-space: nowrap; }

/* File attachments (added 2026-08-06, session 7) */
.advisor-attach-preview {
  display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 1.25rem;
  border-top: 1px solid var(--surface-2); font-size: 0.85rem; color: var(--ink-soft);
}
.advisor-attach-preview button {
  background: var(--surface-2); border: none; border-radius: 50%; width: 22px; height: 22px;
  cursor: pointer; font-size: 0.75rem;
}
.advisor-chat-container.advisor-dragover {
  outline: 2px dashed var(--accent); outline-offset: -4px;
}
.advisor-chat-image { display: block; max-width: 240px; border-radius: 8px; margin-bottom: 0.5rem; }
.advisor-file-chip {
  display: inline-flex; align-items: center; gap: 0.4rem; background: var(--surface-2);
  border-radius: 999px; padding: 0.3rem 0.7rem; font-size: 0.8rem; margin-bottom: 0.5rem;
  color: var(--ink-soft); text-decoration: none;
}
.advisor-file-chip:hover { background: var(--accent-soft); color: var(--accent-dark); }

/* Page-navigation button (added 2026-08-06, session 7) — the visible
   artifact of the navigate_to_page tool; see runAdvisorClaudeTurn()/
   buildAdvisorBubbleEl() in advisor.js. */
.advisor-nav-btn {
  display: inline-flex; align-items: center; gap: 0.3rem; margin-top: 0.6rem;
  background: var(--accent); color: var(--on-accent); border: none; border-radius: var(--radius);
  padding: 0.45rem 0.9rem; font-size: 0.85rem; font-weight: 500; cursor: pointer;
  font-family: var(--font-body); transition: background 0.15s;
}
.advisor-nav-btn:hover { background: var(--accent-dark); }

/* Files tab — grouped attachment browser (added 2026-08-06, session 7) */
.advisor-files-total { font-size: 0.8rem; color: var(--ink-muted); }
.advisor-files-total--warn { color: var(--warn-text, var(--warn)); font-weight: 600; }
.advisor-files-group { margin-bottom: 1.2rem; }
.advisor-files-group:last-child { margin-bottom: 0; }
.advisor-files-group-header {
  display: flex; align-items: center; justify-content: space-between; font-weight: 600;
  font-size: 0.88rem; margin-bottom: 0.5rem; color: var(--ink);
}
.advisor-files-list { display: flex; flex-direction: column; gap: 0.4rem; }
.advisor-files-row {
  display: flex; align-items: center; gap: 0.6rem; border: 1px solid var(--surface-2);
  border-radius: var(--radius); padding: 0.5rem 0.75rem; font-size: 0.85rem;
}
.advisor-files-row a { color: var(--ink); text-decoration: none; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.advisor-files-row a:hover { color: var(--accent); text-decoration: underline; }
.advisor-files-meta { font-size: 0.76rem; color: var(--ink-muted); flex-shrink: 0; }
.advisor-files-delete-btn { background: none; border: none; cursor: pointer; opacity: 0.5; flex-shrink: 0; }
.advisor-files-delete-btn:hover { opacity: 1; }

/* Markdown rendering inside chat bubbles (added 2026-08-05, session 6, via
   marked.js) — scoped to .chat-bubble so it applies wherever a bubble
   renders markdown, not just on advisor.html. Tables/headers/lists were
   previously showing as literal '###'/'| col |' text since the old
   renderer only handled bold/inline-code. */
.chat-bubble table { border-collapse: collapse; margin: 0.6rem 0; font-size: 0.85em; width: 100%; table-layout: fixed; }
.chat-bubble th, .chat-bubble td { border: 1px solid var(--surface-2); padding: 0.35rem 0.6rem; text-align: left; word-break: break-word; overflow-wrap: break-word; }
.chat-bubble th { background: var(--surface); font-weight: 600; }
/* Wraps every rendered <table> (see buildAdvisorBubbleEl() in advisor.js)
   — table-layout:fixed + break-word above handles most cases, but a
   table with many columns may still not be able to shrink to fit without
   becoming unreadable; this lets it scroll internally as a fallback
   rather than blowing out the whole bubble/page's layout. */
.advisor-table-scroll { overflow-x: auto; margin: 0.6rem 0; }
.advisor-table-scroll table { margin: 0; }
.chat-bubble h1, .chat-bubble h2, .chat-bubble h3, .chat-bubble h4 {
  margin: 0.8rem 0 0.4rem; font-weight: 600; color: var(--ink); line-height: 1.3;
}
.chat-bubble h1:first-child, .chat-bubble h2:first-child, .chat-bubble h3:first-child, .chat-bubble h4:first-child { margin-top: 0; }
.chat-bubble h1 { font-size: 1.1em; }
.chat-bubble h2 { font-size: 1.05em; }
.chat-bubble h3 { font-size: 1em; }
.chat-bubble h4 { font-size: 0.92em; }
.chat-bubble ul, .chat-bubble ol { margin: 0.4rem 0; padding-left: 1.4rem; }
.chat-bubble li { margin: 0.2rem 0; }
.chat-bubble li > ul, .chat-bubble li > ol { margin: 0.2rem 0; }
.chat-bubble p { margin: 0.5rem 0; }
.chat-bubble p:first-child { margin-top: 0; }
.chat-bubble p:last-child { margin-bottom: 0; }
.chat-bubble code { background: var(--surface-2); padding: 0.1rem 0.3rem; border-radius: 4px; font-size: 0.85em; }
.chat-bubble pre { background: var(--surface-2); padding: 0.6rem 0.8rem; border-radius: 6px; overflow-x: auto; margin: 0.5rem 0; }
.chat-bubble pre code { background: none; padding: 0; }
/* Agent file download cards (js/agent-files.js, 2026-10-18) */
.agent-file-card { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 0.5rem 0; padding: 0.55rem 0.75rem; background: var(--surface-2); border-radius: 8px; }
.agent-file-icon { font-size: 1.2em; }
.agent-file-name { font-weight: 600; word-break: break-all; }
.agent-file-meta { color: var(--ink-muted); font-size: 0.85em; flex: 1; }
.agent-file-cutoff { margin: 0.4rem 0; padding: 0.45rem 0.7rem; background: var(--warn-soft); color: var(--warn-text); border-radius: 8px; font-size: 0.9em; }
.chat-bubble hr { border: none; border-top: 1px solid var(--surface-2); margin: 0.75rem 0; }
.chat-bubble a { color: var(--accent); }
.chat-bubble blockquote {
  margin: 0.5rem 0; padding: 0.3rem 0.8rem; border-left: 3px solid var(--surface-2);
  color: var(--ink-soft);
}

/* Embed mode (added 2026-08-05, session 5) — used when advisor.html is
   loaded inside the Growth chat widget's iframe (?embed=1). ALSO applies
   to the pop-out window (updated 2026-08-06 — that used to deliberately
   load the plain URL, full chrome intact; per Dylan's explicit ask, the
   pop-out now shows exactly the same compact chat-only view as the
   docked panel, just in its own window — see growthChatPopout() in
   growth-chat-widget.js). Class is added pre-paint (see the inline
   script in <head>) so there's no flash of the full layout first. */
html.embed-mode .topbar,
html.embed-mode .advisor-tabs { display: none !important; }
html.embed-mode .portal-main { padding: 0; max-width: none; }
html.embed-mode .advisor-layout { grid-template-columns: 1fr; padding-top: 0; gap: 0; }
/* Found live 2026-08-11 — .advisor-content is hardcoded grid-column: 2
   in the base rule (for the normal 3-column page layout). The line
   above collapses the grid to a single 1fr column but never reset this,
   so the browser auto-generated a phantom "column 2" sized to the
   chat's own content instead of stretching to fill the iframe — leaving
   the real, empty 1fr column visible on the left once the panel was
   dragged wider than that content-driven auto width. Same underlying
   bug as .zipp-office-pane--chat's own grid-column reset further down;
   that one just never got applied here too. */
html.embed-mode .advisor-content { grid-column: 1; }
html.embed-mode .advisor-chat-container { height: 100vh; max-width: none; margin: 0; border-radius: 0; }

/* Popout mode (added 2026-08-07) — the popped-out window's own tiny
   David/Zipp switcher bar (see the popout-switcher markup + JS in
   growth-chat-widget.js). .popout-switcher is empty/height:0 unless
   html.popout-mode is set, so the docked iframe (embed=1 without
   popout=1) renders nothing extra at all. The compound
   `.embed-mode.popout-mode` selector (both classes on the same <html>)
   is deliberately more specific than the plain `.embed-mode` height rule
   above, so this wins regardless of source order. */
.popout-switcher { display: none; }
html.popout-mode .popout-switcher {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  padding: 0.5rem 0.75rem;
  background: var(--white);
  border-bottom: 1px solid var(--surface-2);
  height: 40px;
  box-sizing: border-box;
}
.popout-switcher-btn {
  flex: 1;
  padding: 0.35rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--surface-2);
  background: var(--surface-2);
  color: var(--ink-muted);
  font-size: 0.78rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.popout-switcher-btn--active {
  background: var(--agent-accent, var(--accent));
  border-color: transparent;
  color: #ffffff;
  cursor: default;
}
/* Context-awareness banner (added 2026-08-11) — see the matching HTML
   comment in advisor.html/assistant.html. Same popout-mode-only gating
   as .popout-switcher above; stacks directly below it, so its 30px is
   added to the switcher's 40px in the height calc below. */
.popout-context-banner { display: none; }
html.popout-mode .popout-context-banner {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.75rem;
  background: var(--surface-alt, rgba(150,150,150,0.12));
  border-bottom: 1px solid var(--surface-2);
  font-size: 0.74rem;
  color: var(--ink-muted);
  height: 30px;
  box-sizing: border-box;
}
html.embed-mode.popout-mode .advisor-chat-container { height: calc(100vh - 40px - 30px); }

/* "Less contained" dedicated-page treatment (added 2026-08-06, per
   Dylan's ask) — David and Zipp's OWN full pages (advisor.html/
   assistant.html) drop the card shadow/rounding their chat panel
   otherwise shares with every other .chat-container on the portal, so
   the panel reads as part of the page rather than a boxed widget sitting
   on top of it. Deliberately scoped to :not(.embed-mode) — the floating
   Growth chat widget's iframe loads this exact same page/container, and
   that one keeps its normal border/shadow untouched; only the dedicated
   page changes. */
html:not(.embed-mode) .advisor-chat-container {
  box-shadow: none;
  border-radius: 0;
  /* Reverted 2026-08-06 back to a fixed calc() per Dylan's ask — the
     flex-fill chain (body/portal-main/advisor-layout all passing
     flex:1/min-height:0 down the tree) turned out to let the chat keep
     growing downward instead of being capped, pushing the input out of
     view again — the opposite problem, worse than the one it was meant
     to fix. Simple fixed offset instead: this 140px value is correct for
     THIS class alone (advisor.html/assistant.html standalone, which have
     no toggle-group above the chat) — Marketing Office needs a taller
     offset since it has one, see body.marketing-office-page's own
     override further down, which is more specific and wins there. */
  height: calc(100vh - 140px);
  /* The actual remaining source of the "grey bars" (2026-08-06 follow-up)
     — .chat-header/.chat-input-wrap were already made transparent above,
     but .chat-container ITSELF still had background:var(--white)
     (#1e1e2b in dark mode) showing through behind them, visibly
     different from the true page background (.portal-page's
     var(--surface), #15151f) that .chat-messages already matches
     exactly. Zeroing it here means header/messages/input all show the
     same true page background now, with nothing left to look like a box. */
  background: transparent;
}

/* Marketing Office needs a taller offset than the base 140px above — it
   has the David/Zipp toggle-group sitting above the chat that
   advisor.html/assistant.html standalone don't have. body.marketing-
   office-page + .advisor-chat-container (two classes) is more specific
   than html:not(.embed-mode) .advisor-chat-container (one class +
   :not()), so this correctly wins on this page without needing !important.
   204px = the base 140px plus the toggle-group's own height (~34px:
   button padding + font-size) plus its margin-bottom (1.5rem = 24px),
   rounded up a little for safety. Estimate, not pixel-measured — nudge
   if it's still off once it's live. */
body.marketing-office-page .advisor-chat-container {
  height: calc(100vh - 204px);
}

/* =============================================
   ZIPP'S OFFICE (added 2026-08-07)
   ============================================= */
/* Split row — board pane (his "space") + a draggable resizer + his
   normal chat, unchanged internally. Deliberately scoped to
   #assistantSection only; David's #advisorSection is untouched. */
.zipp-office-split {
  display: flex;
  align-items: stretch;
  gap: 0;
}
.zipp-office-pane {
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.zipp-office-pane--board {
  flex: 0 0 44%; /* overwritten inline by js/zipp-office.js's saved width, this is just the first-ever-load default */
  height: calc(100vh - 204px); /* same formula as body.marketing-office-page .advisor-chat-container above, kept as its own explicit rule since it's a different element */
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--radius);
  padding: 0 0.875rem 0.875rem;
}
.zipp-office-pane--chat {
  flex: 1;
}
.zipp-office-resizer {
  width: 6px;
  margin: 0 0.6rem;
  border-radius: 3px;
  background: var(--surface-2);
  cursor: col-resize;
  flex-shrink: 0;
  transition: background 0.15s;
}
.zipp-office-resizer:hover, .zipp-office-resizer.zipp-office-dragging { background: var(--accent-soft); }

/* Expand-either-pane states — the OTHER pane and the resizer both
   collapse to nothing, current pane takes the full row. */
.zipp-office-split.zipp-office-expanded-board .zipp-office-pane--chat,
.zipp-office-split.zipp-office-expanded-board .zipp-office-resizer,
.zipp-office-split.zipp-office-expanded-chat .zipp-office-pane--board,
.zipp-office-split.zipp-office-expanded-chat .zipp-office-resizer {
  display: none;
}
.zipp-office-split.zipp-office-expanded-board .zipp-office-pane--board,
.zipp-office-split.zipp-office-expanded-chat .zipp-office-pane--chat {
  flex: 1 1 100% !important;
}

.zipp-office-pane-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.875rem 0;
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 2;
}
.zipp-office-pane-header--chat {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  padding: 0;
  background: transparent;
  z-index: 5;
  width: auto;
}
.zipp-office-pane-title {
  font-weight: 700;
  font-size: 0.95rem;
}
.zipp-office-pane-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.zipp-office-expand-btn {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  border: 1px solid var(--surface-2);
  background: var(--surface);
  color: var(--ink-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.zipp-office-expand-btn:hover { background: var(--surface-2); color: var(--ink); }

/* Board — card grid. Deliberately a plain responsive grid rather than a
   fixed column count, per Dylan's "flexible depending on the job/work"
   ask — a short one-liner and a long draft both just take up whatever
   height their own content needs. */
.zipp-office-board-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.75rem;
}
.zipp-office-empty {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--ink-muted);
  font-size: 0.85rem;
  grid-column: 1 / -1;
}
.zipp-office-card {
  background: var(--white);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 0.75rem;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.zipp-office-card:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.zipp-office-card-title {
  font-weight: 600;
  font-size: 0.88rem;
}
.zipp-office-card-preview {
  font-size: 0.8rem;
  color: var(--ink-soft);
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.zipp-office-card-preview :is(h1, h2, h3) { font-size: 0.85rem; margin: 0.2rem 0; }
.zipp-office-card-preview p { margin: 0.2rem 0; }
.zipp-office-card-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: auto;
  font-size: 0.72rem;
  color: var(--ink-muted);
}

/* .advisor-layout override, scoped to Zipp's Office chat pane only — the
   base rule's `minmax(0, 900px)` middle column + symmetric gutters is
   built for the chat filling most/all of the page width (its normal
   case, standalone or David's side here). Once the chat lives in a
   resizable pane that might only be half the page, that 900px minimum
   just overflows. Dropping the gutters and letting content genuinely
   fill the pane reads fine here — there's no "page center" to preserve
   inside a pane this narrow anyway. Same kind of scoped override
   precedent as html.embed-mode .advisor-layout further up. */
.zipp-office-pane--chat .advisor-layout {
  grid-template-columns: minmax(0, 1fr) auto;
  padding-top: 2.5rem; /* clears the absolutely-positioned expand button above */
}
.zipp-office-pane--chat .advisor-content { grid-column: 1; }
.zipp-office-pane--chat .advisor-tabs { grid-column: 2; }

/* =============================================
   TECH ROOM SIDE TABS (added 2026-08-06)
   ============================================= */
/* Same visual pattern as .advisor-tabs/.advisor-tab (David/Zipp's side
   pill-nav), but under its own class names rather than reusing those —
   .advisor-tab literally has "advisor" in the name, which would read
   strangely applied to Tech Room's completely unrelated settings
   sections, even though the pill-button LOOK is deliberately identical
   for visual consistency across the portal's two side-tab pages. */
.tr-layout {
  display: grid;
  grid-template-columns: minmax(0, 1100px) 1fr;
  gap: 1rem;
  align-items: start;
}
.tr-content {
  min-width: 0;
}
.tr-tabs {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  width: 180px;
  position: sticky;
  top: 1.25rem;
  justify-self: start;
}
.tr-tab {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 0.6rem 1rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink-muted);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-body);
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.tr-tab:hover { color: var(--ink); background: var(--surface-2); }
.tr-tab.active { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); font-weight: 600; }

/* Per-agent accent color (added 2026-08-06) — --agent-accent defaults to
   the portal's normal brand accent, but advisor.js/assistant.js set it
   inline (element.style.setProperty) from whatever's saved in
   advisor_state/assistant_state.accent_color, per agent, independently
   of each other and of every other chat surface (Customer Service,
   Shopify Assistant) which never sets this variable and so just keeps
   using the plain var(--accent) fallback. filter:brightness() on hover
   instead of a separate --accent-dark-equivalent, since that only
   exists as a precomputed shade for the ONE default brand color — this
   works for any color the picker produces, not just the default. */
#advisorChatContainer, #assistantChatContainer {
  --agent-accent: var(--accent);
}
#advisorChatContainer .chat-message--user .chat-bubble,
#assistantChatContainer .chat-message--user .chat-bubble {
  background: var(--agent-accent);
}
#advisorChatContainer .chat-send-btn,
#assistantChatContainer .chat-send-btn {
  background: var(--agent-accent);
}
#advisorChatContainer .chat-send-btn:hover,
#assistantChatContainer .chat-send-btn:hover {
  background: var(--agent-accent);
  filter: brightness(0.88);
}

/* Extended 2026-08-06 (same session, follow-up ask) — the header row
   (avatar/name/status + scale/Save&Clear/Clear) and the input row
   (attach/textarea/send) each still had their own background + dividing
   border, which read as two more "grey boxes" even after the outer
   panel's shadow/rounding was removed above. Stripped both so every
   control in these rows sits directly on the page background — this
   does NOT touch each individual button/input's own styling (they keep
   their own pill background), only the row/strip behind them. */
html:not(.embed-mode) .advisor-chat-container .chat-header,
html:not(.embed-mode) .advisor-chat-container .chat-input-wrap {
  background: transparent;
  border: none;
}

/* Scoped override, not a change to the shared .chat-input class — David's
   input specifically gets more room to grow (matches ADVISOR_INPUT_MAX_HEIGHT
   in advisor.js) before it starts scrolling internally; other chat features
   sharing .chat-input are untouched. */
#advisorChatInput { max-height: 160px; }

/* Text-size scale (fixed 2026-08-06, session 8; #assistantChatContainer
   added 2026-08-07 — Zipp's own scale control (session 11) called the
   exact same applyAssistantScale() pattern, but this rule was never
   extended to his container, so his +/- buttons updated the stored value
   and the on-screen "100%" label with zero visible effect. Same bug
   class as the lesson doc's "hand-synced copies" entry.)
   .chat-bubble/.chat-input/.chat-product-label all set their own fixed
   rem font-sizes (shared classes, used by other chat features too),
   which would otherwise ignore either agent's own scale JS entirely.
   Scoped overrides here (not changes to the shared classes themselves)
   make them inherit instead, specifically within each agent's own
   container — other pages using .chat-bubble/.chat-input are unaffected. */
/* Widened 2026-09-17 s4: the per-container id list (advisor, assistant,
   then the three that would have followed) is replaced by one rule on the
   shared .advisor-chat-container class — verified that exactly the five
   agents' chat containers carry it, nothing else. Safe only because
   initAgentChatScaleControl() (agent-chats.js) ALWAYS sets an explicit
   font-size on the container at init, buttons present or not — without
   that, an uninitialised container would inherit the page's base size and
   silently render bigger than the 0.875rem these classes used to pin. */
.advisor-chat-container .chat-bubble,
.advisor-chat-container .chat-input,
.advisor-chat-container .chat-product-label {
  font-size: inherit;
}

/* Name group — avatar + name + status dot, kept together so .chat-header's
   justify-content:space-between still only sees two groups (this one,
   and the scale controls), same fix needed when the (now-removed) rename
   button lived here. */
.advisor-name-group {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  border-radius: 999px;
  padding: 0.2rem 0.5rem 0.2rem 0.2rem;
  transition: background 0.15s;
}
.advisor-name-group:hover { background: var(--surface-2); }
.advisor-header-avatar { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }

/* Status dot (added 2026-08-06, session 8) — green while idle/ready,
   yellow while a request is in flight (upload or waiting on Claude).
   Toggled by setAdvisorStatus() in advisor.js. No red state — per
   Dylan's call, errors already show inline as a message bubble, a
   persistent red dot alongside that would be redundant. */
.advisor-status-dot {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
  transition: background 0.15s;
}
.advisor-status-dot--green { background: var(--success, #2ecc71); }
.advisor-status-dot--yellow { background: var(--warn, #f5a623); }

/* Per-message avatars (added 2026-08-06, session 8) — .chat-message's
   existing flex + row-reverse (for user messages) already puts this on
   the correct side with no extra positioning needed. */
.advisor-msg-avatar {
  width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0; object-fit: cover; margin-top: 2px;
}
.advisor-msg-avatar--fallback {
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-2); color: var(--ink-soft); font-size: 0.78rem; font-weight: 600;
}

/* Header actions group (added 2026-08-06, session 8) — scale controls +
   Save&Clear + Clear, kept together so .chat-header's space-between
   still only ever sees two top-level groups. */
.advisor-header-actions { display: flex; align-items: center; gap: 0.5rem; }
/* Chat header actions (2026-09-18 s1): Clear/New keep a FIXED size — px, not
   rem/em — so the chat text-size control and narrow dock widths never stretch,
   shrink or wrap them. flex:none wins over the header's flex squeezing. */
.chat-action-btn {
  flex: none;
  white-space: nowrap;
  font-size: 12px;
  line-height: 1;
  padding: 6px 10px;
  height: 28px;
  display: inline-flex;
  align-items: center;
}
.advisor-clear-btn { color: var(--danger-text-alt); border-color: var(--danger-bg-soft); }
.advisor-clear-btn:hover { background: var(--danger-bg-faint); border-color: var(--danger-text-alt); }

/* =============================================
   TASKS / PROJECTS TRACKER (added 2026-08-06)
   ============================================= */
.tasks-board {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  align-items: start;
}
@media (max-width: 1100px) {
  .tasks-board { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .tasks-board { grid-template-columns: 1fr; }
}

.tasks-column {
  background: var(--surface);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  min-height: 120px;
  min-width: 0; /* fix (added 2026-08-10): without this, a grid item's automatic minimum width is based on its content's min-content size — a long nowrap skinny-card title forced this column wider than its 1fr share, squeezing the other three columns. min-width:0 tells the grid track sizing to ignore that and actually honor equal 1fr division; the title's own overflow/ellipsis (see .tasks-card-title--skinny) then clips correctly within the resulting fixed width. */
  position: relative; /* anchors .tasks-col-resize-handle below */
  display: flex;
  flex-direction: column;
}
/* Column resize handle (added 2026-08-10) — same shape/behavior as the
   AR page's .ar-col-resize-handle: a thin strip on the column's right
   edge, dragged to set that column's width directly in pixels,
   independent of every other column (see js/tasks.js's
   startTasksColumnResize() for why "own column only, plain pixels" won
   out over a percentage/neighbor-shrinking approach). */
.tasks-col-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  user-select: none;
  z-index: 2;
}
.tasks-col-resize-handle:hover, .tasks-col-resize-handle:active {
  background: var(--accent-soft);
}
.tasks-column-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 0.9rem;
  border-bottom: 1px solid var(--surface-2);
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--ink);
}
.tasks-column-count {
  background: var(--surface-2);
  color: var(--ink-soft);
  border-radius: 999px;
  padding: 0.1rem 0.55rem;
  font-size: 0.75rem;
  font-weight: 600;
}
.tasks-column-body {
  padding: 0.65rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  flex: 1;
}
.tasks-empty-col {
  color: var(--ink-muted);
  font-size: 0.82rem;
  text-align: center;
  padding: 1.25rem 0.5rem;
}

.tasks-card {
  background: var(--white);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 0.75rem 0.85rem;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: box-shadow 0.15s, border-color 0.15s;
}
.tasks-card:hover {
  box-shadow: var(--shadow-lg);
  border-color: var(--accent);
}
.tasks-parent-tag {
  font-size: 0.72rem;
  color: var(--ink-muted);
  margin-bottom: 0.3rem;
}
.tasks-card-title {
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink);
  margin-bottom: 0.3rem;
}
.tasks-card-desc {
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin-bottom: 0.5rem;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tasks-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.72rem;
}
.tasks-card-by {
  color: var(--ink-muted);
  margin-left: auto;
}
.tasks-sub-badge {
  background: var(--surface-2);
  color: var(--ink-soft);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  font-weight: 500;
}
/* Deadline + recurrence (added 2026-08-10) — a plain pill like
   .tasks-sub-badge, turning red only when genuinely overdue (past due
   AND not already Done — a recurring task's due_at only ever holds a
   future occurrence, so this never fires for one that's on schedule). */
.tasks-due-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  background: var(--surface-2);
  color: var(--ink-soft);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  font-weight: 500;
}
.tasks-due-badge--overdue {
  background: var(--danger-bg-faint);
  color: var(--danger);
  font-weight: 600;
}
.tasks-recur-icon {
  font-size: 0.85em;
}
.tasks-assignee-pill {
  border-radius: 999px;
  padding: 0.1rem 0.55rem;
  font-weight: 600;
  color: var(--on-accent);
}
.tasks-assignee-pill--zipp { background: #993556; }
.tasks-assignee-pill--david { background: #D01D5A; }
.tasks-assignee-pill--dylan { background: #22c55e; }
.tasks-assignee-pill--sue { background: #3b82f6; }

/* Project pill (added 2026-08-10) — sits above the card title, same spot
   as .tasks-parent-tag but visually distinct (a filled soft-color pill
   with a solid dot, vs. the parent tag's plain muted text) since the two
   represent unrelated concepts: this is visibility, that's nesting. */
.tasks-project-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  border-radius: 999px;
  padding: 0.1rem 0.55rem;
  font-weight: 600;
  font-size: 0.7rem;
  margin-bottom: 0.35rem;
}
.tasks-project-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* Priority (added 2026-08-10) — a small colored dot, same visual weight
   as .tasks-project-dot but a fixed 4-color palette (not user-chosen
   like project colors) since Dylan specified the exact mapping:
   Red=Urgent, Orange/Yellow=Medium, Blue=No rush, gray=None. */
.tasks-priority-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-right: 0.4rem; /* fix (added 2026-08-10) — was riding flush against the task title text with zero gap; the Filters/manager checklists already had a little breathing room from a literal space in their HTML, so this only visibly changes the card title case */
}
.tasks-priority-dot--urgent { background: var(--danger); }
.tasks-priority-dot--medium { background: var(--warn); }
.tasks-priority-dot--low    { background: #3b82f6; }
.tasks-priority-dot--none   { background: var(--surface-2); border: 1px solid var(--ink-muted); }

/* Task card's own priority indicator — a short colored bar down the
   left edge, rather than yet another pill competing with the assignee/
   project pills already crowding the card header. Omitted entirely for
   'none' (see renderTasksBoard()) rather than showing a gray bar for
   the common no-priority case. */
.tasks-card--priority-urgent { border-left: 3px solid var(--danger); }
.tasks-card--priority-medium { border-left: 3px solid var(--warn); }
.tasks-card--priority-low    { border-left: 3px solid #3b82f6; }

/* Assignee avatar (added 2026-08-10) — a small circular image before
   the name text inside .tasks-assignee-pill. Falls back to nothing
   (just the pill's existing background color) when no avatar_url is on
   file, rather than a placeholder initial — the pill's own agent/
   generic background already distinguishes who it is even without a
   photo. */
.tasks-assignee-avatar {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  object-fit: cover;
  vertical-align: middle;
  margin-right: 0.3rem;
  flex-shrink: 0;
}

/* Grouped-by-project layout (added 2026-08-10) — one row per project
   (+ "No Project"), each row a horizontally-scrollable mini version of
   the flat board's 4 columns. */
.tasks-board-grouped {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}
.tasks-project-row {
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 1rem;
}
.tasks-project-row-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: 0.75rem;
}
.tasks-project-row-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}
/* Reorder arrows (added 2026-08-10) — pushed to the row header's right
   edge via margin-left:auto; reuses .delay-nav-btn's existing small
   icon-button styling rather than introducing a new button class. */
.tasks-project-row-reorder {
  margin-left: auto;
  display: flex;
  gap: 0.25rem;
}

/* Project tabs (added 2026-08-10) — a per-user pinned shortcut row.
   Deliberately its own pill style, not .toggle-btn — these can carry a
   project's own color as a left accent, which .toggle-btn's shared
   pill-group background doesn't accommodate. */
/* Project tabs (added 2026-08-10) — a per-user pinned shortcut row.
   Deliberately its own pill style, not .toggle-btn — these can carry a
   project's own color as a left accent, which .toggle-btn's shared
   pill-group background doesn't accommodate. */
.tasks-project-tabs-row {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 1.25rem;
}
/* Fix: position:relative belongs on the shared wrapper (see the HTML
   comment on .tasks-project-tabs-container), not on the row itself —
   the row's own innerHTML gets fully replaced on every render, which
   would've been fine either way, but the popover is a SIBLING of the
   row, not a descendant, so it needs the wrapper as its positioned
   ancestor to anchor against. */
.tasks-project-tabs-container {
  position: relative;
}
/* The manage-tabs popover reuses .settings-menu-wrap/.settings-menu-
   dropdown (same toggle-on-click / close-on-outside-click behavior as
   Filters/the notification bell), just positioned to hang below the
   tab row's "+" button rather than below its own trigger — there's no
   separate visible trigger element for it; the "+" tab IS the trigger,
   rendered dynamically inside .tasks-project-tabs-row itself. */
#tasksTabsManagerWrap {
  position: absolute;
  top: 100%;
  right: 0; /* the "+" button is always the last/rightmost tab, so anchoring right lines up close to it without needing per-pixel JS positioning */
}
#tasksTabsManagerPanel {
  top: 8px;
  min-width: 220px;
}
.tasks-project-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  border: 1.5px solid var(--surface-2);
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}
.tasks-project-tab:hover { border-color: var(--ink-muted); color: var(--ink); }
.tasks-project-tab.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.tasks-project-tab-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.tasks-project-tab--manage {
  width: 28px;
  height: 28px;
  padding: 0;
  justify-content: center;
  border-radius: 50%;
  font-size: 0.9rem;
}

.tasks-project-row-columns {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
}
@media (max-width: 900px) {
  .tasks-project-row-columns { grid-template-columns: 1fr; }
}

/* Card density (added 2026-08-10) — "Skinny" cards get their own much
   shorter template in tasksCardHtml() (js/tasks.js), so most of this is
   just tightening the column body's own spacing to match; the cards
   themselves carry their own compact padding via .tasks-card--skinny. */
.tasks-board--skinny .tasks-column-body {
  gap: 0.35rem;
}
.tasks-card--skinny {
  padding: 0.3rem 0.5rem;
}
.tasks-card-skinny-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.tasks-card-title--skinny {
  font-weight: 600;
  font-size: 0.76rem;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}
/* Skinny assignee pill needs to not grow/wrap — it sits opposite the
   title in the same row, and the title above already handles its own
   overflow via ellipsis. Shrunk smaller than the normal-card pill
   (added 2026-08-10, per feedback that skinny felt too large) — its
   own avatar image gets a matching smaller size too. */
.tasks-card--skinny .tasks-assignee-pill {
  flex-shrink: 0;
  white-space: nowrap;
  font-size: 0.68rem;
  padding: 0.05rem 0.4rem;
}
.tasks-card--skinny .tasks-assignee-avatar {
  width: 13px;
  height: 13px;
}
/* Skinny cards keep the project pill, just tightened to sit right above
   the title row instead of .tasks-card's normal spacing, and shrunk to
   match the smaller overall footprint. */
.tasks-card--skinny .tasks-project-pill {
  margin-bottom: 0.25rem;
  font-size: 0.68rem;
  padding: 0.05rem 0.4rem;
}

/* Sub-task card styling (added 2026-08-07, per Dylan's ask) — a task
   with a parent_id now renders visibly smaller and indented, with a left
   accent border standing in for the "nested under" connection, instead
   of being the exact same size/weight as a top-level task or project.
   Paired with tasksGroupForColumn() in js/tasks.js, which sorts a child
   to sit directly under its own parent WITHIN the same column — this
   class is what makes that grouping actually visible, not just ordered.
   If a child's own status differs from its parent's, it still lands in
   its own column (independent status is real, not just cosmetic) — it
   just can't visually nest under a parent that isn't there, so it keeps
   this same smaller styling on its own, with the existing "Part of: X"
   tag carrying the context instead. */
.tasks-card--sub {
  margin-left: 1.1rem;
  padding: 0.5rem 0.65rem;
  border-left: 3px solid var(--accent-soft);
  background: var(--surface);
  box-shadow: none;
}
.tasks-card--sub:hover {
  box-shadow: none;
  border-color: var(--surface-2);
  border-left-color: var(--accent);
}
.tasks-card--sub .tasks-card-title {
  font-size: 0.82rem;
  font-weight: 500;
}
.tasks-card--sub .tasks-card-desc {
  font-size: 0.76rem;
  -webkit-line-clamp: 2;
}

/* Run now button (added 2026-08-07, Zipp Phase 2) — only ever shown on a
   todo/zipp card (see js/tasks.js's renderTasksBoard()), so it's a small
   full-width row rather than competing for space in .tasks-card-meta. */
.tasks-run-now-btn {
  display: block;
  width: 100%;
  margin-top: 0.5rem;
  padding: 0.35rem 0;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: transparent;
  color: var(--accent);
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
}
.tasks-run-now-btn:hover {
  background: var(--accent);
  color: var(--on-accent);
}

/* Skinny variant (added 2026-08-10, per Dylan's follow-up ask to keep
   Run Now reachable there) — a small icon-only circle instead of the
   full-width text button above, sitting inline in the skinny row
   between the title and the assignee pill rather than on its own line. */
.tasks-run-now-btn--skinny {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-top: 0;
  padding: 0;
  border-radius: 50%;
  font-size: 0.65rem;
  flex-shrink: 0;
}

/* Mark Completed (added 2026-08-12) — same box shape as .tasks-run-now-btn
   above, just success-colored, since the two can sit side by side on
   the same card (Run Now only shows for a todo/zipp card; Complete
   shows on every card). .tasks-card-actions wraps both so they share a
   row evenly instead of stacking as separate full-width blocks. */
.tasks-card-actions {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.5rem;
}
.tasks-card-actions .tasks-run-now-btn,
.tasks-card-actions .tasks-complete-btn {
  margin-top: 0; /* the wrapper above owns the spacing now */
  flex: 1;
}
.tasks-complete-btn {
  display: block;
  width: 100%;
  padding: 0.35rem 0;
  border: 1px solid var(--success);
  border-radius: 6px;
  background: transparent;
  color: var(--success-text);
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
}
.tasks-complete-btn:hover {
  background: var(--success);
  color: var(--on-accent);
}
.tasks-complete-btn--skinny {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-top: 0;
  padding: 0;
  border-radius: 50%;
  font-size: 0.65rem;
  flex-shrink: 0;
}

/* Completed list rows (added 2026-08-12) — reuses .dash-table wholesale
   (same pattern as AR/Automation Log/Delay Orders); rows just need a
   pointer cursor since clicking one opens the task modal, same as a
   board card. Hover highlight already comes free from .dash-table's
   own tr:hover rule. */
.tasks-completed-row {
  cursor: pointer;
}

/* Vendor Directory table rows (added 2026-08-12, session 6) — reuses
   .dash-table wholesale, same pointer-cursor spirit as
   .tasks-completed-row above/.inv-report-table's own tbody tr rule —
   clicking a row opens the vendor edit modal. */
.im-vendor-row {
  cursor: pointer;
}

/* Vendor Orders tab (added 2026-08-12, session 6) — one card per vendor,
   same bordered-box shape as Tasks' .tasks-project-row (a proven
   "grouped section" pattern already in this codebase) rather than a
   flat table, since each vendor carries several pieces of context
   (threshold status, lead time, contact, a SKU list) that don't fit a
   single row well. */
.im-vendor-card {
  background: var(--white);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}
.im-vendor-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.im-vendor-card-name {
  font-weight: 600;
  font-size: 1rem;
}
.im-vendor-card-info {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.25rem;
  margin-top: 0.6rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
}
.im-vendor-card-info a { color: var(--accent); }
.im-vendor-card-notes {
  margin-top: 0.6rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
  background: var(--surface);
  border-radius: 6px;
  padding: 0.5rem 0.75rem;
}
.im-vendor-card-totals {
  margin-top: 0.6rem;
  font-size: 0.85rem;
  font-weight: 600;
}
.im-vendor-card-skus {
  margin-top: 0.75rem;
}
.im-vendor-card-sku-row {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.82rem;
  padding: 0.35rem 0;
  border-top: 1px solid var(--surface);
}
.im-vendor-card-sku-row:first-child { border-top: none; }

/* Agent Work Log — result preview clamp (added 2026-08-07, per Dylan's
   live-test feedback) — same -webkit-line-clamp pattern as
   .tasks-card-desc above, so a long result wraps and clips instead of
   inflating the row indefinitely. Full text is always available via the
   Details modal (js/automation-log.js's openAwlDetailModal()). */
.awl-result-preview {
  font-size: 0.85rem;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Text-size scale for Automation Log (added 2026-08-06) — same fix as
   #advisorChatContainer above: .dash-table (and its th cells) set their
   own fixed font-size (shared classes, used by several other pages'
   tables too), which would otherwise ignore applyAlScale()'s font-size
   set on #alTableWrap entirely. Scoped here to #alTableWrap only — every
   other page still using .dash-table at its normal fixed size is
   unaffected. th uses em rather than inherit — it was deliberately
   smaller than the body text before (0.7rem vs 0.825rem, for the
   uppercase label look), and inherit would make it identical to body
   text instead of preserving that ratio as it scales. td cells have no
   font-size of their own, so they already inherit correctly without
   needing a rule here. */
#alTableWrap .dash-table {
  font-size: inherit;
}
#alTableWrap .dash-table th {
  font-size: 0.848em; /* 0.7 / 0.825 — same ratio to body text the original fixed rem values had */
}

/* Text-size scale for Private Orders (added 2026-08-06) — same fix as
   #alTableWrap above, same reasoning: .dash-table (and its th cells) set
   their own fixed font-size, which would otherwise ignore
   applyPoScale()'s font-size set on #poTableWrap entirely. Scoped to
   #poTableWrap only. */
#poTableWrap .dash-table {
  font-size: inherit;
}
#poTableWrap .dash-table th {
  font-size: 0.848em; /* 0.7 / 0.825 — same ratio to body text the original fixed rem values had */
}

/* Text-size scale for Agent Work Log (added 2026-08-07) — same fix as
   #alTableWrap/#poTableWrap above, same root cause: .dash-table (and its
   th cells) set their own fixed font-size, which otherwise ignores
   applyAwlScale()'s font-size set on #awlTableWrap entirely. This was the
   actual bug behind Dylan's "scale +/- doesn't work" report — the JS was
   always correct, this override rule was just never added for the new
   wrapper id. Scoped to #awlTableWrap only. */
#awlTableWrap .dash-table {
  font-size: inherit;
}
#awlTableWrap .dash-table th {
  font-size: 0.848em; /* 0.7 / 0.825 — same ratio to body text the original fixed rem values had */
}

/* =============================================
   INVENTORY MONITOR (added 2026-08-12)
   ============================================= */

/* Column-source legend + per-column accent borders, so it's visible at a
   glance whether a number came from Shopify, Sumtracker, or is
   computed/manually uploaded within the portal. Colors reuse existing
   theme vars (--info-badge-text/--success/--warn) rather than introducing
   new ones. */
.im-source-legend {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  font-size: 0.8rem;
  color: var(--ink-muted);
  margin: 0.5rem 0 0.75rem;
}
.im-source-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-right: 0.4rem;
  vertical-align: middle;
}
.im-source-dot--shopify     { background: #95BF47; } /* Shopify's own brand green */
.im-source-dot--sumtracker  { background: #1b55d2; } /* Sumtracker's own app blue */
.im-source-dot--custom      { background: var(--warn); }

#monitorTable thead th {
  position: sticky; /* was position:relative — still anchors the .ar-col-resize-handle strip below exactly the same way, since a stickily-positioned element is just as much a "positioned element" as a relatively-positioned one. Also makes the header stick as you scroll — see #monitorTableWrap above for why this couldn't just live as its own separate rule. */
  top: 58px; /* matches the topbar's own sticky height, same convention as .delay-sticky-toolbar */
  z-index: 2;
  border-top: 3px solid transparent;
  /* background comes from .inv-report-table thead th's own var(--surface)
     rule above — a sticky header MUST be opaque or scrolled-past rows
     show through it, and that rule already provides it, so nothing
     extra needed here. */
}
#monitorTable thead th.im-src-shopify    { border-top-color: #95BF47; }
#monitorTable thead th.im-src-sumtracker { border-top-color: #1b55d2; }
#monitorTable thead th.im-src-custom     { border-top-color: var(--warn); }

/* Vendor Directory table's own column-resize anchor (added 2026-08-12,
   session 8) — plain position:relative, no sticky needed here (not
   requested for this table) — just enough for .ar-col-resize-handle's
   position:absolute to anchor against, same reasoning as every other
   resizable table on this site. */
#vendorDirectoryTable thead th {
  position: relative;
}

.im-pagination-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 0.75rem;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.im-pagination-row select {
  margin-left: 0.4rem;
}

/* Zoom-control/table spacing fix (added 2026-08-12, screenshot-reported).
   .table-zoom-controls itself has no built-in margin anywhere in the
   portal — other pages happen to have enough natural spacing around it
   already; this page didn't. Scoped to #imMonitorTab specifically rather
   than touching the shared .table-zoom-controls rule, so already-shipped
   pages (Inventory Report, AR, etc.) can't shift as a side effect. */
#imMonitorTab .table-zoom-controls {
  margin-bottom: 0.6rem;
}

.im-progress-bar-wrap {
  width: 100%;
  height: 8px;
  background: var(--surface-2);
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 1rem;
}
.im-progress-bar-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #1b55d2 0%, #5b8def 50%, #1b55d2 100%);
  background-size: 200% 100%;
  border-radius: 4px;
  transition: width 0.3s ease;
  animation: im-progress-shimmer 1.4s linear infinite;
}
@keyframes im-progress-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Subtle "reference" link for Inventory Monitor cells whose value is pulled
   straight from Shopify (added 2026-08-13) — looks like normal data, but is
   clickable to open that variant in Shopify Admin. Deliberately quieter than
   .inv-link (used for the SKU anchor) so a row isn't mostly accent-coloured. */
.im-shopify-cell-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
.im-shopify-cell-link:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* Beside-value "open in Shopify" icon (added 2026-08-13) — bigger padded hit
   target than linking a single digit directly; muted until hover. */
.im-shopify-ref-icon {
  display: inline-block;
  margin-left: 0.15rem;
  padding: 0 0.3rem;
  color: var(--ink-muted);
  text-decoration: none;
  font-size: 0.85rem;
  border-radius: 4px;
}
.im-shopify-ref-icon:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

/* =============================================
   Purchasing page (added 2026-08-24)
   Builds on the existing .im-vendor-card + .po-status-badge + .modal-*
   patterns; only genuinely new bits (accordion header, item rows with
   photos, ABC tags, delay chips, remove modal fields) get their own rules.
   All colours via tokens so dark mode is automatic.
   ============================================= */
.purch-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 1rem;
}
.purch-toolbar-filters { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.purch-summary { font-size: 0.85rem; color: var(--ink-soft); display: flex; gap: 0.4rem; flex-wrap: wrap; }
.purch-summary strong { color: var(--ink); }

.purch-vendor-card { padding: 0; overflow: hidden; }
.purch-vendor-card.purch-ordered { opacity: 0.72; }

.purch-accordion-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 1rem 1.25rem;
  cursor: pointer;
  user-select: none;
}
.purch-accordion-header:hover { background: var(--surface); }
.purch-accordion-header-main { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.purch-accordion-header .accordion-chevron { display: inline-block; }
.purch-accordion-header-totals { font-size: 0.8rem; color: var(--ink-soft); }

.purch-accordion-body { padding: 0 1.25rem 1.1rem; border-top: 1px solid var(--surface-2); }

.purch-channel-badge {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
}
/* Quieted 2026-09-11 s3 (Dylan): the ordering-method label is reference info,
   not a call to action — it was the loudest thing on a collapsed header. Same
   muted treatment as the online variant below. */
.purch-channel-po     { background: var(--surface-2); color: var(--ink-soft); }
.purch-channel-online { background: var(--surface-2); color: var(--ink-soft); }

.purch-backup-toggle {
  margin: 0.85rem 0 0.4rem;
  padding: 0.6rem 0.75rem;
  background: var(--surface);
  border-radius: 8px;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.purch-item-rows { margin-top: 0.85rem; }
.purch-item-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0;
  border-top: 1px solid var(--surface);
}
.purch-item-row:first-child { border-top: none; }
.purch-item-check { flex-shrink: 0; width: 1.05rem; height: 1.05rem; cursor: pointer; }

.purch-item-photo {
  width: 40px; height: 40px;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--surface-2);
  background: var(--white);
}
.purch-item-photo--empty {
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-muted); font-size: 0.9rem;
}
.purch-item-main { flex: 1; min-width: 0; }
.purch-item-title { font-size: 0.85rem; color: var(--ink); }
.purch-item-sub { margin-top: 0.15rem; display: flex; gap: 0.4rem; flex-wrap: wrap; }
.purch-item-qty { text-align: right; flex-shrink: 0; }
.purch-item-qty-num { font-weight: 600; font-size: 0.95rem; color: var(--ink); }
.purch-item-qty-cost { font-size: 0.72rem; color: var(--ink-muted); }
/* Editable order qty (2026-08-27) */
.purch-item-qty-input {
  width: 4.5rem; text-align: right; font-weight: 600; font-size: 0.95rem;
  color: var(--ink); background: var(--surface); border: 1px solid var(--surface-2);
  border-radius: 6px; padding: 0.15rem 0.35rem;
}
.purch-item-qty-input:focus { outline: none; border-color: var(--accent); }
.purch-item-qty-input.overridden { border-color: var(--accent); background: var(--accent-soft, rgba(37,99,235,0.06)); }
.purch-item-qty-advisory { font-size: 0.7rem; color: var(--danger-text); font-weight: 600; margin-top: 0.15rem; }
.purch-qty-suggest {
  font: inherit; font-size: 0.68rem; color: var(--accent-dark); background: transparent;
  border: 1px solid currentColor; border-radius: 4px; padding: 0 0.3rem; cursor: pointer;
}
.purch-qty-suggest:hover { background: var(--accent-soft, rgba(37,99,235,0.08)); }
.purch-item-qty-drift { font-size: 0.68rem; color: var(--ink-muted); margin-top: 0.1rem; }
.purch-qty-reset {
  font: inherit; font-size: 0.72rem; color: var(--ink-muted); background: transparent;
  border: none; cursor: pointer; padding: 0 0.15rem;
}
.purch-qty-reset:hover { color: var(--accent-dark); }
/* Line items with photos modal (P12, 2026-08-27) */
.pc-lineitems-list { display: flex; flex-direction: column; gap: 0.5rem; }
.pc-lineitem-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.4rem; border: 1px solid var(--surface-2); border-radius: 8px; }
.pc-lineitem-thumb { width: 48px; height: 48px; object-fit: cover; border-radius: 6px; background: var(--surface-2); flex-shrink: 0; }
.pc-lineitem-thumb--empty { display: flex; align-items: center; justify-content: center; color: var(--ink-muted); font-size: 0.85rem; }
.pc-lineitem-main { flex: 1; min-width: 0; }
.pc-lineitem-title { font-weight: 600; font-size: 0.9rem; }
.pc-lineitem-sku { font-size: 0.75rem; color: var(--ink-muted); }
.pc-lineitem-qty { font-weight: 600; font-size: 0.95rem; flex-shrink: 0; }

.purch-remove-btn {
  flex-shrink: 0;
  border: none; background: none; cursor: pointer;
  color: var(--ink-muted); font-size: 0.95rem;
  padding: 0.25rem 0.4rem; border-radius: 6px;
  transition: background 0.15s ease, color 0.15s ease;
}
.purch-remove-btn:hover { background: var(--danger-soft); color: var(--danger-text); }
/* Open-orders button (2026-08-25) */
.purch-orders-btn {
  flex-shrink: 0;
  border: 1px solid var(--surface-2); background: var(--white); cursor: pointer;
  color: var(--ink-soft); font-size: 0.72rem; font-weight: 600;
  padding: 0.2rem 0.4rem; border-radius: 6px; white-space: nowrap;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.purch-orders-btn:hover { border-color: var(--cyan-border-hover); color: var(--cyan-text); }
.purch-orders-btn.has-backorder { border-color: var(--danger-soft); color: var(--danger-text); }

.purch-abc {
  font-size: 0.68rem; font-weight: 700;
  padding: 0.05rem 0.35rem; border-radius: 4px;
  vertical-align: middle;
}
/* Per-row status stub (tier icon + ABC context badge) — layout cleanup 2026-09-10 s2 */
.purch-item-status {
  flex-shrink: 0;
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 0.2rem;
}
.purch-status-icon { font-size: 0.95rem; line-height: 1; cursor: help; }
.purch-status-icon--none { color: var(--ink-muted); cursor: default; }
.purch-status-badges { display: flex; flex-direction: row; align-items: center; gap: 0.25rem; }
.purch-item-instr {
  margin-top: 0.15rem; font-size: 0.72rem; color: var(--ink-muted);
  line-height: 1.3; word-break: break-word;
}
/* Inline min/max + Vendor SKU editors (Chunk 2, 2026-08-25) */
.purch-item-vsku { margin-top: 0.2rem; display: flex; align-items: center; gap: 0.35rem; }
.purch-vsku-label { font-size: 0.7rem; color: var(--ink-muted); flex-shrink: 0; }
.purch-vsku-input {
  font-size: 0.74rem; padding: 0.1rem 0.35rem;
  border: 1px solid var(--surface-2); border-radius: 4px;
  background: var(--white); color: var(--ink); width: 11rem; max-width: 40vw;
}
.purch-vsku-input::placeholder { color: var(--danger-text); opacity: 0.7; }
.purch-vsku-note { font-size: 0.66rem; color: var(--ink-muted); cursor: help; }
.purch-vsku-copy {
  border: none;
  background: none;
  color: var(--ink-muted);
  cursor: pointer;
  font-size: 0.78rem;
  padding: 0.05rem 0.2rem;
  border-radius: 4px;
  flex-shrink: 0;
  line-height: 1;
}
.purch-vsku-copy:hover { background: var(--surface-2); color: var(--ink); }

/* Customer-committed (outstanding orders) overlay — 2026-08-26 */
.purch-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
  cursor: pointer;
  user-select: none;
}
.purch-toggle input { cursor: pointer; }
.purch-committed-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 0.72rem;
  font-weight: 600;
  background: var(--danger-soft, #fde8e8);
  color: var(--danger-text, #b42318);
  cursor: help;
}
.purch-committed-chip {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 10px;
  font-size: 0.72rem;
  background: var(--danger-soft, #fde8e8);
  color: var(--danger-text, #b42318);
  cursor: help;
  margin-right: 0.3rem;
}
.purch-unmatched {
  border: 1px solid var(--warn-border, #e6d08a);
  background: var(--warn-soft, #fdf6e3);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
}
.purch-unmatched > summary {
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--warn-text, #8a6d1a);
}
.purch-unmatched-note { font-size: 0.76rem; color: var(--ink-muted); margin: 0.5rem 0; }
.purch-unmatched-tag {
  display: inline-block;
  padding: 0 5px;
  border-radius: 8px;
  font-size: 0.66rem;
  background: var(--surface-2);
  color: var(--ink-muted);
}
.purch-item-minmax {
  flex-shrink: 0; display: flex; gap: 0.4rem; align-items: center;
}
.purch-mm-field { display: flex; flex-direction: column; align-items: center; gap: 0.05rem; }
.purch-mm-field label { font-size: 0.62rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600; }
.purch-mm-input {
  width: 3.2rem; font-size: 0.78rem; text-align: center;
  padding: 0.1rem 0.2rem; border: 1px solid var(--surface-2);
  border-radius: 4px; background: var(--white); color: var(--ink);
}
/* Amber while a Shopify write is in flight (optimistic-pending) */
.purch-cell-pending {
  border-color: var(--warn-text) !important;
  background: var(--warn-soft) !important;
  color: var(--warn-text) !important;
}
/* Custom filter view pills (Chunk 4, 2026-08-25) — mirrors .delay-filter-toggle */
.purch-filter-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin: 0 0 0.9rem; }
.purch-filter-pill {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.78rem; font-weight: 600;
  padding: 0.3rem 0.75rem; border-radius: 999px;
  border: 1.5px solid var(--surface-2); background: var(--white);
  color: var(--ink-soft); cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.purch-filter-pill:hover { border-color: var(--cyan-border-hover); }
.purch-filter-pill.active { background: var(--cyan-bg); border-color: var(--cyan-border); color: var(--cyan-text); }
.purch-filter-pill-edit { font-size: 0.72rem; opacity: 0.6; cursor: pointer; }
.purch-filter-pill-edit:hover { opacity: 1; }
.purch-filter-newview {
  font-size: 0.78rem; font-weight: 600;
  padding: 0.3rem 0.7rem; border-radius: 999px;
  border: 1.5px dashed var(--surface-2); background: transparent;
  color: var(--ink-muted); cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.purch-filter-newview:hover { border-color: var(--cyan-border-hover); color: var(--cyan-text); }
.purch-view-section { margin-bottom: 0.85rem; }
.purch-view-legend { font-size: 0.72rem; font-weight: 700; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.02em; margin-bottom: 0.35rem; }
.purch-view-checks { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; }
.purch-view-checks label { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.83rem; cursor: pointer; }
.purch-abc-A { background: var(--success-soft); color: var(--success-text); }
.purch-abc-B { background: var(--warn-soft); color: var(--warn-text); }
.purch-abc-C { background: var(--surface-2); color: var(--ink-soft); }
.purch-neg-tag {
  font-size: 0.68rem; font-weight: 600;
  padding: 0.05rem 0.35rem; border-radius: 4px;
  background: var(--danger-soft); color: var(--danger-text);
  vertical-align: middle; cursor: help;
}
/* Net-position label when balanced/positive (P8, 2026-08-27) — neutral tone. */
.purch-net-tag {
  font-size: 0.68rem; font-weight: 600;
  padding: 0.05rem 0.35rem; border-radius: 4px;
  background: var(--surface-2, #e9e9ee); color: var(--ink-soft);
  vertical-align: middle; cursor: help;
}
/* Accordion total repeated at the bottom of an expanded vendor group (P3). */
.purch-accordion-body-total {
  text-align: right; font-size: 0.82rem; font-weight: 600; color: var(--ink-soft);
  padding: 0.6rem 0.9rem 0.2rem; border-top: 1px solid var(--surface-2, #e9e9ee); margin-top: 0.4rem;
}
.purch-delay-chip { font-size: 0.72rem; cursor: help; }

.purch-empty-rows { padding: 0.75rem 0; font-size: 0.82rem; color: var(--ink-muted); }

.purch-removed-wrap { margin-top: 0.75rem; }
.purch-removed-toggle {
  border: none; background: none; cursor: pointer;
  color: var(--ink-muted); font-size: 0.78rem; padding: 0.2rem 0;
}
.purch-removed-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  font-size: 0.8rem; color: var(--ink-soft);
  padding: 0.35rem 0; border-top: 1px solid var(--surface);
}

.purch-footer {
  display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;
  margin-top: 1rem; padding-top: 0.85rem; border-top: 1px solid var(--surface-2);
}
.purch-footer-note { font-size: 0.8rem; color: var(--ink-muted); flex: 1; min-width: 180px; }

/* Sumtracker duplicate-order steps — a standing instruction under the export
   buttons (daily + mandatory, so a persistent note rather than a modal). */
.purch-sumtracker-steps {
  flex-basis: 100%; width: 100%;
  margin-top: 0.35rem;
  padding: 0.6rem 0.75rem 0.6rem 0.85rem;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 6px;
  font-size: 0.8rem; color: var(--ink-soft); line-height: 1.5;
}
.purch-sumtracker-steps .pss-head { font-weight: 600; margin-bottom: 0.3rem; }
.purch-sumtracker-steps .pss-req { color: var(--accent-dark); font-weight: 600; }
.purch-sumtracker-steps .pss-manual { color: var(--ink-muted); font-size: 0.76rem; }
.purch-sumtracker-steps ol { margin: 0; padding-left: 1.15rem; }
.purch-sumtracker-steps li { margin: 0.12rem 0; }
.purch-sumtracker-steps strong { color: var(--ink); font-weight: 600; }

/* Sumtracker "draft created" result modal */
.pc-st-ok { font-size: 0.95rem; margin-bottom: 0.75rem; color: var(--ink); }
.pc-st-row { display: flex; justify-content: space-between; gap: 1rem; padding: 0.3rem 0; border-bottom: 1px solid var(--surface-2); font-size: 0.85rem; }
.pc-st-row span { color: var(--ink-muted); }
.pc-st-row strong { color: var(--ink); text-align: right; }
.pc-st-note { margin: 0.85rem 0; font-size: 0.83rem; color: var(--ink-soft); line-height: 1.5; }
.pc-st-warn { margin: 0.85rem 0; padding: 0.6rem 0.75rem; border-left: 3px solid var(--danger); background: var(--danger-soft); border-radius: 6px; font-size: 0.82rem; color: var(--ink-soft); }
.pc-st-warn ul { margin: 0.35rem 0 0; padding-left: 1.15rem; }
.pc-st-warn li { margin: 0.1rem 0; }
.pc-st-actions { display: flex; gap: 0.6rem; margin-top: 1rem; }
.pc-st-actions a.btn-primary { text-decoration: none; display: inline-flex; align-items: center; }
.pc-st-foot { margin-top: 0.85rem; font-size: 0.76rem; color: var(--ink-muted); }

.purch-modal-field { margin-bottom: 1rem; }
.purch-modal-label { font-size: 0.78rem; font-weight: 600; color: var(--ink-soft); margin-bottom: 0.4rem; }
.purch-radio {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: 0.86rem; color: var(--ink); padding: 0.25rem 0; cursor: pointer;
}

/* Purchasing — Phase 2 additions (2026-08-24) */
.purch-item-qty-pack { font-size: 0.72rem; color: var(--accent-dark); font-weight: 600; }

/* Row-field column alignment (2026-08-27) — fixed widths so Min/Max, status,
   Avail and Qty line up vertically down the accordion rows; .purch-item-main
   (flex:1, min-width:0) absorbs the title-length variance so the right-hand
   fields read like columns. */
/* Rigid columns (layout round 2): every section is a fixed-basis column that
   neither grows nor shrinks, so rows line up vertically down the accordion —
   .purch-item-main alone absorbs all width variance. */
.purch-item-minmax { flex: 0 0 7rem; width: 7rem; justify-content: center; }
.purch-item-status { flex: 0 0 2.6rem; width: 2.6rem; justify-content: center; }
.purch-item-net    { flex: 0 0 8rem; width: 8rem; }
.purch-item-qty    { flex: 0 0 10rem; width: 10rem; }

/* Compact, wrap-friendly variant of .dash-table for the open-orders modal, so
   it fits a 92vw card without horizontal scroll (the base .dash-table has
   min-width:900px + nowrap cells). Scoped to this table only (2026-08-27). */
.pc-orders-table { min-width: 0; font-size: 0.8rem; }
.pc-orders-table th, .pc-orders-table td { white-space: normal; }

/* Bundle decomposition in the unmatched-committed callout (2026-08-27). */
.purch-bundle-breakdown { margin-top: 0.9rem; }
.purch-bundle-h { font-size: 0.9rem; margin: 0 0 0.5rem; }
.purch-bundle-block { margin: 0 0 1rem; padding: 0.6rem 0.7rem; border: 1px solid var(--surface-2); border-radius: 8px; background: var(--surface); }
.purch-bundle-head { font-weight: 600; font-size: 0.85rem; margin: 0 0 0.4rem; }
.purch-bundle-short td { background: var(--danger-soft, #fde8e8); font-weight: 600; }
.purch-po-vendor-fields { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 1rem; }
.purch-po-vendor-fields label { font-size: 0.78rem; color: var(--ink-soft); display: flex; flex-direction: column; gap: 0.2rem; }
.purch-po-vendor-fields input { min-width: 180px; }
.purch-po-table { width: 100%; border-collapse: collapse; font-size: 0.8rem; }
.purch-po-table th { text-align: left; color: var(--ink-soft); font-weight: 600; padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--surface-2); font-size: 0.72rem; }
.purch-po-table td { padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--surface); vertical-align: middle; }
.purch-po-table td.num { text-align: right; }
.purch-po-table input.purch-supplier-sku { width: 130px; font-size: 0.78rem; padding: 0.2rem 0.4rem; }
.purch-po-table input.purch-supplier-sku.missing { border-color: var(--warn); background: var(--warn-soft); }
.purch-po-thumb { width: 32px; height: 32px; object-fit: cover; border-radius: 4px; border: 1px solid var(--surface-2); }
.purch-po-modal-card { max-width: 900px; width: 94%; }
.purch-email-preview { background: var(--surface); border-radius: 8px; padding: 0.75rem; font-size: 0.82rem; margin-top: 0.75rem; }
.purch-email-preview textarea { width: 100%; min-height: 120px; font-family: inherit; font-size: 0.82rem; margin-top: 0.4rem; }
.purch-settings-field { margin-bottom: 0.9rem; display: flex; flex-direction: column; gap: 0.3rem; }
.purch-settings-field label { font-size: 0.78rem; font-weight: 600; color: var(--ink-soft); }
/* Themed form controls (use design tokens so they flip with html.theme-dark;
   without these the inputs fall back to the browser's default chrome, which
   looks off against the dark modal). */
.purch-settings-field input[type="text"],
.purch-settings-field input[type="number"],
.purch-settings-field textarea,
.purch-settings-field select {
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius);
  padding: 0.5rem 0.65rem;
  font-family: inherit;
  font-size: 0.86rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.purch-settings-field textarea { min-height: 70px; resize: vertical; line-height: 1.45; }
.purch-settings-field input[type="text"]:focus,
.purch-settings-field input[type="number"]:focus,
.purch-settings-field textarea:focus,
.purch-settings-field select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.purch-settings-field input::placeholder,
.purch-settings-field textarea::placeholder { color: var(--ink-muted); }
/* Column editor + section rows live in .purch-settings-field but aren't inputs;
   keep their dividers on the flipping token too. */
#pcColEditor .pc-col-row { border-bottom-color: var(--surface-2) !important; }
/* PO Settings two-pane (controls + live preview) — stack on narrow screens */
@media (max-width: 860px) {
  .pc-settings-body { flex-direction: column; max-height: 82vh; overflow-y: auto; }
  .pc-settings-preview { border-left: none !important; border-top: 1px solid var(--surface-2); }
  #pcPdfPreview { min-height: 420px; }
}

/* =============================================================================
   Recommendation Logic panel (2026-09-01, session 2) — explainer + per-SKU trace.
   Tokens verified against the real palette (no phantom vars).
   ============================================================================= */
.purch-why-btn {
  background: none; border: none; cursor: pointer; font-size: 0.95rem;
  color: var(--ink-muted); padding: 0 0.15rem; line-height: 1; align-self: center;
  opacity: 0.65; transition: opacity 0.15s ease;
}
.purch-why-btn:hover { opacity: 1; }

.pc-rec-searchwrap { position: relative; margin-bottom: 1rem; }
.pc-rec-search-input {
  width: 100%; padding: 0.55rem 0.75rem; border: 1px solid var(--surface-2);
  border-radius: var(--radius); background: var(--surface); color: var(--ink); font-size: 0.9rem;
}
.pc-rec-search-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.pc-rec-search-results {
  position: absolute; z-index: 5; top: calc(100% + 2px); left: 0; right: 0;
  background: var(--surface); border: 1px solid var(--surface-2); border-radius: var(--radius);
  box-shadow: var(--shadow); max-height: 320px; overflow-y: auto;
}
.pc-rec-search-hit {
  display: flex; flex-direction: column; gap: 0.1rem; width: 100%; text-align: left;
  background: none; border: none; border-bottom: 1px solid var(--surface-2); cursor: pointer;
  padding: 0.5rem 0.75rem;
}
.pc-rec-search-hit:last-child { border-bottom: none; }
.pc-rec-search-hit:hover { background: var(--surface-2); }
.pc-rec-search-sku { font-weight: 600; font-size: 0.85rem; color: var(--ink); }
.pc-rec-search-title { font-size: 0.78rem; color: var(--ink-muted); }
.pc-rec-search-none { padding: 0.6rem 0.75rem; font-size: 0.85rem; color: var(--ink-muted); }

.pc-rec-empty { padding: 2rem 1rem; text-align: center; color: var(--ink-muted); font-size: 0.9rem; }

.pc-rec-trace-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
  padding-bottom: 0.85rem; margin-bottom: 0.85rem; border-bottom: 1px solid var(--surface-2); flex-wrap: wrap;
}
.pc-rec-trace-sku { font-size: 1.05rem; font-weight: 700; color: var(--ink); }
.pc-rec-shopify { text-decoration: none; color: var(--accent); font-size: 0.85rem; }
.pc-rec-trace-title { font-size: 0.82rem; color: var(--ink-muted); margin-top: 0.15rem; }
.pc-rec-verdict { text-align: right; }
.pc-rec-verdict-tier { font-weight: 700; font-size: 0.95rem; color: var(--ink); }
.pc-rec-verdict-qty { font-size: 0.85rem; color: var(--ink-muted); margin-top: 0.1rem; }

.pc-rec-card {
  background: var(--surface-2); border-radius: var(--radius); padding: 0.75rem 0.9rem; margin-bottom: 0.75rem;
}
.pc-rec-card-h { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-muted); font-weight: 700; margin-bottom: 0.5rem; }
.pc-rec-sub { font-size: 0.8rem; color: var(--ink-muted); margin-top: 0.4rem; line-height: 1.45; }

.pc-rec-eq { display: flex; align-items: flex-end; gap: 0.5rem; flex-wrap: wrap; }
.pc-rec-eq-part { display: flex; flex-direction: column; align-items: center; }
.pc-rec-eq-n { font-size: 1.15rem; font-weight: 700; color: var(--ink); }
.pc-rec-eq-l { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-muted); margin-top: 0.1rem; }
.pc-rec-eq-op { font-size: 1.05rem; color: var(--ink-muted); padding-bottom: 0.9rem; }
.pc-rec-eq-total .pc-rec-eq-n { color: var(--accent); }

.pc-rec-ladder-live { display: flex; flex-direction: column; gap: 0.3rem; }
.pc-rec-rung { display: grid; grid-template-columns: 1.2rem auto 1fr; align-items: baseline; gap: 0.5rem; font-size: 0.83rem; padding: 0.25rem 0.4rem; border-radius: 6px; }
.pc-rec-rung-off { opacity: 0.5; }
.pc-rec-rung-fired { background: var(--surface); font-weight: 600; }
.pc-rec-rung-mark { color: var(--accent); font-weight: 700; text-align: center; }
.pc-rec-rung-name { white-space: nowrap; color: var(--ink); }
.pc-rec-rung-test { color: var(--ink-muted); font-weight: 400; }
.pc-rec-rung-fired .pc-rec-rung-test { color: var(--ink); }

.pc-rec-inputs { display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem; align-items: flex-end; }
.pc-rec-mm { display: flex; flex-direction: column; gap: 0.15rem; }
.pc-rec-mm span { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-muted); }
.pc-rec-mm-input {
  width: 72px; padding: 0.3rem 0.4rem; border: 1px solid var(--surface); border-radius: 6px;
  background: var(--surface); color: var(--ink); font-size: 0.85rem;
}
.pc-rec-mm-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.pc-rec-mm-pending { border-color: var(--warn) !important; background: var(--warn-soft) !important; }
.pc-rec-kv { display: flex; flex-direction: column; gap: 0.1rem; }
.pc-rec-kv span { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-muted); }
.pc-rec-kv strong { font-size: 0.9rem; color: var(--ink); }

.pc-rec-mismatch {
  background: var(--danger-soft); color: var(--danger-text); border-radius: var(--radius);
  padding: 0.6rem 0.8rem; font-size: 0.82rem; margin-bottom: 0.85rem; line-height: 1.45;
}

/* Overview (collapsible) */
.pc-rec-ov-wrap { margin-top: 0.5rem; border-top: 1px solid var(--surface-2); padding-top: 0.75rem; }
.pc-rec-ov-wrap summary { cursor: pointer; font-weight: 600; font-size: 0.88rem; color: var(--ink); }
.pc-rec-overview { margin-top: 0.85rem; display: flex; flex-direction: column; gap: 0.9rem; }
.pc-rec-ov-step { display: grid; grid-template-columns: 1.8rem 1fr; gap: 0.7rem; align-items: start; }
.pc-rec-ov-num {
  width: 1.8rem; height: 1.8rem; border-radius: 50%; background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.9rem;
}
.pc-rec-ov-h { font-weight: 700; font-size: 0.9rem; color: var(--ink); margin-bottom: 0.25rem; }
.pc-rec-ov-body { font-size: 0.83rem; color: var(--ink-soft); line-height: 1.5; }
.pc-rec-ov-body code, .pc-rec-ov-note code { background: var(--surface-2); border-radius: 4px; padding: 0.05rem 0.3rem; font-size: 0.9em; }
.pc-rec-ladder { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.35rem; }
.pc-rec-ladder .pc-rec-t { font-weight: 600; color: var(--ink); }
.pc-rec-abc { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.4rem; }
.pc-rec-abc-badge { display: inline-block; min-width: 1.15rem; text-align: center; border-radius: 4px; font-weight: 700; font-size: 0.75rem; padding: 0 0.2rem; border: 1px solid currentColor; }
.pc-abc-A { color: var(--success-text); }
.pc-abc-B { color: var(--warn); }
.pc-abc-C { color: var(--ink-muted); }
.pc-abc-D { color: var(--danger); }
.pc-rec-ov-note { font-size: 0.8rem; color: var(--ink-muted); line-height: 1.5; background: var(--surface-2); border-radius: var(--radius); padding: 0.6rem 0.8rem; }

/* Bundle-demand line in the recommendation trace (2026-09-01 s2).
   The CCM chip classes that used to live here (.purch-ccm-chip, .pc-rec-ccm,
   .pc-rec-ccm-flag) were removed 2026-09-03 s2 — the CCM chip was reverted on
   2026-09-01 once the investigation reframed the problem as bundle demand, and
   the CSS had been dead ever since. .pc-rec-bundle below is live and in use. */
.pc-rec-bundle {
  margin-top: 0.45rem;
  font-size: 0.8rem;
  color: var(--ink);
  background: var(--cyan-bg);
  border-radius: 6px;
  padding: 0.4rem 0.55rem;
  line-height: 1.5;
}

/* Settings tab sections + condensed per-row quick view (2026-09-01 s2) */
.pc-settings-section { margin-bottom: 0.5rem; }
.pc-settings-divider { border: none; border-top: 1px solid var(--surface-2); margin: 1.6rem 0 1.4rem; }

.pc-recq-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; }
.pc-recq-sku { font-size: 1.05rem; font-weight: 700; color: var(--ink); }
.pc-recq-verdict { font-size: 0.9rem; color: var(--ink-muted); }
.pc-recq-title { font-size: 0.82rem; color: var(--ink-muted); margin: 0.15rem 0 0.7rem; }
.pc-recq-why { font-size: 0.9rem; color: var(--ink); line-height: 1.55; margin: 0 0 0.7rem; }
.pc-recq-why code { background: var(--surface-2); border-radius: 4px; padding: 0.05rem 0.3rem; font-size: 0.9em; }
.pc-recq-net { font-size: 0.82rem; color: var(--ink-muted); background: var(--surface-2); border-radius: var(--radius); padding: 0.5rem 0.7rem; }
.pc-recq-ccm { font-size: 0.82rem; color: var(--ccm-accent); background: var(--cyan-bg); border: 1px solid var(--ccm-accent); border-radius: var(--radius); padding: 0.5rem 0.7rem; margin-top: 0.6rem; line-height: 1.45; }
.pc-recq-mm { display: flex; align-items: flex-end; gap: 1rem; margin-top: 0.9rem; padding-top: 0.8rem; border-top: 1px solid var(--surface-2); }

/* =============================================
   Purchasing → Delay Orders tab (added 2026-09-02)
   =============================================
   A near-mirror of the OrderStatus app's DELAY view. Card-per-order rather
   than a table, because each order carries a variable-height private-note
   block (with an indented component sub-list on kit lines) that a table row
   can't hold cleanly. All colors come from existing tokens so dark mode works
   with no extra rules. See js/purchasing-delay.js. */
.pd-count { font-size: 0.82rem; color: var(--ink-muted); white-space: nowrap; }
.pd-refresh-msg { font-size: 0.8rem; color: var(--ink-muted); margin: 0.4rem 0 0.8rem; min-height: 1em; }

/* Each order is its own bordered block (2026-09-15 s3, Dylan). Two weights,
   because the two states are doing different jobs: collapsed cards are being
   SCANNED, so they need a quiet edge that separates one order from the next
   down a long list; an expanded card is being WORKED ON, so it gets a heavier
   border plus a lift to pull it forward from its neighbours. The header's own
   border-bottom stays the internal divider when open and is suppressed when
   collapsed (see .pd-card--collapsed .pd-head below), so the outline is the
   only edge on a closed card. Border WIDTH is held constant across both
   states — only the colour changes — so toggling an accordion can't shift the
   rows beneath it by a pixel. */
.pd-card { background: var(--white); border: 1.5px solid var(--pd-card-border-open); border-radius: var(--radius);
  margin-bottom: 0.9rem; overflow: hidden; box-shadow: var(--shadow); }
.pd-card--collapsed { border-color: var(--pd-card-border); box-shadow: none; }

/* Order header. Fixed-ish column widths keep the cards visually aligned
   down the page without an actual table, mirroring the app's layout. */
.pd-head { display: grid; grid-template-columns: 1.1rem 8.5rem 12rem 9rem 7.5rem minmax(7rem, 1fr) 13rem 6rem 7rem 5rem;
  gap: 0.5rem; align-items: center; padding: 0.6rem 0.8rem; border-bottom: 1px solid var(--surface-2); font-size: 0.82rem;
  background: var(--surface); /* darker than the card body (Sue, 2026-09-15 s1) so each order's header row reads as a divider */
  cursor: pointer; } /* whole header toggles the accordion (2026-09-09); interactive children opt out in the delegated handler */
/* The badges cell (col 7) holds up to THREE chips — Paid + Unfulfilled +
   ⚡PRIORITY. PRIORITY lives INSIDE this cell (2026-09-11 s2): as a sibling it
   was an 11th child in a 10-column grid, which shoved the Edit button onto a
   second row on exactly the PRIORITY orders. Constant child count = Edit is
   always the last column and collapsed cards keep one fixed height. The cell
   widened 11rem -> 13rem (taken from the flexible customer column) so all
   three fit on one line; flex-wrap stays as an extreme-zoom fallback that
   never hides information. */
@media (max-width: 1200px) { .pd-head { grid-template-columns: 1rem 1fr 1fr 1fr; } }
/* Accordion pieces (2026-09-09, Sue's ask) */
.pd-card--collapsed .pd-head { border-bottom: none; }
.pd-head:hover { background: var(--surface-2); }
.pd-linecount { font-size: 0.72rem; color: var(--ink-muted); white-space: nowrap; }
.pd-expandall { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; color: var(--ink-muted);
  cursor: pointer; white-space: nowrap; margin-right: 0.6rem; }
.pd-chip--vendor { background: var(--accent-soft); color: var(--accent); }
.pd-order { font-weight: 600; color: var(--accent); text-decoration: none; }
.pd-order:hover { text-decoration: underline; }
.pd-status { display: inline-block; padding: 0.15rem 0.5rem; border-radius: 999px; font-size: 0.72rem;
  font-weight: 600; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Status chip colours mirroring the OrderStatus (W3trends) app's own palette,
   read off its Statuses screen 2026-09-02, so a status reads the same colour in
   the portal as it does in the app. ~70 statuses share ~15 colours; the
   name->family matching lives in pdStatusChipClass() (js/purchasing-delay.js).
   These hexes are INTENTIONALLY not themed — they mirror an external app's
   brand colours, so they must not shift with light/dark mode. Each pairs a
   background with an explicit text colour so contrast holds in both. */
.pd-st--purple     { background: #9028ad; color: #ffffff; }
.pd-st--onorder    { background: #c97bae; color: #ffffff; }
.pd-st--blue       { background: #2196f3; color: #ffffff; }
.pd-st--lightblue  { background: #35b6f2; color: #ffffff; }
.pd-st--brown      { background: #6d4c41; color: #ffffff; }
.pd-st--brown-dark { background: #3e2723; color: #ffffff; }
.pd-st--green      { background: #2e7d32; color: #ffffff; }
.pd-st--pink       { background: #e51e63; color: #ffffff; }
.pd-st--olive      { background: #9e9d24; color: #ffffff; }
.pd-st--red        { background: #e53935; color: #ffffff; }
.pd-st--redorange  { background: #f4511e; color: #ffffff; }
.pd-st--cyan       { background: #00acc1; color: #ffffff; }
.pd-st--palecyan   { background: #b2ebf2; color: #00565e; }
.pd-st--grey       { background: #dcdce4; color: #3f3f52; }
/* SHIPPED - PAID is unstyled in the app (plain text, no chip). A bare
   transparent chip disappears against the card, so it keeps a light outline. */
.pd-st--plain      { background: transparent; color: var(--ink-soft); border: 1px solid var(--border-dashed); }
/* Any status with no family rule yet — deliberately neutral rather than
   guessing at a colour, so a new status looks obviously uncategorised. */
.pd-st--unknown    { background: var(--surface-2); color: var(--ink-soft); }
.pd-due { font-variant-numeric: tabular-nums; color: var(--ink); }
.pd-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-left: 0.35rem; vertical-align: middle; }
.pd-dot--red { background: var(--danger); }
.pd-dot--amber { background: var(--warn); }
.pd-dot--green { background: var(--success); }
.pd-date { color: var(--ink-muted); }
.pd-cust { color: var(--ink); overflow: hidden; text-overflow: ellipsis; }
.pd-co { display: block; font-size: 0.74rem; color: var(--ink-muted); }
.pd-badges { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.pd-badge { padding: 0.1rem 0.4rem; border-radius: 999px; font-size: 0.7rem; font-weight: 600; white-space: nowrap; }
/* Paid + every fulfillment status are neutral grey (Sue, 2026-10-13); only an
   unpaid/pending payment keeps amber, so it is the one that stands out. */
.pd-badge--neutral { background: var(--surface-2); color: var(--ink-soft); }
.pd-badge--pending { background: var(--warn-soft); color: var(--warn-text); }
.pd-total { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); }

/* Notes. Private and public sit side by side so both are visible at once
   (an explicit ask — the app hides the public note behind a separate edit). */
.pd-notes { display: grid; grid-template-columns: 1.6fr 1fr; gap: 0.8rem; padding: 0.7rem 0.8rem; }
@media (max-width: 1000px) { .pd-notes { grid-template-columns: 1fr; } }
.pd-note-block { background: var(--warn-soft); border-radius: var(--radius); padding: 0.6rem 0.7rem; }
.pd-note-block--public { background: var(--surface-2); }
/* Shopify order note: neutral grey like the public notes (Sue, 2026-10-13 —
   fewer colours, easier to focus). Amber private notes stay the one coloured
   block; the labels tell the two grey blocks apart. */
.pd-note-block--shopify { background: var(--surface-2); }
.pd-note-label { font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--ink-soft); margin-bottom: 0.4rem; }
.pd-note-hint { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--ink-muted); }
.pd-public { font-size: 0.82rem; color: var(--ink); line-height: 1.5; }
.pd-public :is(p, ul, ol) { margin: 0 0 0.4rem; }

.pd-note-line { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 0.4rem;
  font-size: 0.82rem; color: var(--ink); padding: 0.2rem 0; line-height: 1.45; }
.pd-note-line--done .pd-note-text { text-decoration: line-through; color: var(--ink-muted); }
/* Hand-written lines aren't order data, so they get no checkbox and are
   never touched by the bulk remove — visually de-emphasised to match. */
.pd-note-line--hand { color: var(--ink-muted); font-style: italic; padding-left: 1.4rem; }

/* Live-note staleness (2026-09-03 s2) — a rendered line the OrderStatus note no
   longer contains. Struck out with its checkbox disabled, because ticking it
   could only ever end in the save-time abort. */
.pd-note-line--stale { opacity: 0.65; }
.pd-note-line--stale .pd-note-text { text-decoration: line-through; color: var(--ink-muted); }
.pd-chip--stale { background: var(--warn-soft); color: var(--warn-text); }
.pd-stale-notice {
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--warn-text);
  background: var(--warn-soft);
  border-radius: var(--radius);
  padding: 0.5rem 0.7rem;
  margin-bottom: 0.6rem;
}
.pd-note-check { flex: 0 0 auto; padding-top: 0.15rem; cursor: pointer; }
.pd-note-text { flex: 1 1 20rem; min-width: 0; }

.pd-chip { flex: 0 0 auto; padding: 0.1rem 0.45rem; border-radius: 999px; font-size: 0.72rem;
  font-weight: 600; white-space: nowrap; cursor: help; }
/* "All good" chips (in stock, on order) are neutral grey (Sue, 2026-10-13) so
   only amber (check) and red (needs ordering) draw the eye. */
.pd-chip--ok { background: var(--surface-2); color: var(--ink-soft); }
.pd-chip--warn { background: var(--warn-soft); color: var(--warn-text); }
.pd-chip--need { background: var(--danger-soft); color: var(--danger-text-alt); }
.pd-chip--muted { background: var(--surface-2); color: var(--ink-muted); }
/* "Already on the buy list under vendor X" — deliberately a different palette
   from the ok/warn/need verdict chips, because it isn't a verdict about stock,
   it's a cross-reference to the Orders tab. --info-soft has a dark-mode pair. */
.pd-chip--reco { background: var(--info-soft); color: var(--ink); }
.pd-via { font-size: 0.72rem; color: var(--ink-muted); cursor: help; }

/* Kit component sub-list — indented under its note line, because a kit hides
   several different products behind one SKU and those components are what
   actually get ordered. Single-component bundles get an inline chip instead. */
.pd-subs { flex: 1 1 100%; margin: 0.25rem 0 0.2rem 1.6rem; padding-left: 0.7rem;
  border-left: 2px solid var(--border-dashed); display: flex; flex-direction: column; gap: 0.2rem; }
.pd-sub { display: flex; align-items: center; gap: 0.45rem; font-size: 0.78rem; }
.pd-sub-qty { font-variant-numeric: tabular-nums; color: var(--ink-soft); font-weight: 600; flex: 0 0 auto; }
.pd-sub-sku { font-family: ui-monospace, Menlo, Consolas, monospace; color: var(--ink); flex: 0 0 auto; }
.pd-sub-title { color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; min-width: 0; }

.pd-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem;
  margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid rgba(0, 0, 0, 0.08); }
.pd-actions-count { font-size: 0.78rem; color: var(--ink-soft); font-weight: 600; }
.pd-btn { font-size: 0.78rem; padding: 0.35rem 0.7rem; }
.pd-btn-plain { background: none; border: none; color: var(--ink-muted); font-size: 0.78rem;
  cursor: pointer; padding: 0.2rem 0.35rem; border-radius: 4px; white-space: nowrap; }
.pd-btn-plain:hover { color: var(--accent); background: var(--surface-2); }

/* Delay Orders custom filter builder + pill counts (2026-09-02). The pills
   themselves reuse .purch-filter-pill* from the Orders tab — same idea, so
   deliberately the same styling rather than a second look. */
.pd-pill-count { font-size: 0.7rem; opacity: 0.65; font-variant-numeric: tabular-nums; }
.pd-view-list-head { display: flex; align-items: center; justify-content: space-between; margin: 0.9rem 0 0.2rem; }
.pd-view-status-list { max-height: 320px; overflow-y: auto; border: 1px solid var(--surface-2);
  border-radius: var(--radius); padding: 0.4rem 0.5rem; }
.pd-view-status { display: flex; align-items: center; gap: 0.5rem; padding: 0.22rem 0.1rem; cursor: pointer; }
.pd-view-status:hover { background: var(--surface-2); border-radius: 4px; }
.pd-view-status input { flex: 0 0 auto; cursor: pointer; }
/* The status chip renders at its real colour here, so picking statuses looks
   the same as reading them in the list. */
.pd-view-status .pd-status { flex: 0 1 auto; max-width: none; }
.pd-view-status-count { margin-left: auto; font-size: 0.75rem; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
/* Two deep links per order row: the order number opens Shopify admin (system
   of record), the small "OS" chip opens the OrderStatus app. Added 2026-09-02. */
.pd-order-links { display: flex; align-items: baseline; gap: 0.35rem; min-width: 0; }
.pd-order-os { font-size: 0.68rem; font-weight: 600; color: var(--ink-muted); text-decoration: none;
  border: 1px solid var(--border-dashed); border-radius: 4px; padding: 0.02rem 0.25rem; white-space: nowrap; }
.pd-order-os:hover { color: var(--accent); border-color: var(--accent); }
/* Icon variant (2026-09-04): the "OS ↗" text label replaced by the app's own
   icon, sized to match the label's footprint so row height and the baseline
   alignment of .pd-order-links are unchanged. */
.pd-order-os--icon { padding: 0.02rem 0.18rem; display: inline-flex; align-items: center;
  line-height: 1; align-self: center; }
.pd-order-os--icon img { width: 14px; height: 14px; border-radius: 3px; display: block; }
.pd-order-os--icon:hover img { opacity: 0.85; }

/* ============================================================
   Committed-bundle diagnostics on the Orders tab (2026-09-04)
   The verdict block is deliberately the loudest thing in a bundle
   block: whether a bundle is in the bundles reference decides
   whether there is anything to DO, and that was previously only
   inferable from a component table.
   ============================================================ */
.purch-bundle-verdict { font-size: 0.8rem; line-height: 1.5; border-radius: 6px;
  padding: 0.5rem 0.65rem; margin: 0.45rem 0 0.6rem; border: 1px solid transparent; }
.purch-bundle-verdict--ok { color: var(--ink-soft); background: rgba(34, 197, 94, 0.08);
  border-color: rgba(34, 197, 94, 0.35); }
.purch-bundle-verdict--warn { color: var(--ink); background: rgba(251, 146, 60, 0.10);
  border-color: rgba(251, 146, 60, 0.45); }
.purch-bundle-fixnote { margin-top: 0.4rem; font-size: 0.76rem; color: var(--ink-soft); }
.purch-bundle-csv { margin-top: 0.5rem; }
.purch-bundle-csv-h { font-size: 0.76rem; color: var(--ink-soft); margin-bottom: 0.25rem; }
.purch-bundle-csv pre { margin: 0; font-size: 0.74rem; line-height: 1.5; padding: 0.45rem 0.6rem;
  background: var(--surface-2); border: 1px solid var(--border-dashed); border-radius: 5px;
  overflow-x: auto; white-space: pre; font-family: ui-monospace, Menlo, Consolas, monospace; }
.purch-bundle-ok-tag { font-size: 0.7rem; font-weight: 600; color: rgb(74, 222, 128);
  background: rgba(34, 197, 94, 0.10); border: 1px solid rgba(34, 197, 94, 0.30);
  border-radius: 4px; padding: 0.02rem 0.3rem; white-space: nowrap; }
/* Row chip naming demand that comes from bundles rather than from orders for
   the SKU itself — otherwise the recommended quantity looks unexplained. */
.purch-bundle-chip { font-size: 0.7rem; font-weight: 600; color: var(--ink-soft);
  background: var(--surface-2); border: 1px solid var(--border-dashed);
  border-radius: 4px; padding: 0.02rem 0.3rem; white-space: nowrap; margin-left: 0.3rem; }

/* ============================================================
   E-Transfers page (added 2026-09-02)
   ============================================================
   Scoped under .et-* so nothing here can reach the other tables. Chips
   reuse the themed --success-text/--warn-text/--danger-text-alt tokens
   rather than hardcoded hex, so they stay readable in dark mode — the
   2026-09-02 Delay Orders lesson, applied up front this time. (The Delay
   tab's status chips are the deliberate exception to that rule: they
   mirror an EXTERNAL app's brand colours, which must not shift.) */
.et-muted { color: var(--ink-muted); }
.et-submuted { font-size: 0.72rem; color: var(--ink-muted); margin-top: 0.12rem; line-height: 1.3; }
.et-amount { font-weight: 600; white-space: nowrap; }
.et-ref { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.75rem; color: var(--ink-soft); }

.et-chip { display: inline-block; font-size: 0.68rem; font-weight: 600; padding: 0.1rem 0.4rem;
  border-radius: 999px; white-space: nowrap; }
.et-chip--ok      { background: var(--success-soft); color: var(--success-text); }
.et-chip--warn    { background: var(--warn-soft);    color: var(--warn-text); }
.et-chip--danger  { background: var(--danger-soft);  color: var(--danger-text-alt); }
.et-chip--neutral { background: var(--surface-2);    color: var(--ink-soft); }

/* Store identity colours — BSC #D01D5A, CCM #1cd5ff, HBC #139cd2.
   DELIBERATELY UN-THEMED, same reasoning as the Delay tab's OrderStatus
   chips: these are the three businesses' real brand colours, so they must
   NOT invert or shift in dark mode. Each chip therefore pairs its
   background with an explicit text colour rather than inheriting one.
   CCM's cyan is far too light to carry white text, so it takes dark ink
   while the other two take white. */
.et-chip--store { border: 1px solid transparent; }
.et-chip--bsc { background: #D01D5A; color: #ffffff; }
.et-chip--ccm { background: #1cd5ff; color: #06384a; }
.et-chip--hbc { background: #139cd2; color: #ffffff; }

/* Row identity. A solid left edge in the store's colour plus a very
   light wash of the same hue, so the store is readable at a glance
   without the tint fighting the text. The washes are rgba rather than
   opaque tints so they sit correctly over BOTH the light and dark row
   backgrounds — an opaque pastel would blow out the dark theme. */
.et-row--bsc td:first-child { box-shadow: inset 4px 0 0 0 #D01D5A; }
.et-row--ccm td:first-child { box-shadow: inset 4px 0 0 0 #1cd5ff; }
.et-row--hbc td:first-child { box-shadow: inset 4px 0 0 0 #139cd2; }
.et-row--bsc td { background: rgba(208, 29, 90, 0.045); }
.et-row--ccm td { background: rgba(28, 213, 255, 0.075); }
.et-row--hbc td { background: rgba(19, 156, 210, 0.065); }
/* No store worked out yet — a dashed neutral edge, visually distinct
   from all three brands so "unknown" never reads as one of them. */
.et-row--unknown td:first-child { box-shadow: inset 4px 0 0 0 var(--border-dashed); }
.theme-dark .et-row--bsc td { background: rgba(208, 29, 90, 0.13); }
.theme-dark .et-row--ccm td { background: rgba(28, 213, 255, 0.11); }
.theme-dark .et-row--hbc td { background: rgba(19, 156, 210, 0.13); }

/* Where the customer's email came from. The e-transfer forward usually
   destroys it, so a Shopify-sourced address is labelled as such rather
   than presented as the sender's — they are not the same claim. */
.et-email-src { font-size: 0.64rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.02em; color: var(--ink-muted); margin-left: 0.25rem; }

.et-store-unknown { display: flex; flex-direction: column; gap: 0.2rem; align-items: flex-start; }
.et-store-select { font-size: 0.7rem; padding: 0.1rem 0.2rem; border: 1px solid var(--border-dashed);
  border-radius: 4px; background: var(--white); color: var(--ink-soft); max-width: 140px; }

.et-match { display: flex; flex-direction: column; gap: 0.1rem; align-items: flex-start; }
.et-order-link { font-weight: 600; color: var(--accent); text-decoration: none; }
.et-order-link:hover { text-decoration: underline; }
.et-linkish { background: none; border: none; padding: 0; font: inherit; font-weight: 600;
  color: var(--accent); cursor: pointer; text-align: left; }
.et-linkish:hover { text-decoration: underline; }

.et-verify { text-align: center; }
.et-check input { width: 17px; height: 17px; cursor: pointer; accent-color: var(--accent); }
.et-row--verified { opacity: 0.72; }

/* Candidate picker */
.et-modal-intro { font-size: 0.85rem; color: var(--ink-soft); margin: 0 0 0.75rem; }
.et-cand-list { display: flex; flex-direction: column; gap: 0.5rem; }
.et-cand { border: 1px solid var(--surface-2); border-radius: var(--radius); padding: 0.6rem 0.7rem;
  display: flex; flex-direction: column; gap: 0.3rem; align-items: flex-start; }
.et-cand-main { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; }
.et-cand-sub { font-size: 0.76rem; color: var(--ink-muted); line-height: 1.4; }
.et-modal-actions { margin-top: 0.9rem; padding-top: 0.7rem; border-top: 1px solid var(--surface-2); }

/* Original-email modal. The iframe is sandboxed with NO allow-scripts
   and NO allow-same-origin (see openEtEmailModal) — the white background
   is hardcoded rather than themed on purpose, because the email's own
   HTML assumes a light background and would be unreadable if the frame
   inverted in dark mode while the email's inline colours did not. */
.et-email-meta { font-size: 0.82rem; color: var(--ink-soft); margin-bottom: 0.7rem;
  padding-bottom: 0.6rem; border-bottom: 1px solid var(--surface-2); }
.et-email-frame { width: 100%; height: 62vh; border: 1px solid var(--surface-2);
  border-radius: var(--radius); background: #ffffff; }
.et-email-note { font-size: 0.72rem; color: var(--ink-muted); margin: 0.5rem 0 0; }
.et-email-pre { margin: 0; white-space: pre-wrap; font-family: inherit; font-size: 0.86rem;
  line-height: 1.5; }

/* Column resize + long-text clipping (added 2026-09-03).
   Ported from the AR page's confirmed-working model rather than written
   fresh — see the "Column resize (added 2026-07-23)" section above for why
   each handle resizes ONLY its own column, in plain pixels (a
   neighbour-shrinking/percentage variant was tried there and reverted
   because the error compounded per drag).

   `table-layout: fixed` is load-bearing TWICE over here: it's required for
   a manually-set <th> width to stick rather than being recomputed from
   content, AND it's what stops one long cell from widening the whole
   table. Before this, a long message_note — in practice Interac's own
   ~400-character boilerplate footer, on a single line because
   `.dash-table td` sets `white-space: nowrap` — stretched the Order column
   until Reference / 👁 / Verified sat off the right edge of
   .dash-table-wrap's scroll area. Starting widths are set per column in
   ET_COLUMN_DEFS (js/e-transfers.js) rather than left to fixed-layout's
   even 10-way division, which gave the 👁 button the same room as Order. */
#etTable { table-layout: fixed; }
#etTable thead th { position: relative; overflow: hidden; text-overflow: ellipsis; }
#etTable td { overflow: hidden; }
/* The two trailing columns are both interactive (👁 opens the original
   email, then the Verified checkbox). Clipping a control makes it
   UNCLICKABLE rather than merely truncated, which is the same reason the
   AR tables exempt their actions column — widened to two here because this
   table ends with two control columns. Both sit at the right edge, so
   overflowing rightward can never cover another column's content. */
#etTable td:nth-last-child(1), #etTable td:nth-last-child(2) { overflow: visible; }

.et-col-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 6px;
  cursor: col-resize;
  user-select: none;
  z-index: 2;
}
.et-col-resize-handle:hover, .et-col-resize-handle:active { background: var(--accent-soft); }

/* The sender's message note, clamped to 2 lines. Deliberately NOT
   single-line ellipsis: every other cell in this table stacks a small
   .et-submuted sub-line under its main value, and the `white-space: nowrap`
   that ellipsis needs would flatten all of them into one line.
   `overflow-wrap: anywhere` is required because the note can contain an
   unbroken URL (Interac's FAQ link is in there), which would otherwise
   refuse to wrap and just get sliced mid-line at the column edge.
   The full text stays one click away via the 👁 original-email modal,
   which is why it isn't crammed into a data-tooltip — the shared
   .dynamic-tooltip is capped at 230px with pointer-events:none, so a long
   note would render as a tall, unselectable sliver. */
.et-note {
  white-space: normal;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* E-Transfers Settings tab (added 2026-09-03) — the address -> store map
   that drives automatic store detection at intake. Reuses the page's
   existing .et-chip--store colours and .et-store-select so an address row
   reads the same way a transfer row does. */
.et-settings-intro { margin: 0 0 1.1rem; }
.et-settings-intro p { font-size: 0.85rem; color: var(--ink-soft); line-height: 1.55; margin: 0 0 0.55rem; }
/* The "don't add an address that appears in every forward" warning. Styled
   as a caution rather than body copy because getting it wrong doesn't fail
   loudly — it silently mislabels which store a payment belongs to. */
.et-settings-warn { background: var(--warn-soft); color: var(--warn-text);
  border-radius: var(--radius); padding: 0.6rem 0.75rem; font-size: 0.8rem; }
.et-settings-warn code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.76rem; }

#etAddressTable { table-layout: auto; }
.et-addr-cell { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.78rem; color: var(--ink); }

.et-addr-add { margin-top: 1.25rem; background: var(--surface); border-radius: var(--radius); padding: 0.9rem 1rem; }
.et-addr-add-title { font-size: 0.9rem; font-weight: 600; color: var(--ink); margin: 0 0 0.6rem; }
.et-addr-add-row { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.et-addr-add-row .dash-search-input { flex: 1 1 200px; min-width: 0; }
.et-addr-add-hint { font-size: 0.76rem; color: var(--ink-muted); margin: 0.6rem 0 0; line-height: 1.45; }

/* =============================================================
   Recommendation Logic editor (2026-09-03, session 3)
   Sits under the read-only explainer in Purchasing → Settings.
   Uses only real tokens (--surface, --surface-2, --radius, --accent,
   --ink*, --danger*, --success*, --warn*) so it themes with everything else.
   ============================================================= */
.pc-logic-editor { border: 1px solid var(--surface-2); border-radius: var(--radius);
  background: var(--surface); padding: 1rem 1.1rem; }
.pc-logic-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 0.85rem; }
.pc-logic-title { margin: 0; font-size: 0.98rem; }
.pc-logic-sub { margin: 0.25rem 0 0; font-size: 0.85rem; color: var(--ink-soft); max-width: 46rem; line-height: 1.5; }
.pc-logic-actions { display: flex; gap: 0.5rem; flex: 0 0 auto; }

/* The impact line — the whole point of the editor. Colour-coded by direction
   so "this will make us buy more" reads at a glance, never only from text. */
.pc-logic-impact { border-radius: var(--radius); padding: 0.6rem 0.8rem; font-size: 0.86rem;
  line-height: 1.5; margin-bottom: 1rem; border: 1px solid transparent; }
.pc-logic-impact--none { background: var(--surface-2); color: var(--ink-soft); }
.pc-logic-impact--up { background: var(--warn-soft); color: var(--warn-text); border-color: var(--warn-soft); }
.pc-logic-impact--down { background: var(--info-soft); color: var(--ink); }
.pc-logic-impact-sub { margin-top: 0.3rem; font-size: 0.78rem; opacity: 0.85; }

.pc-logic-block { border-top: 1px solid var(--surface-2); padding: 0.85rem 0 0.2rem; }
.pc-logic-block:first-of-type { border-top: none; }
.pc-logic-block-h { font-weight: 600; font-size: 0.9rem; margin-bottom: 0.6rem; color: var(--accent); }
.pc-logic-field { display: flex; align-items: baseline; gap: 0.55rem; flex-wrap: wrap; margin-bottom: 0.7rem; }
.pc-logic-field > label { flex: 0 0 9rem; font-size: 0.85rem; font-weight: 600; }
.pc-logic-field select { width: auto; }
.pc-logic-note { flex: 1 1 22rem; min-width: 0; font-size: 0.8rem; color: var(--ink-soft); line-height: 1.5; }
.pc-logic-derived { background: var(--surface-2); border-radius: var(--radius);
  padding: 0.5rem 0.7rem; font-size: 0.82rem; color: var(--ink-soft); line-height: 1.5; }

.pc-logic-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.pc-logic-table th { text-align: left; font-size: 0.76rem; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--ink-muted); padding: 0 0.5rem 0.3rem 0; font-weight: 600; }
.pc-logic-table td { padding: 0.3rem 0.5rem 0.3rem 0; border-top: 1px solid var(--surface-2); vertical-align: middle; }

/* Stage 2 top-up plan modal (2026-09-03, session 3) */
.pc-topup-verdict { border-radius: var(--radius); padding: 0.65rem 0.85rem; font-size: 0.88rem;
  line-height: 1.5; margin-bottom: 0.8rem; }
.pc-topup-verdict--ok { background: var(--success-soft); color: var(--success-text); }
.pc-topup-verdict--short { background: var(--warn-soft); color: var(--warn-text); }
.pc-topup-note { font-size: 0.82rem; color: var(--ink-soft); line-height: 1.55;
  background: var(--surface-2); border-radius: var(--radius); padding: 0.55rem 0.75rem; }

/* Per-row selection bar on each vendor accordion (2026-09-03, session 3).
   The --partial variant is the guardrail: an order covering only part of the
   recommended list must never look like a normal full order. */
.purch-selbar { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap;
  padding: 0.5rem 0.75rem; margin: 0 0 0.6rem; border-radius: var(--radius);
  background: var(--surface-2); font-size: 0.84rem; line-height: 1.5; }
.purch-selbar--partial { background: var(--warn-soft); color: var(--warn-text); }
.purch-selbar-text { flex: 1 1 22rem; min-width: 0; }

/* Per-SKU cost editor (2026-09-03, session 3) */
.pc-cost-source { padding: 0.6rem 0.8rem; border-radius: var(--radius); background: var(--info-soft);
  color: var(--ink); font-size: 0.86rem; line-height: 1.5; margin-bottom: 0.9rem; }
.pc-cost-block { border-top: 1px solid var(--surface-2); padding: 0.85rem 0 0.4rem; }
.pc-cost-block:first-of-type { border-top: none; padding-top: 0; }
.pc-cost-block-h { font-weight: 600; font-size: 0.9rem; color: var(--accent); margin-bottom: 0.4rem; }
.pc-cost-note { margin: 0.35rem 0 0; font-size: 0.8rem; color: var(--ink-soft); line-height: 1.55; }
.pc-cost-fields { display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 0.5rem; }
.pc-cost-fields label { display: flex; flex-direction: column; gap: 0.2rem;
  font-size: 0.78rem; font-weight: 600; color: var(--ink-soft); }
.pc-cost-fields input, .pc-cost-fields select { max-width: 11rem; }
.pc-cost-actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 0.7rem; flex-wrap: wrap; }

/* History "actions taken" chips (2026-09-03, session 3) — one row per PO, so
   the row itself has to carry what was done to it. */
.pc-hist-chip { display: inline-block; padding: 0.05rem 0.4rem; border-radius: 999px;
  font-size: 0.72rem; font-weight: 600; white-space: nowrap; cursor: help;
  background: var(--surface-2); color: var(--ink-soft); }
.pc-hist-chip--email { background: var(--success-soft); color: var(--success-text); }
.pc-hist-chip--st { background: var(--info-soft); color: var(--ink); }

/* =============================================================
   Sumtracker PO presence + sticky accordion footer
   (2026-09-03, session 3)
   ============================================================= */

/* "Already in Sumtracker" — on the accordion header, so it's readable while
   collapsed. That's when it matters: before you open the vendor and start
   building a second PO for an order that already exists. */
.purch-st-badge {
  display: inline-flex; align-items: center; gap: 0.25rem;
  padding: 0.1rem 0.45rem; border-radius: 999px;
  font-size: 0.72rem; font-weight: 600; white-space: nowrap; cursor: help;
  background: var(--info-soft); color: var(--ink);
}
/* The full explanation, at the top of the open accordion. */
.purch-st-strip {
  padding: 0.55rem 0.8rem; margin: 0.6rem 0 0.2rem;
  border-radius: var(--radius); background: var(--info-soft); color: var(--ink);
  font-size: 0.84rem; line-height: 1.55;
}
.purch-st-strip a { color: var(--accent); font-weight: 600; white-space: nowrap; }

/* Sticky footer: a vendor with forty SKUs shouldn't need a scroll back to the
   header to collapse. `position: sticky` works here because no ancestor of the
   accordion body sets overflow — checked, not assumed. z-index stays low so
   real modals (which sit far higher) always win. */
.purch-sticky-foot {
  position: sticky; bottom: 0; z-index: 5;
  display: flex; align-items: center; justify-content: flex-end; gap: 0.6rem;
  flex-wrap: wrap; text-align: right;
  background: var(--white);
  /* Bleed over the body's horizontal padding so the bar spans the card. */
  margin: 0.4rem -1.25rem -1.1rem; padding: 0.6rem 1.25rem;
  border-top: 1px solid var(--surface-2);
  border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
}
.purch-sticky-foot-totals { flex: 1 1 auto; text-align: left; }
.purch-collapse-btn { flex: 0 0 auto; }

/* On a narrow screen the bar stacks; keep it compact so it never eats the
   screen on mobile. */
@media (max-width: 640px) {
  .purch-sticky-foot { gap: 0.4rem; padding: 0.5rem 1rem; }
  .purch-sticky-foot-totals { flex: 1 1 100%; text-align: left; }
}

/* In-accordion row filters (2026-09-03, session 3). Deliberately styled as
   lightweight chips, NOT as the vendor-level filter pills — these are a lens on
   one vendor's rows, not a saved view, and shouldn't read as the same thing. */
.purch-rf-bar { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap;
  padding: 0.45rem 0; margin-bottom: 0.2rem; }
.purch-rf-label { font-size: 0.78rem; font-weight: 600; color: var(--ink-muted);
  text-transform: uppercase; letter-spacing: 0.03em; margin-right: 0.1rem; }
.purch-rf-group { display: inline-flex; gap: 0.25rem; padding-left: 0.35rem;
  margin-left: 0.15rem; border-left: 1px solid var(--surface-2); }
.purch-rf-chip { padding: 0.1rem 0.5rem; border-radius: 999px; cursor: pointer;
  font-size: 0.75rem; font-weight: 600; white-space: nowrap;
  background: var(--surface-2); color: var(--ink-soft);
  border: 1px solid transparent; line-height: 1.5; }
.purch-rf-chip:hover { color: var(--ink); }
.purch-rf-chip.active { background: var(--accent); color: #fff; border-color: var(--accent); }
/* Custom pill affordances (2026-09-09) */
.purch-rf-chip-edit { margin-left: 0.25rem; opacity: 0.55; font-size: 0.85em; }
.purch-rf-chip-edit:hover { opacity: 1; }
.purch-rf-chip-new { font-weight: 700; }
.purch-rf-clear { background: none; border: none; cursor: pointer; padding: 0 0.2rem;
  font-size: 0.75rem; font-weight: 600; color: var(--accent); text-decoration: underline; }
.purch-rf-count { flex: 1 1 100%; font-size: 0.76rem; color: var(--ink-muted); line-height: 1.5; }
/* On the header, so a filtered total is never unexplained from the outside. */
.purch-rf-header-chip { padding: 0.1rem 0.45rem; border-radius: 999px; cursor: help;
  font-size: 0.72rem; font-weight: 600; white-space: nowrap;
  background: var(--warn-soft); color: var(--warn-text); }

/* "This vendor has its own ordering rules" (2026-09-03, session 3). A vendor
   whose top-up behaves differently from the global settings must say so, or the
   different answer looks like a bug rather than a configuration. */
.purch-vov-badge { padding: 0.1rem 0.45rem; border-radius: 999px; cursor: help;
  font-size: 0.72rem; font-weight: 600; white-space: nowrap;
  background: var(--surface-2); color: var(--ink-soft); }

/* =============================================================
   Density pass (2026-09-03, session 3)
   The Purchasing page gained a lot of new labels in one session and started
   to feel crowded. These overrides come LAST so they win over the original
   rules above without editing them (keeping each feature's block readable).

   The principle applied throughout: anything that prevents a costly mistake
   stays prominent — the amber partial-selection bar, the top-up shortfall
   verdict. Everything informational shrinks and moves into a tooltip.
   ============================================================= */

/* Selection bar — a quiet status line, not a callout. Still turns amber and
   full-size when it's warning about a partial order. */
.purch-selbar { padding: 0.25rem 0; margin-bottom: 0.15rem; font-size: 0.78rem;
  background: none; gap: 0.5rem; }
.purch-selbar-text { color: var(--ink-muted); cursor: help; flex: 0 1 auto; }
.purch-selbar--partial { background: var(--warn-soft); color: var(--warn-text);
  padding: 0.4rem 0.7rem; border-radius: var(--radius); font-size: 0.82rem; }
.purch-selbar--partial .purch-selbar-text { color: inherit; cursor: default; }
/* The Select all / Clear buttons don't need button weight at this size. */
.purch-selbar .btn-secondary { padding: 0.1rem 0.45rem; font-size: 0.72rem; }

/* Row filter chips — tighter, and the label reads as a prefix not a heading. */
.purch-rf-bar { padding: 0.3rem 0; gap: 0.3rem; }
.purch-rf-label { font-size: 0.7rem; letter-spacing: 0.02em; cursor: help; }
.purch-rf-chip { padding: 0.05rem 0.4rem; font-size: 0.72rem; }
.purch-rf-count { flex: 0 1 auto; font-size: 0.72rem; cursor: help; }
.purch-rf-clear { font-size: 0.72rem; }

/* Sumtracker strip — one compact line; the badge on the header carries the
   at-a-glance signal, so this doesn't need to shout too. */
.purch-st-strip { padding: 0.3rem 0.6rem; margin: 0.4rem 0 0.1rem;
  font-size: 0.76rem; cursor: help; }

/* Header badges: several can appear at once (channel, readiness, committed,
   Sumtracker, own-rules, filtered, ordered). Shrink the ones this session
   added so they read as annotations on the vendor name, not as peers of it. */
.purch-st-badge, .purch-vov-badge, .purch-rf-header-chip {
  font-size: 0.68rem; padding: 0.05rem 0.38rem;
}

/* Sticky footer — slimmer, since it's permanently on screen while open. */
.purch-sticky-foot { padding: 0.45rem 1.25rem; font-size: 0.78rem; }

/* Logic editor + top-up notes: explanatory prose, so it can be smaller than
   the controls it explains. */
.pc-logic-note, .pc-cost-note, .pc-topup-note { font-size: 0.76rem; }
.pc-logic-sub { font-size: 0.8rem; }

/* Delay Orders chips — a note line can carry four of these at once. */
.pd-chip { font-size: 0.69rem; padding: 0.05rem 0.38rem; }


/* ---- Topbar search (2026-09-09 s2 follow-up — moved from home.html) ---- */
.topbar-search-wrap { position: relative; display: flex; align-items: center; margin-right: 0.6rem; }
.topbar-search-input {
  width: 150px;
  padding: 0.3rem 0.6rem 0.3rem 1.8rem;
  font-size: 0.78rem;
  font-family: var(--font-body); /* inputs don't inherit — keep it Poppins */
  border: 1px solid var(--surface-2);
  border-radius: 999px;
  /* --surface-2 exists in BOTH themes (the phantom --surface-1 this first
     shipped with doesn't, so dark mode showed the light fallback). */
  background: var(--surface-2);
  color: var(--ink);
  outline: none;
  transition: width 0.18s ease, background 0.15s ease, border-color 0.15s ease;
}
.topbar-search-input::placeholder { color: var(--ink-muted); }
.topbar-search-input:focus { width: 320px; background: var(--surface); border-color: var(--accent); }
.topbar-search-icon { position: absolute; left: 0.55rem; color: var(--ink-muted); pointer-events: none; }
.topbar-search-results {
  position: absolute; top: calc(100% + 6px); right: 0; width: 380px; max-height: 60vh; overflow-y: auto;
  background: var(--white); border: 1px solid var(--surface-2); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.12); z-index: 250; padding: 0.25rem;
}
/* While typing, the REST of the topbar steps back — the search stays full. */
.topbar--searching .topbar-left,
.topbar--searching .growth-toggle-wrap,
.topbar--searching .topbar-right > *:not(.topbar-search-wrap) {
  opacity: 0.25;
  transition: opacity 0.15s ease;
}
.topbar-left, .growth-toggle-wrap, .topbar-right > * { transition: opacity 0.15s ease; }

/* Tight screens (2026-09-24): the bar needs ~880px as-is and ran off the
   right edge below that, taking the ☰ button with it. Two trims: the
   version badge keeps "V610" but drops its date, and the closed search is
   just its magnifier icon. Focused, the search grows leftward OVER the bar
   (absolute) instead of pushing it wider, the same "steps back while you
   type" idea as .topbar--searching above. */
@media (max-width: 900px) {
  .topbar-version-date { display: none; }
  .topbar-search-wrap { width: 30px; height: 30px; }
  .topbar-search-input {
    position: absolute;
    right: 0;
    top: 0;
    width: 30px;
    height: 30px;
    padding: 0;
    border-color: transparent;
    background: transparent;
    cursor: pointer;
  }
  .topbar-search-input::placeholder { color: transparent; }
  .topbar-search-icon { left: 8px; }
  .topbar-search-input:focus {
    width: min(320px, calc(100vw - 2rem));
    padding: 0.3rem 0.6rem 0.3rem 1.8rem;
    cursor: text;
    z-index: 1;
  }
  .topbar-search-input:focus::placeholder { color: var(--ink-muted); }
  /* Icon stays with the input's left edge once it has grown. */
  .topbar-search-wrap:focus-within .topbar-search-icon { left: auto; right: calc(min(320px, 100vw - 2rem) - 1.35rem); z-index: 2; }
  .topbar-search-results { width: min(380px, calc(100vw - 2rem)); }
}

/* Live clock under the section date (2026-09-09 s2 follow-up, revised same
   session): its own line, so the date sits exactly where the Ops header always
   put it, and a fixed-width tabular block so the ticking seconds can't shift
   the line (right-aligned text otherwise re-flows on every digit change). */
.home-clock {
  display: block;
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
  min-width: 9ch;
  text-align: right;
}

/* ── Purchasing: in-accordion catalog search (2026-09-10) ──
   Dark-mode fix same day: this originally used phantom variables
   (--card-bg / --border, which don't exist → fell back to hardcoded light
   values) and a body.dark-mode selector (the portal's dark mode is
   html.theme-dark flipping the VARIABLES). White rows with light ink in
   dark mode — Dylan's screenshot. Now built on --white / --surface-2 /
   --ink / --ink-muted, which flip on their own; no dark selector needed. */
.purch-acc-search { margin: 0.5rem 0 0.75rem; position: relative; }
.purch-acc-search-input {
  width: 100%; max-width: 520px; padding: 0.45rem 0.7rem;
  border: 1px solid var(--surface-2); border-radius: 8px;
  font: inherit; background: var(--white); color: var(--ink);
}
.purch-acc-search-input:focus { outline: none; border-color: #d01d5a; }
.purch-acc-search-results { max-width: 680px; }
.purch-acc-search-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.45rem 0.6rem; border: 1px solid var(--surface-2); border-top: none;
  background: var(--white); color: var(--ink); font-size: 0.85rem;
}
.purch-acc-search-row:first-child { border-top: 1px solid var(--surface-2); border-radius: 8px 8px 0 0; }
.purch-acc-search-row:last-child { border-radius: 0 0 8px 8px; }
.purch-acc-search-main { min-width: 0; }
.purch-acc-search-meta { color: var(--ink-muted); margin-left: 0.5rem; white-space: nowrap; }
.purch-acc-search-action { display: flex; align-items: center; gap: 0.4rem; flex-shrink: 0; }
.purch-acc-search-qty { width: 4.2rem; padding: 0.3rem 0.4rem; border: 1px solid var(--surface-2); border-radius: 6px; font: inherit; background: var(--white); color: var(--ink); }
.purch-acc-search-note { color: var(--ink-muted); font-size: 0.8rem; white-space: nowrap; }
.purch-acc-search-empty { padding: 0.5rem 0.6rem; color: var(--ink-muted); font-size: 0.85rem; }

/* ── Purchasing: History accordions + PO revision (2026-09-10) ── */
.pc-hist-card { margin-bottom: 0.6rem; }
.pc-hist-ref { color: var(--ink-muted, #8a8478); font-size: 0.85rem; }
.pc-hist-status { font-size: 0.72rem; padding: 0.1rem 0.5rem; border-radius: 999px; background: #eee; color: #555; white-space: nowrap; }
.pc-hist-status--2 { background: #f2efe9; color: #7a7468; }
.pc-hist-status--3 { background: #e4f0fb; color: #2a6db5; }
.pc-hist-status--4 { background: #e3f4e6; color: #2c7a3f; }
.pc-hist-status--5 { background: #fbe7e7; color: #b03a3a; }
.pc-hist-status--partial { background: #fdf3dc; color: #9a7318; }
.pc-hist-status--stale { background: #f2efe9; color: #8a8478; }
.pc-hist-rev { font-size: 0.72rem; padding: 0.1rem 0.45rem; border-radius: 999px; background: #f3e8fd; color: #7b3fbf; }
.pc-hist-body { padding: 0.75rem 1rem 1rem; border-top: 1px solid var(--surface-2); }
.pc-hist-events { margin-bottom: 0.75rem; }
.pc-hist-event { font-size: 0.85rem; padding: 0.15rem 0; color: var(--ink-soft, #55504a); }
.pc-hist-loading { font-size: 0.82rem; color: var(--ink-muted, #8a8478); margin: 0.4rem 0; }
.pc-hist-photo { width: 30px; height: 30px; object-fit: contain; border-radius: 4px; background: #fff; border: 1px solid #eee; }
.pc-hist-photo--none { display: inline-block; width: 30px; text-align: center; color: #ccc; }
.pc-hist-recv { font-size: 0.78rem; color: var(--ink-muted, #8a8478); white-space: nowrap; }
.pc-hist-recv--full { color: #2c7a3f; }
.pc-hist-recv--part { color: #9a7318; font-weight: 600; }
.pc-hist-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.9rem; }
.pc-rev-box { max-width: 900px; width: 94vw; }
.pc-rev-body { padding: 0.75rem 1.25rem 1.1rem; }
.pc-rev-sub { font-size: 0.85rem; color: var(--ink-soft, #55504a); margin: 0 0 0.75rem; }
.pc-rev-input { padding: 0.3rem 0.4rem; border: 1px solid var(--surface-2); border-radius: 6px; font: inherit; width: 100%; background: var(--white); color: var(--ink); }
.pc-rev-input--num { width: 5.5rem; text-align: right; }
.pc-rev-input--sku { width: 9rem; }
.pc-rev-row--removed td { opacity: 0.45; text-decoration: line-through; }
.pc-rev-row--changed td { background: var(--warn-soft, #fdf7e8); }
.pc-rev-badge { font-size: 0.68rem; padding: 0.05rem 0.4rem; border-radius: 999px; white-space: nowrap; }
.pc-rev-badge--custom { background: #fdf3dc; color: #9a7318; }
.pc-rev-badge--new { background: #e3f4e6; color: #2c7a3f; }
.pc-rev-recv { font-size: 0.72rem; color: #9a7318; white-space: nowrap; margin-left: 0.3rem; }
.pc-rev-add { display: flex; gap: 0.6rem; align-items: flex-start; margin: 0.8rem 0; }
.pc-rev-foot { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.6rem; }
.pc-rev-totals { font-size: 0.85rem; color: var(--ink-soft, #55504a); font-weight: 600; }
.pd-chip--ordered { background: var(--surface-2); color: var(--ink-soft); } /* grey like .pd-chip--ok (2026-10-13) */

/* ── 2026-09-10 round 2: icon-first accordion search + compact history ── */
.purch-acc-search--icon { margin: 0.35rem 0 0.5rem; }
.purch-acc-search-btn { font-size: 0.8rem; }
.pc-hist-card .purch-accordion-header { padding: 0.45rem 0.9rem; min-height: 0; }
.pc-hist-card .im-vendor-card-name { font-size: 0.92rem; }
.pc-hist-card .purch-accordion-header-totals { font-size: 0.8rem; }
.pc-hist-card { margin-bottom: 0.4rem; }
/* #pcHistSearch bespoke grow-on-focus retired 2026-09-15 s1 — the bar now uses
   .dash-search-input like every other search bar (Sue's ask). Width cap kept
   so the toolbar's date inputs still fit on one row. */
#pcHistSearch { max-width: 260px; }

/* ── 2026-09-10 round 3: tab popouts, MAX-cap advisory, delay on-order ── */
.pc-tab-popout { display: none; margin-left: 0.35rem; font-size: 0.75rem; text-decoration: none; color: inherit; opacity: 0.7; }
.toggle-btn:hover .pc-tab-popout { display: inline; }
.pc-tab-popout:hover { opacity: 1; }
.delay-onorder { color: var(--success, #2c7a3f); font-weight: 600; }
html.theme-dark .delay-onorder { color: #6fd18a; }

/* revise modal sizing on top of .modal-card (2026-09-10 fix; widened same day —
   long product titles forced horizontal scrolling past the edit controls) */
.pc-rev-box { max-width: min(1280px, 96vw); width: 96vw; max-height: 90vh; }
.pc-rev-table { width: 100%; table-layout: fixed; }
/* Columns: photo · SKU · Supplier SKU · Product · Qty · Unit cost · Total ·
   actions. Only the product column flexes. (The photo column was added after
   the first widths were written, which shifted every rule one column left and
   squeezed the product title under the inputs — Sue, 2026-10-05; the editable
   Supplier SKU column came 2026-10-07.) */
.pc-rev-table th:nth-child(1), .pc-rev-table td:nth-child(1) { width: 44px; }
.pc-rev-table th:nth-child(2), .pc-rev-table td:nth-child(2) { width: 120px; white-space: normal; overflow-wrap: anywhere; }
.pc-rev-table th:nth-child(3), .pc-rev-table td:nth-child(3) { width: 140px; }
.pc-rev-table th:nth-child(4), .pc-rev-table td:nth-child(4) { width: auto; }
.pc-rev-table td:nth-child(4) { white-space: normal; overflow-wrap: anywhere; }
.pc-rev-table th:nth-child(5), .pc-rev-table td:nth-child(5) { width: 90px; }
.pc-rev-table th:nth-child(6), .pc-rev-table td:nth-child(6) { width: 110px; }
.pc-rev-table th:nth-child(7), .pc-rev-table td:nth-child(7) { width: 110px; white-space: nowrap; }
.pc-rev-table th:nth-child(8), .pc-rev-table td:nth-child(8) { width: 96px; white-space: nowrap; }
.pc-rev-input--sup.missing { border-color: var(--warn); background: var(--warn-soft); }
.pc-rev-input--num { width: 100%; max-width: 6rem; }

/* dark-mode variants for the 2026-09-10 chips (light pastels wash out on dark) */
html.theme-dark .pc-hist-status--2 { background: #2a2a38; color: #b6b6cf; }
html.theme-dark .pc-hist-status--3 { background: #14283d; color: #7db4e8; }
html.theme-dark .pc-hist-status--4 { background: #143621; color: #7fd196; }
html.theme-dark .pc-hist-status--5 { background: #3a1616; color: #e89090; }
html.theme-dark .pc-hist-status--partial { background: #3d2e10; color: #e3bd6a; }
html.theme-dark .pc-hist-status--stale { background: #2a2a38; color: #9494b3; }
html.theme-dark .pc-hist-rev { background: #2c1f3d; color: #c39aef; }
html.theme-dark .pc-rev-badge--custom { background: #3d2e10; color: #e3bd6a; }
html.theme-dark .pc-rev-badge--new { background: #143621; color: #7fd196; }
html.theme-dark .pc-hist-photo { background: #262636; border-color: #34344a; }

/* ---- Edit OrderStatus note fields (2026-09-10 s2) ----
   Replaces the inline ui-monospace styling on the two note textareas —
   Dylan's ask: wider modal + friendlier text. Portal font, comfortable
   line height, generous padding, and a real focus state. The preview box
   shares the same reading rhythm so what-you-type matches what-they-see. */
.pc-oe-note {
  width: 100%;
  box-sizing: border-box;
  font-family: inherit;            /* Poppins, same as the rest of the portal */
  font-size: 0.875rem;
  line-height: 1.6;
  letter-spacing: 0.005em;
  padding: 0.7rem 0.85rem;
  color: var(--ink);
  background: var(--surface-2, rgba(0,0,0,0.03));
  border: 1px solid var(--border, #ccc);
  border-radius: 8px;
  resize: vertical;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.pc-oe-note:focus {
  outline: none;
  border-color: var(--accent, #1cd5ff);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #1cd5ff) 18%, transparent);
}
.pc-oe-preview {
  border: 1px solid var(--border, #ccc);
  border-radius: 8px;
  padding: 0.7rem 0.85rem;
  background: var(--surface-2, rgba(0,0,0,0.03));
  font-size: 0.875rem;
  line-height: 1.6;
}

/* ---- Shared cell label (layout round 2, 2026-09-10 s2): one style for every
   small metric/field label — Min, Max, Net, Avail, Sumtr, Inc. ---- */
.purch-cell-label {
  font-size: 0.62rem; color: var(--ink-muted);
  text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600;
}
/* Brand-tinted labels on the Ordering row's comparable availability pair
   (2026-09-10 s3, Dylan): Shopify green / Sumtracker blue — labels only;
   the values keep the shared neutral/negative treatment. */
.purch-lbl-shopify    { color: #95BF47; }
.purch-lbl-sumtracker { color: #1b55d2; }

/* ---- Net stat block: the row's primary metric — label over value, matching
   the Min/Max field pattern, tinted by sign. ---- */
.purch-net-stat {
  display: flex; flex-direction: column; align-items: center; gap: 0.05rem;
  padding: 0.22rem 0.5rem; border-radius: 8px; cursor: help;
  border: 1px solid transparent;
}
.purch-net-value {
  font-size: 1.02rem; font-weight: 800; line-height: 1.1;
  font-variant-numeric: tabular-nums; letter-spacing: 0.01em;
}
.purch-net--neg  { background: var(--danger-soft); border-color: color-mix(in srgb, var(--danger-text) 35%, transparent); }
.purch-net--neg .purch-net-value  { color: var(--danger-text); }
.purch-net--zero { background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn-text) 35%, transparent); }
.purch-net--zero .purch-net-value { color: var(--warn-text); }
.purch-net--pos  { background: var(--success-soft, var(--surface-2)); border-color: color-mix(in srgb, var(--success-text, var(--ink-soft)) 30%, transparent); }
.purch-net--pos .purch-net-value  { color: var(--success-text, var(--ink-soft)); }

/* ---- Net metrics column (layout cleanup, 2026-09-10 s2): primary net tag
   with the secondary numbers in a quiet, aligned label/value grid below. ---- */
.purch-item-net {
  flex-shrink: 0;
  display: flex; flex-direction: column; align-items: stretch; gap: 0.3rem;
}
.purch-metrics { display: flex; flex-direction: column; gap: 0.12rem; padding: 0 0.15rem; }
.purch-metric {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 0.4rem; font-size: 0.72rem; line-height: 1.25; cursor: help;
}
.purch-metric-v { font-weight: 600; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.purch-metric-neg { color: var(--danger-text); }
.purch-metric-inc { color: var(--ok-text, #157f4f); }

/* ---- Custom order lines (Sue, 2026-09-10 s2) ---- */
.purch-custom-wrap { padding: 0.5rem 0 0.2rem; border-top: 1px dashed var(--surface-2); margin-top: 0.4rem; }
.purch-custom-head { font-size: 0.78rem; font-weight: 600; color: var(--ink-soft); margin-bottom: 0.35rem; }
.purch-custom-row {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.3rem 0; font-size: 0.82rem;
}
.purch-custom-title { flex: 1; min-width: 0; }
.purch-custom-qty  { width: 4.2rem; font-size: 0.78rem; text-align: center; padding: 0.1rem 0.2rem; border: 1px solid var(--surface-2); border-radius: 4px; background: var(--white); color: var(--ink); }
.purch-custom-cost { width: 5.4rem; font-size: 0.78rem; text-align: right; padding: 0.1rem 0.3rem; border: 1px solid var(--surface-2); border-radius: 4px; background: var(--white); color: var(--ink); }
.purch-custom-total { min-width: 4.5rem; text-align: right; font-weight: 600; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.purch-custom-mismatch {
  font-size: 0.68rem; font-weight: 600; padding: 0.05rem 0.35rem; border-radius: 4px;
  background: var(--warn-soft); color: var(--warn-text); cursor: help; margin-left: 0.3rem;
}
.purch-custom-note {
  font-size: 0.66rem; color: var(--ink-muted); border: 1px solid var(--surface-2);
  border-radius: 4px; padding: 0 0.3rem; cursor: help; margin-left: 0.3rem;
}

/* ---- Shopify tags + note on Delay Orders cards (Sue, 2026-09-10 s2) ---- */
.pd-tags { display: inline-flex; flex-wrap: wrap; gap: 0.25rem; align-items: center; max-width: 30rem; }
.pd-tag {
  font-size: 0.62rem; color: var(--ink-muted); border: 1px solid var(--surface-2);
  border-radius: 4px; padding: 0 0.3rem; line-height: 1.35; cursor: help; white-space: nowrap;
}
.pd-tag--priority {
  color: var(--danger-text); background: var(--danger-soft);
  border-color: color-mix(in srgb, var(--danger-text) 45%, transparent);
  font-weight: 700; font-size: 0.66rem;
}
.pd-note-block--shopify .pd-shopify-note {
  font-size: 0.78rem; color: var(--ink-soft); white-space: pre-wrap; word-break: break-word;
}

.pd-tags--below { margin-top: 0.35rem; max-width: none; }

/* ---- Unified slim dropdowns on Purchasing (Dylan, 2026-09-11 s2) ----
   The browser-default <select> chrome (screenshotted: "All vendors" /
   "Any status") clashed with the portal's rounded, token-driven surfaces.
   One shared class, applied per-select (never a bare `select` rule — other
   pages' dropdowns must not shift under this change). Colors are all tokens
   so dark mode works, EXCEPT the chevron: background-image url() can't read
   CSS variables, so light/dark each get an explicitly-colored SVG below. */
select.pc-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background-color: var(--white);
  color: var(--ink);
  border: 1px solid var(--surface-2);
  border-radius: 8px;
  font: inherit;
  font-size: 0.82rem;
  line-height: 1.25;
  padding: 0.32rem 1.7rem 0.32rem 0.6rem;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23767686' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.55rem center;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  max-width: 100%;
}
select.pc-select:hover { border-color: var(--accent); }
select.pc-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.theme-dark select.pc-select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23a7a7b8' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Order-meta strip under the public notes (2026-09-11 s3) */
.pd-order-meta { display:flex; align-items:center; gap:0.75rem; margin-top:0.6rem; padding-top:0.5rem; border-top:1px solid color-mix(in srgb, var(--ink-muted) 18%, transparent); font-size:0.8rem; color:var(--ink-muted); }
.pd-note-label { display:flex; align-items:center; gap:0.5rem; }

/* Shopify note & tags editor (2026-09-11 s3) — the raw inputs looked like a
   terminal paste. Same visual language as the note blocks they edit. */
.pd-shopify-edit-note {
  width: 100%;
  font-family: inherit;
  font-size: 0.9rem;
  line-height: 1.55;
  padding: 0.65rem 0.8rem;
  background: var(--surface-2);
  border: 1px solid color-mix(in srgb, var(--ink-muted) 25%, transparent);
  border-radius: var(--radius-md, 10px);
  resize: vertical;
  min-height: 9rem;
  white-space: pre;      /* note lines are line-oriented (the buy list) — don't rewrap them */
  overflow-x: auto;
}
.pd-shopify-edit-note:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.pd-shopify-edit-tags {
  width: 100%;
  font-family: inherit;
  font-size: 0.88rem;
  padding: 0.5rem 0.8rem;
  background: var(--surface-2);
  border: 1px solid color-mix(in srgb, var(--ink-muted) 25%, transparent);
  border-radius: var(--radius-md, 10px);
}
.pd-shopify-edit-tags:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }

/* Manual line-item search results (Draft Order tool, 2026-09-15 s1) */
.do-manual-result { display: flex; align-items: center; gap: 0.7rem; width: 100%; text-align: left;
  background: var(--white); border: 1px solid var(--surface-2); border-radius: var(--radius);
  padding: 0.5rem 0.7rem; margin-bottom: 0.4rem; cursor: pointer; }
.do-manual-result:hover { background: var(--surface); border-color: var(--accent); }
.do-manual-result img, .do-manual-result-noimg { width: 44px; height: 44px; border-radius: 6px;
  object-fit: cover; background: var(--surface-2); flex: 0 0 44px; display: block; }
.do-manual-result-main { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.do-manual-result-title { font-size: 0.88rem; color: var(--ink); }
.do-manual-result-sub { font-size: 0.76rem; color: var(--ink-muted); }


/* ===== Inventory Monitor card list (2026-09-15 s2 revamp) =====
   Flat per-SKU rows stealing the Purchasing item-row look (photo / status /
   main / Min-Max reuse the purch-* classes directly); the stat blocks echo
   .purch-net-stat's label-over-value pattern. */
.im-mon-list { margin-top: 0.85rem; }
.im-mon-row {
  display: flex; align-items: center; gap: 0.9rem;
  padding: 0.6rem 0.4rem; border-top: 1px solid var(--surface-2);
}
.im-mon-row:first-child { border-top: none; }
.im-mon-status {
  flex-shrink: 0; width: 4.4rem; display: flex; align-items: center;
  gap: 0.35rem; justify-content: flex-start;
}
.im-mon-abc { font-weight: 700; font-size: 1rem; cursor: help; }
.im-mon-vendor { font-size: 0.75rem; color: var(--ink-soft); margin-top: 0.15rem; }
.im-mon-stat {
  flex-shrink: 0; min-width: 4.2rem; display: flex; flex-direction: column;
  align-items: center; gap: 0.1rem; text-align: center;
}
.im-mon-stat-v { font-weight: 700; font-size: 1rem; color: var(--ink); }
.im-mon-stat-val { font-size: 0.9rem; }
.im-mon-unit { font-size: 0.7rem; font-weight: 400; color: var(--ink-muted); margin-left: 0.1rem; }
.im-mon-stat.purch-net--neg .im-mon-stat-v { color: var(--danger); }
.im-mon-stat.purch-net--zero .im-mon-stat-v { color: var(--warn); }
.im-mon-stat.purch-net--pos .im-mon-stat-v { color: var(--success-text); }
/* Resume jump highlight — a soft pulse so the row is findable, then gone. */
@keyframes imResumeFlash {
  0% { background: color-mix(in srgb, var(--accent) 22%, transparent); }
  100% { background: transparent; }
}
.im-resume-flash { animation: imResumeFlash 2.4s ease-out 1; border-radius: 8px; }
@media (max-width: 900px) {
  .im-mon-row { flex-wrap: wrap; }
  .im-mon-stat { min-width: 3.4rem; }
}

/* Reviewed marks on the Monitor cards (2026-09-15 s2, Sue's bulk-pass flow) */
.im-mon-reviewcol {
  flex-shrink: 0; width: 2.1rem; display: flex; flex-direction: column;
  align-items: center; gap: 0.1rem;
}
.im-mon-review {
  width: 1.55rem; height: 1.55rem; border-radius: 50%;
  border: 1.5px solid var(--surface-2); background: var(--white);
  color: var(--ink-muted); font-size: 0.85rem; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.im-mon-review:hover { border-color: var(--accent); color: var(--accent); }
.im-mon-review.is-reviewed {
  background: var(--success-text); border-color: var(--success-text); color: var(--white);
}
.im-mon-review-age { font-size: 0.6rem; color: var(--ink-muted); white-space: nowrap; }
/* Reviewed rows recede without disappearing — still readable, clearly done. */
.im-mon-row--reviewed { opacity: 0.62; }
.im-mon-row--reviewed:hover { opacity: 1; }

/* =====================================================================
   Hazel — draft-reply card + Missive label chips (Phase 2, 2026-09-16 s5)
   =====================================================================
   The draft card is deliberately NOT a chat bubble: what's inside it is
   the only text in the conversation meant to leave the portal, so it
   reads as a distinct object with its own copy affordance rather than as
   one more thing Hazel said. Built from the existing surface tokens, so
   it follows theme-dark with no separate dark rules. */
.hz-draft-card {
  align-self: stretch;
  width: 100%;
  border: 1.5px solid var(--accent);
  border-radius: 12px;
  background: var(--white);
  overflow: hidden;
  margin: 0.25rem 0;
}
.hz-draft-head {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  padding: 0.45rem 0.75rem;
  background: var(--accent-soft);
  border-bottom: 1px solid var(--surface-2);
}
.hz-draft-label { font-size: 0.76rem; font-weight: 600; color: var(--accent-dark); }
.hz-draft-copy { display: inline-flex; align-items: center; gap: 0.3rem; }
.hz-draft-body {
  padding: 0.7rem 0.85rem;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--ink);
  /* Rendered by bwReplyHtml (escape-first: **bold** and "* "/"- " bullets
     only), the same rules the Worker uses in Missive — so the card shows what
     the Missive draft will look like. Copy gives the clean text. */
  white-space: pre-wrap;
  word-break: break-word;
}
.hz-draft-body ul { margin: 0.2rem 0 0.2rem 1.2rem; padding: 0; white-space: normal; }

/* Label picker — this agent's Missive read scope, straight from
   agent_registry, as ONE line (it was a chip per label; 29 chips filled half
   the chat). Picking one prefills the input rather than firing a request, so
   the user still chooses to ask. */
.hz-label-chips {
  padding: 0.4rem 1.25rem 0;
}
.hz-label-select {
  width: 100%;
  font-size: 0.78rem; padding: 0.25rem 0.4rem;
  border: 1px solid var(--surface-2); border-radius: 5px;
  background: var(--surface); color: var(--ink-soft);
  cursor: pointer;
}
.hz-label-select:hover, .hz-label-select:focus { border-color: var(--accent); }
.hz-label-empty { font-size: 0.72rem; color: var(--ink-soft); opacity: 0.8; }

/* ---- Hazel's Shopify order panel (2026-09-17 s3) ----------------------------
   The panel itself reuses the .cs-order-* rules left behind by the retired
   Customer Service page — they were deliberately kept in place when that page
   was removed in Phase A, for exactly this. Only the two-column shell and the
   embed-mode suppression are new.

   HIDDEN IN EMBED MODE ON PURPOSE (Dylan, s3). The chat widget runs at roughly
   380px; a side panel there would squeeze the conversation into a gutter. In
   the widget Hazel offers a "Come to my office" button instead, which opens her
   full page where the panel has room. */
.hz-chat-split {
  display: flex;
  gap: 1.1rem;
  align-items: stretch;
}
.hz-chat-split > .chat-container { flex: 1 1 auto; min-width: 0; }
.hz-order-panel { flex: 0 0 300px; }

/* Below the two-column breakpoint the panel drops under the chat rather than
   squeezing it — same threshold the rest of the portal's split layouts use. */
@media (max-width: 1100px) {
  .hz-chat-split { flex-direction: column; }
  .hz-order-panel { flex: 1 1 auto; height: auto; min-height: 0; max-height: 420px; }
}

.embed-mode .hz-order-panel { display: none; }
.embed-mode .hz-chat-split { display: block; }

/* Every agent office uses the whole screen width (Sue, 2026-10-06: "see
   more text during a chat"; Hazel first, then "change all agents"). The
   shared .advisor-layout boxes the content into a 900px middle column; with
   .agent-office-layout the chat grows to fill (Hazel's order panel sits to
   its right) and the side tabs stay at the right edge. Same override shape
   as .zipp-office-pane--chat; the docked widget (embed mode) is untouched. */
/* Easier to read (Sue, 2026-10-07): the side tabs became a small row of
   buttons above the chat, so the chat gets that width too; the tab you are
   on is hidden when it is Chat (the row then shows only where you can go,
   e.g. "Manage Documents"), and "Chat" appears to come back. The chat sits
   in a white card instead of on the grey page. */
html:not(.embed-mode) .agent-office-layout { grid-template-columns: minmax(0, 1fr); gap: 0.4rem; padding-top: 0.6rem; }
html:not(.embed-mode) .agent-office-layout .advisor-content { grid-column: 1; grid-row: 2; }
html:not(.embed-mode) .agent-office-layout .advisor-tabs {
  grid-column: 1; grid-row: 1; justify-self: end;
  flex-direction: row; flex-wrap: wrap; width: auto; position: static; gap: 0.35rem; min-height: 1.6rem;
}
html:not(.embed-mode) .agent-office-layout .advisor-tab { padding: 0.2rem 0.7rem; font-size: 0.76rem; background: var(--white); border-color: var(--surface-2); }
html:not(.embed-mode) .agent-office-layout .advisor-tab.active { background: var(--accent-soft); border-color: var(--accent); }
html:not(.embed-mode) .agent-office-layout .advisor-tab.active[data-tab="chat"] { display: none; }
html:not(.embed-mode) .agent-office-layout .advisor-chat-container {
  height: calc(100vh - 150px);
  background: var(--white);
  border: 1px solid var(--surface-2);
  border-radius: var(--radius-lg);
}
html:not(.embed-mode) .agent-office-layout .advisor-chat-container .chat-header { border-bottom: 1px solid var(--surface-2); }
html:not(.embed-mode) .agent-office-layout .advisor-chat-container .chat-input-wrap { border-top: 1px solid var(--surface-2); }
html:not(.embed-mode) .agent-office-layout .chat-messages { background: var(--white); }

/* The "Come to my office" invitation, shown only inside the widget. */
.hz-office-invite {
  display: inline-flex; align-items: center; gap: 0.4rem;
  margin-top: 0.5rem;
}

/* Guest note on a shared agent's chat bar — a second admin reading someone
   else's thread. Only ever rendered when chat_scope = 'admins'. */
.agent-chat-guest-note {
  font-size: 0.72rem; color: var(--ink-muted); white-space: nowrap;
  padding: 0.15rem 0.45rem; background: var(--surface-2); border-radius: 999px;
}

/* Author tag on a message in a SHARED agent chat (chat_scope = 'admins').
   Never rendered in a private chat — see agentChatAuthorLabel(). Two people in
   one thread need their turns told apart; one person does not. */
.chat-author-tag {
  font-size: 0.68rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--ink-muted); margin-bottom: 0.2rem;
}

/* Full-size preview of an agent's photo, for users without settings access. */
.agent-avatar-preview-overlay {
  position: fixed; inset: 0; z-index: 9000; background: rgba(0,0,0,0.6);
  display: flex; align-items: center; justify-content: center; cursor: zoom-out;
}
.agent-avatar-preview-overlay img {
  max-width: min(420px, 86vw); max-height: 70vh; border-radius: 12px;
  box-shadow: 0 10px 40px rgba(0,0,0,0.4);
}

/* =============================================================================
   Agent Memory Manager modal (2026-09-18 s2, js/agent-memory-modal.js)
   Extra-wide variant of the shared .modal-card. Everything derives from theme
   variables so dark mode follows for free — the real tokens are --white/--ink
   (see the 2026-09-18 s1 lesson: --card-bg does not exist).
   ============================================================================= */
.amm-card {
  max-width: min(1400px, 96vw);
  width: 100%;
  height: min(90vh, 900px);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden; /* the body scrolls, not the card */
}

.amm-header { flex: 0 0 auto; }

.amm-filters {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex-wrap: wrap;
  padding: 0.7rem 1.5rem 0.35rem;
}

.amm-toolbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.35rem 1.5rem 0.6rem;
  border-bottom: 1px solid var(--surface-2);
}

.amm-count { font-size: 0.76rem; color: var(--ink-muted); }

.amm-bulk {
  flex: 0 0 auto;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.5rem 1.5rem;
  background: var(--surface-2);
}

.amm-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0.4rem 1.5rem 1.2rem;
}

.amm-input {
  font-size: 0.78rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--pd-card-border, #d6d3e6);
  border-radius: 6px;
  background: var(--white);
  color: var(--ink);
  font-family: inherit;
}

.amm-q { flex: 1 1 220px; min-width: 160px; }

.amm-datelabel {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.74rem;
  color: var(--ink-muted);
}

.amm-row {
  display: flex;
  gap: 0.5rem;
  align-items: flex-start;
  padding: 0.55rem 0;
  border-top: 1px solid var(--pd-card-border, #e4e0da);
}
.amm-row:first-child { border-top: none; }
.amm-row--rejected { opacity: 0.62; }

.amm-content {
  width: 100%;
  font-size: 0.83rem;
  font-family: inherit;
  background: var(--white);
  color: var(--ink);
  border: 1px solid var(--pd-card-border, #d6d3e6);
  border-radius: 6px;
  padding: 0.35rem 0.45rem;
}
.amm-content:disabled { background: var(--surface); color: var(--ink-muted); }

.amm-rowmeta {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 0.3rem;
}
.amm-rowmeta select { font-size: 0.75rem; }

.amm-badge {
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.12rem 0.45rem;
  border-radius: 8px;
}
.amm-badge--active   { background: var(--success-soft, #dcfce7); color: var(--success-text, #15803d); }
.amm-badge--pending  { background: var(--warn-soft, #fef3c7);    color: var(--warn-text, #92400e); }
.amm-badge--rejected { background: var(--surface-2);             color: var(--ink-muted); }

/* Narrow screens: the filter row stacks and the card takes the viewport. */
@media (max-width: 720px) {
  .amm-card { height: 96vh; max-height: 96vh; max-width: 100vw; border-radius: 0; }
  .amm-filters, .amm-toolbar, .amm-bulk, .amm-body { padding-left: 0.8rem; padding-right: 0.8rem; }
  .amm-q { flex-basis: 100%; }
}

/* Report-a-bug / change-request modal inputs (2026-09-18 s3) — there is no
   generic portal input class; these mirror .purch-settings-field's inputs. */
.cr-input {
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--text-primary);
  font: inherit;
  font-size: 0.9rem;
  margin-top: 0.25rem;
  display: block;
}
.cr-input:focus { outline: none; border-color: var(--primary); }
#crFormModal label { font-size: 0.85rem; color: var(--text-secondary); display: block; }

/* =============================================
   EMAIL MAP (pages/email-map.html, js/email-map.js) — added 2026-10-01
   Everything is emap- prefixed and token-driven, so dark mode follows the
   html.theme-dark variable flip with no extra rules. The diagram is SVG
   styled from here (fill/stroke via classes), for the same reason.
   ============================================= */
.toast.warning { border-left: 4px solid var(--warn); }

.emap-syncbar { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.emap-sync-status { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; color: var(--ink-soft); }
.emap-sync-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--success); flex-shrink: 0; }
.emap-sync-dot--warn { background: var(--warn); }
.emap-sync-dot--error { background: var(--danger); }
.emap-sync-warning { background: var(--warn-soft); color: var(--ink); border-left: 4px solid var(--warn); border-radius: var(--radius); padding: 0.6rem 0.9rem; font-size: 0.85rem; margin-bottom: 0.75rem; }
.emap-sync-warning--error { background: var(--danger-soft); border-left-color: var(--danger); }

.emap-toolbar { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin: 0.5rem 0 0.75rem; }
.emap-toolbar-spacer { flex: 1; }
.emap-tabs { display: inline-flex; background: var(--surface-2); border-radius: 999px; padding: 3px; }
.emap-tab { border: none; background: none; padding: 0.35rem 0.9rem; border-radius: 999px; font: inherit; font-size: 0.82rem; color: var(--ink-soft); cursor: pointer; }
.emap-tab.active { background: var(--white); color: var(--ink); font-weight: 600; box-shadow: var(--shadow); }
.emap-status-chips { display: inline-flex; gap: 0.3rem; flex-wrap: wrap; }
.emap-chip { border: 1.5px solid var(--surface-2); background: var(--white); color: var(--ink-muted); border-radius: 999px; padding: 0.25rem 0.7rem; font: inherit; font-size: 0.78rem; cursor: pointer; }
.emap-chip.active { border-color: var(--accent); background: var(--accent-soft); color: var(--ink); }
.emap-search { width: 240px; margin-top: 0; }

.emap-input { width: 100%; padding: 0.5rem 0.75rem; border: 1.5px solid var(--surface-2); border-radius: var(--radius); font-family: var(--font-body); font-size: 0.85rem; color: var(--ink); background: var(--surface); margin: 0.25rem 0 0.5rem; box-sizing: border-box; }
.emap-input:focus { outline: none; border-color: var(--accent); background: var(--white); }
.emap-textarea { min-height: 70px; resize: vertical; }
.emap-html-input { min-height: 140px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.75rem; }
.emap-full { width: 100%; }
.emap-muted { color: var(--ink-muted); font-size: 0.8rem; }
.emap-error-text { color: var(--danger-text-strong); font-size: 0.82rem; margin: 0.5rem 0; }
.emap-row-end { display: flex; align-items: center; gap: 0.5rem; justify-content: flex-end; margin-top: 0.75rem; }
.emap-form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.6rem; }

.emap-canvas-bar { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.4rem; min-height: 1.6rem; }
.emap-zoom { display: inline-flex; gap: 0.25rem; }
.emap-canvas { position: relative; overflow: hidden; height: 68vh; min-height: 420px; background: var(--surface); border: 1px solid var(--surface-2); border-radius: var(--radius-lg); cursor: grab; touch-action: none; }
.emap-canvas.dragging { cursor: grabbing; }
.emap-canvas--chain { height: 60vh; }
.emap-viewport { position: absolute; top: 0; left: 0; transform-origin: 0 0; }

.emap-lanes { display: flex; gap: 14px; align-items: flex-start; padding: 4px; }
.emap-lane { width: 250px; flex-shrink: 0; background: var(--surface-2); border-radius: var(--radius); padding: 8px; }
.emap-lane-head { display: flex; justify-content: space-between; align-items: center; font-weight: 600; font-size: 0.85rem; color: var(--ink); padding: 4px 6px 8px; }
.emap-lane-count { background: var(--white); color: var(--ink-muted); border-radius: 999px; padding: 0 8px; font-size: 0.75rem; font-weight: 500; }
.emap-lane-body { display: flex; flex-direction: column; gap: 8px; }
.emap-lane-empty { color: var(--ink-muted); font-size: 0.8rem; padding: 10px 6px; text-align: center; }
.emap-chain-empty { padding: 40px; }
.emap-chain-card { display: flex; flex-direction: column; gap: 4px; text-align: left; width: 100%; background: var(--white); border: 1.5px solid var(--pd-card-border); border-radius: var(--radius); padding: 10px 12px; font: inherit; color: var(--ink); cursor: pointer; box-shadow: var(--shadow); }
.emap-chain-card:hover { border-color: var(--accent); }
.emap-chain-card--removed { opacity: 0.7; border-style: dashed; }
.emap-chain-card-top { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.emap-chain-card-name { font-weight: 600; font-size: 0.9rem; line-height: 1.25; }
.emap-chain-card-meta { font-size: 0.78rem; color: var(--ink-soft); }
.emap-chain-card-trigger { font-size: 0.75rem; color: var(--ink-muted); }
.emap-chain-card-source { font-size: 0.7rem; color: var(--ink-muted); border-top: 1px solid var(--surface-2); padding-top: 4px; margin-top: 2px; }
.emap-system { font-size: 0.72rem; color: var(--ink-muted); }

.emap-pill { display: inline-block; font-size: 0.68rem; font-weight: 600; border-radius: 999px; padding: 1px 8px; background: var(--low-soft); color: var(--ink-soft); white-space: nowrap; }
.emap-pill--live { background: var(--success-soft); color: var(--success-text); }
.emap-pill--planned { background: var(--info-badge-bg); color: var(--info-badge-text); }
.emap-pill--manual { background: var(--warn-soft); color: var(--warn-text-alt); }
.emap-pill--removed { background: var(--danger-soft); color: var(--danger-text-alt); }

.emap-chain-head { display: flex; align-items: flex-start; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.emap-chain-title { flex: 1; min-width: 220px; }
.emap-chain-title h2 { font-size: 1.15rem; margin: 0 0 0.25rem; color: var(--ink); }
.emap-chain-sub { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.emap-chain-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.emap-chain-actions a { text-decoration: none; }
.emap-banner { background: var(--surface-2); color: var(--ink); border-radius: var(--radius); padding: 0.5rem 0.8rem; font-size: 0.83rem; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.emap-banner--warn { background: var(--warn-soft); }

.emap-svg { display: block; font-family: var(--font-body); }
.emap-link { fill: none; stroke: var(--ink-muted); stroke-width: 1.6; }
.emap-link--back { stroke-dasharray: 5 4; }
.emap-arrow { fill: var(--ink-muted); }
.emap-link-label rect { fill: var(--white); stroke: var(--surface-2); }
.emap-link-label text { fill: var(--ink-soft); font-size: 11px; font-weight: 600; }
.emap-node { cursor: pointer; }
.emap-node rect { fill: var(--white); stroke: var(--pd-card-border); stroke-width: 1.5; }
.emap-node:hover rect, .emap-node:focus rect { stroke: var(--accent); outline: none; }
.emap-node:focus { outline: none; }
.emap-node--trigger rect { fill: var(--accent-soft); stroke: var(--accent); }
.emap-node--email rect, .emap-node--ab_test rect { stroke-width: 2; }
.emap-node--delay rect { fill: var(--surface-2); stroke: var(--surface-2); }
.emap-node--conditional_split rect, .emap-node--trigger_split rect, .emap-node--multi_branch_split rect { fill: var(--info-badge-bg); stroke: var(--info-badge-text); }
.emap-node--exit rect { fill: var(--low-soft); stroke-dasharray: 4 3; }
.emap-node--other rect, .emap-node--sms rect { stroke-dasharray: 4 3; }
.emap-node-kind { fill: var(--ink-muted); font-size: 10px; font-weight: 600; letter-spacing: 0.04em; }
.emap-node-name { fill: var(--ink); font-size: 13px; font-weight: 600; }
.emap-node-sub { fill: var(--ink-soft); font-size: 11px; }

.emap-info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 0.75rem; margin-top: 0.75rem; }
.emap-info-card { background: var(--white); border: 1px solid var(--surface-2); border-radius: var(--radius); padding: 0.9rem 1rem; box-shadow: var(--shadow); }
.emap-info-card h3 { font-size: 0.85rem; margin: 0 0 0.35rem; color: var(--ink); }
.emap-info-card p { font-size: 0.85rem; margin: 0 0 0.6rem; color: var(--ink-soft); }
.emap-info-card details { margin-bottom: 0.5rem; font-size: 0.8rem; }
.emap-pre { white-space: pre-wrap; word-break: break-word; font-size: 0.72rem; background: var(--surface); border-radius: 8px; padding: 0.6rem; max-height: 280px; overflow: auto; color: var(--ink-soft); }
.emap-log { margin: 0; padding-left: 1.1rem; font-size: 0.82rem; color: var(--ink-soft); }
.emap-log li { margin-bottom: 0.3rem; }

.emap-table .emap-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.emap-row { cursor: pointer; }
.emap-row--hidden td { opacity: 0.65; }
.emap-linkbtn { background: none; border: none; padding: 0; font: inherit; color: var(--accent); cursor: pointer; text-align: left; }
.emap-linkbtn:hover { text-decoration: underline; }

/* 180: above the sticky topbar (170) so the panel's own header shows, below modals (200). */
.emap-detail { position: fixed; top: 0; right: 0; height: 100vh; width: min(560px, 100vw); background: var(--white); box-shadow: var(--shadow-lg); z-index: 180; transform: translateX(105%); transition: transform 0.2s ease; display: flex; flex-direction: column; }
.emap-detail.open { transform: translateX(0); }
.emap-detail-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 1rem 1.25rem; border-bottom: 1px solid var(--surface-2); }
.emap-detail-body { padding: 1rem 1.25rem 2rem; overflow-y: auto; flex: 1; }
.emap-detail-meta { font-size: 0.82rem; color: var(--ink-soft); margin-bottom: 0.75rem; }
.emap-detail-h { font-size: 0.9rem; margin: 1rem 0 0.4rem; color: var(--ink); }
.emap-detail-links { display: flex; gap: 0.4rem; flex-wrap: wrap; margin: 0.6rem 0; }
.emap-detail-links a { text-decoration: none; }
.emap-dl { display: grid; grid-template-columns: 110px 1fr; gap: 0.35rem 0.75rem; margin: 0; font-size: 0.85rem; }
.emap-dl dt { color: var(--ink-muted); }
.emap-dl dd { margin: 0; color: var(--ink); word-break: break-word; }
.emap-preview-wrap { border: 1px solid var(--surface-2); border-radius: var(--radius); overflow: hidden; background: var(--surface); min-height: 60px; padding: 0; }
.emap-preview-wrap > .emap-muted, .emap-preview-wrap > .emap-error-text { padding: 0.75rem; display: block; }
.emap-preview { width: 100%; height: 70vh; border: 0; display: block; background: #ffffff; }

.emap-modal-wide { max-width: 760px; max-height: 88vh; }
.emap-step-edit { border: 1px solid var(--surface-2); border-radius: var(--radius); padding: 0.6rem 0.75rem; margin-bottom: 0.6rem; background: var(--surface); }
.emap-step-edit-head { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.3rem; }
.emap-step-num { width: 22px; height: 22px; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-size: 0.75rem; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.emap-step-type-fixed { font-weight: 600; font-size: 0.85rem; color: var(--ink); }
.emap-html-box { margin: 0.2rem 0 0.4rem; font-size: 0.8rem; }
.emap-add-steps { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; margin: 0.25rem 0 0.5rem; }
.emap-stage-row { display: flex; align-items: center; gap: 0.4rem; }
.emap-stage-row .emap-input { flex: 1; }
.emap-stage-fixed { white-space: nowrap; }

@media (max-width: 700px) {
  .emap-search { width: 100%; }
  .emap-canvas { height: 60vh; }
}

/* Email Map: where each email comes from (2026-10-01). One colour per sender,
   matching its app icon (assets/*-icon.png). Klaviyo's mark is black, so its
   colour follows --ink and stays visible in dark mode. */
:root {
  --emap-src-klaviyo: var(--ink);
  --emap-src-shopify: #95bf47;
  --emap-src-stoq: #7d24ae;
  --emap-src-orderstatus: #cb2524;
  --emap-src-other: var(--ink-muted);
}
.emap-src-icon { width: 18px; height: 18px; border-radius: 4px; object-fit: contain; vertical-align: middle; flex-shrink: 0; background: #ffffff; }
.emap-src-icon--lg { width: 24px; height: 24px; margin-right: 0.45rem; vertical-align: -4px; }
.emap-detail-meta .emap-src-icon { margin-right: 0.3rem; }
.emap-system-cell { white-space: nowrap; }
.emap-system-cell .emap-src-icon { margin-right: 0.4rem; }
.emap-chain-card.emap-src--klaviyo { border-left: 4px solid var(--emap-src-klaviyo); }
.emap-chain-card.emap-src--shopify { border-left: 4px solid var(--emap-src-shopify); }
.emap-chain-card.emap-src--stoq { border-left: 4px solid var(--emap-src-stoq); }
.emap-chain-card.emap-src--orderstatus { border-left: 4px solid var(--emap-src-orderstatus); }
.emap-chain-card.emap-src--other { border-left: 4px solid var(--emap-src-other); }
.emap-row.emap-src--klaviyo td:first-child { box-shadow: inset 4px 0 0 var(--emap-src-klaviyo); }
.emap-row.emap-src--shopify td:first-child { box-shadow: inset 4px 0 0 var(--emap-src-shopify); }
.emap-row.emap-src--stoq td:first-child { box-shadow: inset 4px 0 0 var(--emap-src-stoq); }
.emap-row.emap-src--orderstatus td:first-child { box-shadow: inset 4px 0 0 var(--emap-src-orderstatus); }
.emap-row.emap-src--other td:first-child { box-shadow: inset 4px 0 0 var(--emap-src-other); }
.emap-node rect.emap-src-fill--klaviyo { fill: var(--emap-src-klaviyo); }
.emap-node rect.emap-src-fill--shopify { fill: var(--emap-src-shopify); }
.emap-node rect.emap-src-fill--stoq { fill: var(--emap-src-stoq); }
.emap-node rect.emap-src-fill--orderstatus { fill: var(--emap-src-orderstatus); }
.emap-node rect.emap-src-fill--other { fill: var(--emap-src-other); }
.emap-node rect.emap-node-stripe { stroke: none; }
/* Email Map: "Sends Day N" under each email node, and the table's Sends column. */
.emap-node-day { fill: var(--ink-soft); font-size: 11px; font-weight: 600; }
.emap-nowrap { white-space: nowrap; }
/* Email Map numbers (part 2, 2026-10-01): range bar, card-face metrics,
   badges (status colours + ⚠ icon + text, never colour alone), stat tiles,
   trend charts (one series each), Compare. */
.emap-rangebar { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.35rem; }
.emap-rangebar .inv-sku-label { margin: 0; }
.emap-range-custom { display: inline-flex; align-items: center; gap: 0.35rem; }
.emap-date { width: auto; margin: 0; }
.emap-metrics-status { font-size: 0.8rem; min-height: 1.2rem; margin-bottom: 0.4rem; }
.emap-warn-text { color: var(--warn-text-alt); font-size: 0.8rem; }
.emap-low { opacity: 0.55; }
.emap-num { white-space: nowrap; text-align: right; font-variant-numeric: tabular-nums; }
.emap-node-metric { fill: var(--ink); font-size: 12.5px; font-weight: 600; }
.emap-node-delta { font-size: 11px; font-weight: 600; }
.emap-node-delta--good { fill: var(--success-text); }
.emap-node-delta--bad { fill: var(--danger-text-alt); }
.emap-node-delta--neutral { fill: var(--ink-muted); }
.emap-node-through { fill: var(--ink-soft); font-size: 11px; font-weight: 600; }
.emap-node .emap-node-badge rect { stroke: none; }
.emap-node .emap-node-badge--amber rect { fill: var(--warn-soft); }
.emap-node .emap-node-badge--red rect { fill: var(--danger-soft); }
.emap-node-badge text { font-size: 10px; font-weight: 600; fill: var(--ink); }
.emap-node-badge--low { opacity: 0.6; }
.emap-badges { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.emap-badge { display: inline-block; font-size: 0.72rem; font-weight: 600; border-radius: 999px; padding: 2px 9px; color: var(--ink); white-space: nowrap; }
.emap-badge--amber { background: var(--warn-soft); }
.emap-badge--red { background: var(--danger-soft); }
.emap-badge--low { opacity: 0.6; }
.emap-chain-card-metric { font-size: 0.78rem; color: var(--ink-soft); }
.emap-chain-card-manual { font-size: 0.75rem; color: var(--ink-soft); }
.emap-chain-card .emap-badge { align-self: flex-start; }
.emap-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.5rem; margin: 0.4rem 0 0.6rem; }
.emap-tile { background: var(--surface); border-radius: var(--radius); padding: 0.55rem 0.7rem; }
.emap-tile-label { font-size: 0.72rem; color: var(--ink-muted); }
.emap-tile-value { font-size: 1.05rem; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.emap-tile-note { font-size: 0.68rem; color: var(--ink-muted); margin-top: 0.15rem; }
.emap-delta { font-size: 0.75rem; font-weight: 600; }
.emap-delta--good { color: var(--success-text); }
.emap-delta--bad { color: var(--danger-text-alt); }
.emap-delta--neutral { color: var(--ink-muted); }
.emap-info-card--wide { grid-column: 1 / -1; }
.emap-trend { display: flex; flex-direction: column; gap: 0.75rem; }
.emap-chart-title { font-size: 0.8rem; font-weight: 600; color: var(--ink); margin-bottom: 0.2rem; }
.emap-chart-wrap { position: relative; }
.emap-chart-svg { width: 100%; height: auto; display: block; font-family: var(--font-body); }
.emap-chart-svg:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
.emap-chart-axis { stroke: var(--surface-2); stroke-width: 1; }
.emap-chart-tick { fill: var(--ink-muted); font-size: 10px; }
.emap-chart-line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.emap-chart-dot { fill: var(--accent); stroke: var(--white); stroke-width: 2; }
.emap-chart-dot--low { opacity: 0.5; }
.emap-chart-cross { stroke: var(--ink-muted); stroke-width: 1; }
.emap-chart-hit { fill: transparent; cursor: crosshair; }
.emap-chart-tip { position: absolute; top: 0; transform: translateX(-50%); background: var(--white); border: 1px solid var(--surface-2); box-shadow: var(--shadow); border-radius: 8px; padding: 0.2rem 0.5rem; font-size: 0.75rem; color: var(--ink-soft); white-space: nowrap; pointer-events: none; }
.emap-chart-tip strong { color: var(--ink); }
.emap-chart-table { font-size: 0.75rem; margin-top: 0.25rem; }
.emap-modal-xwide { max-width: 1100px; max-height: 90vh; }
.emap-compare-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin: 0.6rem 0; }
.emap-compare-cols .emap-preview { height: 60vh; }
.emap-compare-head { background: var(--surface); border-radius: var(--radius); padding: 0.6rem 0.8rem; }
@media (max-width: 700px) { .emap-compare-cols { grid-template-columns: 1fr; } }

/* Segmentation page (2026-10-07): engine switch, count check, segments, health. */
.sgm-section { background: var(--white); border-radius: var(--radius); box-shadow: var(--shadow); padding: 1.25rem 1.5rem; margin-bottom: 1.25rem; }
.sgm-title { font-size: 1.05rem; font-weight: 600; color: var(--ink); margin: 0 0 0.5rem; }
.sgm-subtitle { font-size: 0.9rem; font-weight: 600; color: var(--ink); margin: 1.1rem 0 0.5rem; }
.sgm-note { color: var(--ink-soft); font-size: 0.85rem; margin: 0 0 0.75rem; }
.sgm-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.9rem; }
.sgm-kv { font-size: 0.85rem; color: var(--ink-soft); margin: 0.3rem 0; }
.sgm-k { display: inline-block; min-width: 9.5rem; font-weight: 600; color: var(--ink); }
.sgm-muted { color: var(--ink-muted); font-size: 0.82rem; margin: 0.4rem 0; }
.sgm-pass { color: var(--success-text); font-weight: 600; }
.sgm-check { color: var(--danger-text-alt); font-weight: 600; }
.sgm-warn { color: var(--warn-text); font-weight: 600; }
.sgm-tag { display: inline-block; font-size: 0.7rem; padding: 0.05rem 0.45rem; border-radius: 999px; background: var(--surface-2); color: var(--ink-soft); margin-left: 0.25rem; }
.sgm-error { margin: 0.5rem 0; }
.sgm-table-wrap { margin: 0.5rem 0 0.75rem; }
.sgm-table td { white-space: normal; }
.sgm-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1rem; margin: 0.5rem 0 0.75rem; }
.sgm-control { display: flex; align-items: center; gap: 0.4rem; font-size: 0.85rem; font-weight: 600; color: var(--ink); }
.sgm-check-label { display: flex; align-items: center; gap: 0.35rem; font-size: 0.85rem; color: var(--ink-soft); cursor: pointer; }
.sgm-pager { align-items: center; }
.sgm-pager-info { font-size: 0.82rem; color: var(--ink-muted); }
.sgm-fired { font-size: 0.78rem; color: var(--ink-soft); }

/* ===== Pick Lists (pages/pick-lists.html, js/pick-lists.js) — added 2026-10-14 =====
   Screen: the order list. Print: only #pkPrintArea, one .pk-sheet per printed
   page. Print colours are fixed black-on-white (not theme tokens) so a
   dark-mode browser still prints a readable sheet. */
.pk-toolbar { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.pk-count { font-size: 0.85rem; font-weight: 600; color: var(--ink); }
.pk-status { font-size: 0.82rem; color: var(--ink-soft); margin-bottom: 0.75rem; }
.pk-check-col { width: 36px; }
.pk-num { text-align: right; white-space: nowrap; }
.pk-empty { text-align: center; color: var(--ink-muted); padding: 1.5rem; }
.pk-sort-btn { background: none; border: none; font: inherit; color: inherit; cursor: pointer; padding: 0; text-transform: inherit; letter-spacing: inherit; }
.pk-badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 0.72rem; font-weight: 600; white-space: nowrap; }
.pk-badge--paid { background: var(--success-soft); color: var(--success-text); }
.pk-badge--due { background: var(--warn-soft); color: var(--warn-text); }
.pk-badge--unfulfilled { background: var(--info-badge-bg); color: var(--info-badge-text); }
.pk-badge--partial { background: var(--warn-soft); color: var(--warn-text); }
.pk-badge--hold { background: var(--danger-soft); color: var(--danger-text); }
.pk-badge--picked { background: var(--surface-2); color: var(--ink-soft); margin-left: 6px; }
.pk-opt { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.85rem; color: var(--ink-soft); cursor: pointer; }
.pk-badge--pickup { background: var(--danger-text-strong); color: var(--white); }
.pk-ship { font-size: 0.82rem; color: var(--ink-soft); }
.pk-ship--none { color: var(--ink-muted); font-style: italic; }
.pk-oos-icon { display: inline-flex; vertical-align: middle; margin-left: 6px; color: var(--warn-text-alt); cursor: help; }
.pk-order-link { color: var(--ink); font-weight: 600; text-decoration: none; }
.pk-order-link:hover { text-decoration: underline; }
.pk-lookup { display: flex; gap: 0.5rem; max-width: 640px; margin-bottom: 0.5rem; }
.pk-lookup .dash-search-input { flex: 1; }
.pk-lookup-result { max-width: 900px; margin-bottom: 1rem; background: var(--white); border: 1px solid var(--warn-border-alt); border-radius: var(--radius); padding: 0.6rem 0.75rem; }
.pk-lookup-result:empty { display: none; }
.pk-lk-item { display: flex; gap: 0.75rem; align-items: flex-start; background: var(--surface); border-radius: var(--radius); padding: 0.6rem 0.75rem; margin-bottom: 0.4rem; }
.pk-lk-sub { margin-left: 1.5rem; background: var(--surface-2); }
.pk-lk-img { width: 64px; height: 64px; object-fit: contain; flex-shrink: 0; background: var(--white); border-radius: 6px; }
.pk-lk-noimg { display: flex; align-items: center; justify-content: center; font-size: 0.7rem; color: var(--ink-muted); }
.pk-lk-title { font-weight: 600; color: var(--ink); }
.pk-lk-meta { font-size: 0.82rem; color: var(--ink-soft); }
.pk-lk-order { font-size: 0.82rem; color: var(--success-text); background: var(--white); border: 1px solid var(--success-border-soft); display: inline-block; padding: 1px 6px; border-radius: 4px; margin-top: 2px; }
.pk-lk-subhead { font-size: 0.78rem; font-weight: 600; text-transform: uppercase; color: var(--ink-muted); margin: 0.5rem 0 0.3rem 1.5rem; }
.pk-lk-notes { margin: 0 0 0.4rem 1.5rem; font-size: 0.82rem; background: var(--white); border-left: 3px solid var(--warn-border-alt); color: var(--ink); padding: 0.3rem 0.6rem; border-radius: 6px; }
.pk-lk-state { font-size: 0.82rem; color: var(--ink-soft); margin: 0.3rem 0 0.3rem 1.5rem; }
.pk-lk-warn { color: var(--danger-text); }
.pk-lk-list { display: flex; flex-direction: column; gap: 0.25rem; margin-left: 1.5rem; }
.pk-lk-pick { text-align: left; background: var(--surface); border: 1px solid var(--surface-2); border-radius: 6px; padding: 0.35rem 0.6rem; font: inherit; font-size: 0.82rem; color: var(--ink); cursor: pointer; }
.pk-lk-pick:hover { border-color: var(--ink-muted); }
#pkPrintArea { display: none; }

@media print {
  /* Colours copied from the Order Printer template (Sue, 2026-10-14). */
  @page { margin: 10mm; }
  body.pk-page { background: #fff !important; padding: 0 !important; }
  body.pk-page > *:not(#pkPrintArea) { display: none !important; }
  body.pk-page #pkPrintArea { display: block; color: #000; font-family: var(--font-body); font-size: 13px; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .pk-sheet { break-after: page; page-break-after: always; }
  .pk-sheet:last-child { break-after: auto; page-break-after: auto; }
  .pk-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
  .pk-head-left { flex: 1; min-width: 0; }
  .pk-head-right { text-align: right; flex: 0 1 auto; max-width: 45%; min-width: 0; }
  .pk-ctype { overflow-wrap: anywhere; }
  .pk-order-no { font-size: 32px; font-weight: 700; }
  .pk-dest { font-size: 26px; font-weight: 700; color: blue; margin-left: 12px; }
  .pk-po { font-size: 18px; font-weight: 700; }
  .pk-barcode { display: block; margin-left: auto; }
  .pk-utm { font-size: 8px; margin-top: 6px; }
  #pkPrintArea * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .pk-hl { background: yellow !important; }
  .pk-grey { color: grey; }
  .pk-pink { color: #d01d5a; }
  .pk-red { color: red; }
  .pk-blue { color: blue; }
  .pk-purple { color: #6a1b9a; overflow-wrap: anywhere; }
  .pk-bold { font-weight: 700; }
  .pk-big { font-size: 15px; }
  .pk-mid { font-size: 13px; }
  .pk-small { font-size: 11px; }
  .pk-tiny { font-size: 9px; }
  .pk-pickup { color: red; font-size: 18px; font-weight: 700; }
  .pk-outstanding { border: 1px solid red; padding: 8px; margin: 4px 0; color: red; font-size: 13px; font-weight: 700; }
  .pk-risk { border: 2px solid red; color: red; padding: 4px 8px; margin: 6px 0; font-weight: 700; }
  .pk-risk--unknown { border-style: dashed; }
  .pk-rule { border: 0; border-top: 2px solid #000; margin: 8px 0; }
  .pk-notes-row { display: flex; gap: 16px; padding: 0 20px 0 40px; }
  .pk-notes-left { flex: 1; }
  .pk-notes-right { width: 40%; text-align: right; }
  .pk-note { font-size: 13px; }
  .pk-note-line { white-space: pre-wrap; }
  .pk-note-oos { font-weight: 400; }
  .pk-sub { margin: 2px 0 6px 16px; padding-left: 8px; border-left: 2px solid #000; font-size: 10px; color: #000; }
  .pk-sub-state { font-style: italic; }
  .pk-sub-notes { background: none; }
  .pk-warn { font-style: italic; }
  .pk-lines { width: 100%; border-collapse: collapse; margin: 8px 0 1.5em; border: 1px solid grey; }
  .pk-lines th { color: grey; text-align: left; }
  .pk-lines th, .pk-lines td { border: 1px solid #eee; padding: 4px; vertical-align: top; }
  .pk-lines tr { break-inside: avoid; page-break-inside: avoid; }
  .pk-qty { font-size: 15px; }
  .pk-thumb { width: 50px; height: 50px; object-fit: contain; display: block; }
  .pk-thumb--none { font-size: 9px; color: grey; }
  .pk-li-title { font-size: 11px; }
  .pk-li-sku { font-size: 11px; }
  .pk-green { color: #0a7a2f; }
  .pk-stock-comp + .pk-stock-comp { margin-top: 1px; }
  .pk-kit { margin-top: 2px; font-size: 9px; line-height: 1.35; }
  .pk-kit-head { font-weight: 700; }
  .pk-slip { font-size: 11px; }
  .pk-slip-title { text-align: center; font-size: 20px; font-weight: 700; margin: 0 0 6px; }
  .pk-slip-top { display: flex; justify-content: space-between; align-items: flex-start; }
  .pk-slip-logo { width: 16em; max-width: 50%; }
  .pk-slip .pk-po { font-size: 16px; }
  .pk-slip .pk-thumb { width: 36px; height: 36px; }
  .pk-slip-po { text-align: right; }
  .pk-slip-cols { display: flex; gap: 24px; margin-top: 1.5em; }
  .pk-slip-cols > div { flex: 1; }
  .pk-slip-rule { border: 0; border-top: 1px solid #000; margin: 14px 0; }
  .pk-slip-h2 { font-size: 14px; font-weight: 700; margin: 0; }
  .pk-slip-table { width: 100%; border-collapse: collapse; margin-top: 1em; }
  .pk-slip-table th, .pk-slip-table td { text-align: left; padding: 2px 4px; border-bottom: 1px solid #ddd; vertical-align: middle; }
  .pk-slip-table th:first-child { width: 60px; }
  .pk-slip-table th:nth-child(2) { width: 50px; }
  .pk-slip-foot { text-align: center; max-width: 70%; margin: 1.5em auto 0; border: 3px solid #d01d5a; border-radius: 8px; padding: 8px 14px; }
  .pk-slip-foot h1 { font-size: 16px; font-weight: 700; color: #d01d5a; margin: 0 0 4px; }
  .pk-slip-foot p { margin: 0; font-size: 12px; }
  .pk-totals { border-collapse: collapse; margin: 0 0 1.5em; border: 1px solid #eee; font-size: 10px; }
  .pk-totals td { border: 1px solid #eee; padding: 2px 6px; }
}

/* ---- Demo login form ---- */
.demo-login-form { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; text-align: left; }
.demo-login-form label { font-size: 13px; font-weight: 500; color: var(--ink); }
.demo-login-form input { padding: 10px 12px; border: 1px solid var(--border, #d6d3cc); border-radius: 8px; font: inherit; background: var(--surface); color: var(--ink); }
.demo-login-btn { margin-top: 10px; padding: 11px 14px; border-radius: 8px; }
.demo-login-error { color: #b42318; font-size: 13px; margin: 4px 0 0; }

/* ---- Demo Settings page ---- */
.ds-card { background: var(--surface); border-radius: 14px; padding: 22px 24px; margin-bottom: 18px; box-shadow: 0 1px 3px rgba(0,0,0,.06); }
.ds-card h2 { margin: 0 0 6px; font-size: 18px; }
.ds-note { color: var(--ink-soft, #6b6880); font-size: 13px; margin: 0 0 12px; }
.ds-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 10px 0 14px; }
.ds-actions .ds-note { margin: 0; }
.ds-pages { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px 22px; }
.ds-cat h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft, #6b6880); margin: 6px 0 6px; }
.ds-row { display: flex; gap: 10px; align-items: flex-start; padding: 6px 0; cursor: pointer; }
.ds-row input { margin-top: 3px; }
.ds-row span { display: flex; flex-direction: column; }
.ds-row small { color: var(--ink-soft, #6b6880); font-size: 12px; line-height: 1.35; }
.ds-label { display: block; font-size: 13px; font-weight: 500; margin: 10px 0 4px; }
.ds-input { width: 100%; max-width: 420px; padding: 9px 11px; border-radius: 8px; border: 1px solid #d6d3cc; background: var(--surface); color: var(--ink); font: inherit; }
.ds-danger { color: #b42318; }
.ds-grid-wrap { overflow: auto; max-height: 520px; border: 1px solid #e4e2dc; border-radius: 10px; }
.ds-grid { border-collapse: collapse; width: 100%; font-size: 13px; }
.ds-grid th { position: sticky; top: 0; background: var(--surface-2, #f3f2ef); text-align: left; padding: 8px 10px; font-weight: 600; text-transform: capitalize; white-space: nowrap; }
.ds-grid td { border-top: 1px solid #eeece7; padding: 6px 10px; white-space: nowrap; max-width: 260px; overflow: hidden; text-overflow: ellipsis; }
.ds-grid td[contenteditable]:focus { outline: 2px solid var(--accent, #15805c); background: var(--surface); white-space: normal; }
.ds-del { border: 0; background: none; color: #b42318; cursor: pointer; }
.ds-upload { cursor: pointer; display: inline-flex; align-items: center; }

/* ---- Demo Setup page ---- */
.dsu-toc { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.dsu-toc a { font-size: 13px; padding: 6px 12px; border-radius: 999px; background: var(--surface); color: var(--ink); text-decoration: none; box-shadow: 0 1px 2px rgba(0,0,0,.06); }
.dsu-btn { display: inline-block; margin: 6px 6px 0 0; padding: 7px 14px; border-radius: 8px; background: var(--accent, #d01d5a); color: #fff !important; font-size: 13px; font-weight: 500; text-decoration: none; white-space: nowrap; }
.dsu-btn--ghost { background: var(--surface-2, #f3f2ef); color: var(--ink) !important; }
.dsu-table { width: 100%; border-collapse: collapse; font-size: 14px; margin: 10px 0; }
.dsu-table th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft, #6b6880); padding: 6px 8px; }
.dsu-table td { border-top: 1px solid #eeece7; padding: 10px 8px; vertical-align: top; }
.dsu-table td:last-child { white-space: nowrap; text-align: right; }
#what p, #data p, #pages p, #people p, #agents p, #stack p, #help p, .ds-card ol, .ds-card ul { line-height: 1.55; }
.ds-card code { background: var(--surface-2, #f3f2ef); padding: 1px 5px; border-radius: 4px; font-size: 12.5px; }
