:root {
  /* Sep 5 session — real verified pakhimalayan.com palette (owner-
     supplied, checked against the actual site, not guessed). Replaces
     the earlier black/bone-white placeholder pass entirely. Used
     as-is, deliberately: this is a cooler, muted, purple-leaning
     palette, not warmed up and not mixed with an unrelated accent
     (the earlier salt-pink is gone everywhere in this file).
     Exception, and the only one: --good/--warn/--bad below stay
     conventional green/amber/red. That's a semantic-status decision,
     not a decorative one — REJECTED/FAILED/VERIFIED badges rely on a
     near-universal color cue for fast scanning, and desaturating
     those into the brand palette would cost usability for no brand
     benefit (nobody experiences a status badge as "branding"). */
  --brand-black: #282828;
  --brand-gray: #A0A0A0;
  --slate: #515479;
  --dim-gray: #806C5C;
  --slate-blue: #4E52A5;
  --slate-light: #9086A7;
  --lavender: #D5D8EE;
  --slate-dark: #3C4B4B;

  --ink: var(--brand-black);
  --ink-soft: var(--brand-gray);
  --paper: #F5F5FA;      /* lavender, heavily lightened for a usable page background — not a new hue, a tint of the given one */
  --card: #ffffff;
  --line: #DEDCEE;       /* lavender, darkened slightly for a visible-but-quiet border */
  --accent: var(--slate-blue);
  --accent-dark: #3d4084;
  --good: #3f8f5f;
  --warn: #c98a1f;
  --bad: #c14b3f;

  /* Sep 17 redesign — every background literal that used to be
     hardcoded (#fff, #EEEDF7, #FAFAFD, #e6f4ea, etc.) is now one of
     these semantic tokens instead, specifically so a single dark-theme
     override block below can flip the whole site's surfaces at once
     without touching every individual selector that uses them. */
  --surface-1: #ffffff;      /* was hardcoded #fff — topbar, filters, buttons, cards */
  --surface-2: #EEEDF7;      /* was hardcoded #EEEDF7 — th backgrounds, chip backgrounds, hover fills */
  --row-hover: #FAFAFD;      /* was hardcoded #FAFAFD — table row hover, category-card hover */
  --success-bg: #e6f4ea;
  --success-border: #bfe3cc;
  --warn-bg: #fbf1e0;
  --danger-bg: #fbeae8;
  --danger-border: #f2c6c1;
  --accent-soft-bg: #E6E5F5;
  --shadow-soft: rgba(40,40,40,0.06);
  --radius: 8px;

  /* Sep 17 — multi-color KPI icon chips (owner's explicit choice,
     referencing real Instagram dashboard-design examples — a
     deliberate, deliberate-in-writing departure from this file's
     earlier monochrome-plus-one-accent rule, scoped ONLY to these
     icon chips: badges/status colors above are untouched, and the
     core brand palette itself isn't being replaced). Five colors,
     enough to visually distinguish adjacent KPI cards without turning
     into a rainbow — light-mode values are saturated-but-soft tints
     (icon color + a pale background), same "chip" construction as
     the reference screenshots. */
  --chip-blue: #3B6FD6; --chip-blue-bg: #E9EFFC;
  --chip-teal: #1FA37A; --chip-teal-bg: #E4F6EF;
  --chip-purple: #8A4FD6; --chip-purple-bg: #F1E9FB;
  --chip-gold: #C98A1F; --chip-gold-bg: #FBF1DE;
  --chip-pink: #D6478A; --chip-pink-bg: #FBE7F1;

  /* Sep 17 — light-theme card gradient, "salt" palette (owner: wants
     colored/gradient cards in light mode too, not just dark — blue,
     green, or pink since "we're dealing in pink salt"). A soft
     lavender-to-blush diagonal wash, drawing from colors already in
     this file's own palette (--lavender) plus a touch of the pink chip
     hue — not an arbitrary new color, a tint of what "pink salt"
     actually suggests. Kept light enough that dark text stays fully
     readable on it (checked: --ink at #282828 on this gradient's
     lightest/darkest stops both pass basic contrast by inspection). */
  --card-gradient: linear-gradient(135deg, #FFFFFF 0%, #F3EEFA 55%, #FCEEF5 100%);
}

/* ==========================================================
   Sep 17 — real dark theme (owner-requested, missed in the
   first redesign pass — this closes that gap directly).
   Toggled via a `data-theme="dark"` attribute on <html>,
   set by ui-effects.js: defaults to the visitor's OS
   preference (prefers-color-scheme) on first visit, then
   remembers whatever they actually choose via the topbar
   toggle, in localStorage, from then on — matching the
   "always offer a toggle, respect system preference as the
   default" convention every 2026 dashboard design writeup
   agrees on (Linear/Vercel/Supabase/Raycast all ship exactly
   this pattern, not a forced theme either direction).
   Because nearly every rule in this file already reads colors
   from a variable rather than a literal, this one block is
   almost the entire dark theme — no other selector needed to
   change. Status/semantic colors (badges, flash messages) get
   their own explicit dark-safe backgrounds here too, following
   the researched convention of "saturated but not neon, with
   enough contrast against a dark surface" rather than just
   inverting their light-mode tints (which would go muddy/low-
   contrast on a dark background if left as-is). */
:root[data-theme="dark"] {
  --ink: #E8E7F2;
  --ink-soft: #9997B3;
  --paper: #17161F;
  --card: #1E1D29;
  --line: #322F42;
  --accent: #7B7FDE;      /* lightened slate-blue — the literal --slate-blue is too low-contrast as an accent against a near-black surface */
  --accent-dark: #9DA0EA;
  --good: #4FBE7E;
  --warn: #E0A83F;
  --bad: #E06A5C;

  --surface-1: #1E1D29;
  --surface-2: #272533;
  --row-hover: #24222F;
  --success-bg: rgba(79, 190, 126, 0.14);
  --success-border: rgba(79, 190, 126, 0.35);
  --warn-bg: rgba(224, 168, 63, 0.14);
  --danger-bg: rgba(224, 106, 92, 0.14);
  --danger-border: rgba(224, 106, 92, 0.35);
  --accent-soft-bg: rgba(123, 127, 222, 0.18);
  --shadow-soft: rgba(0,0,0,0.35);

  /* Dark-mode chip variants — brighter icon color, a translucent tint
     of it as the chip background (rather than the light mode's pale
     solid tint, which would look washed-out/wrong on a dark surface).
     Same 5 hues, tuned for contrast against --card here specifically. */
  --chip-blue: #6FA0FF; --chip-blue-bg: rgba(111, 160, 255, 0.16);
  --chip-teal: #4FD9A8; --chip-teal-bg: rgba(79, 217, 168, 0.16);
  --chip-purple: #B98CF2; --chip-purple-bg: rgba(185, 140, 242, 0.18);
  --chip-gold: #F0BE5C; --chip-gold-bg: rgba(240, 190, 92, 0.16);
  --chip-pink: #F27FB5; --chip-pink-bg: rgba(242, 127, 181, 0.16);

  /* "Radiant" dark treatment (owner-requested, sitewide) — a faint
     gradient wash across card surfaces plus a soft colored glow on
     hover, instead of dark mode just being "the same flat cards, in
     grey instead of white." Sep 17 hotfix: owner reported the gradient
     was too subtle to actually notice ("needs to be visible in dark
     theme as well") — widened the color distance between stops and
     added a genuine hue shift (slate-blue-tinted top, toward near-black
     bottom) rather than two near-identical greys, so the effect reads
     clearly without becoming a loud, distracting background. */
  --card-gradient: linear-gradient(160deg, #2C2A42 0%, #211F2E 55%, #1A1926 100%);
  --glow-accent: rgba(123, 127, 222, 0.22);
}

/* Sep 17 hotfix — .stat-card, .chart-card, .draft-card,
   .category-card, and .board-column all now set
   background: var(--card-gradient) directly at their own definitions
   below, in both themes (the --card-gradient token itself is redefined
   under :root[data-theme="dark"] above). .card and .module-card fall
   through to this token via inheritance from wherever they're used. */
:root[data-theme="dark"] .stat-card:hover {
  box-shadow: 0 0 0 1px var(--accent) inset, 0 8px 28px var(--glow-accent);
}
:root[data-theme="dark"] .nav-item.active {
  box-shadow: 0 0 16px var(--glow-accent);
}
:root[data-theme="dark"] .btn.primary {
  box-shadow: 0 0 14px var(--glow-accent);
}
:root[data-theme="dark"] .btn.primary:hover {
  box-shadow: 0 0 22px var(--glow-accent);
}

/* Smooth, non-jarring theme switch rather than an instant hard cut —
   applied broadly but cheaply (only the properties that actually
   change), and skipped entirely for anyone with reduced-motion set. */
body, .sidebar, header.topbar, .stat-card, .card, table, .badge, .btn,
.draft-card, .category-card, .board-column, .board-card, .flash {
  transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
@media (prefers-reduced-motion: reduce) {
  body, .sidebar, header.topbar, .stat-card, .card, table, .badge, .btn,
  .draft-card, .category-card, .board-column, .board-card, .flash {
    transition: none;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: 'Inter', -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--paper);
  color: var(--ink);
  font-size: 15px;
  line-height: 1.55;
}

/* ==========================================================
   Sep 17 redesign — app shell: collapsible left sidebar +
   slim topbar, replacing the old flat 13-item top nav row.
   Layout technique: a hidden checkbox (#sidebar-toggle) plus
   the CSS "general sibling" selector drives collapse state
   with zero JS required for the toggle itself — works with
   JS fully disabled. JS (ui-effects.js) only persists the
   choice across page loads via localStorage, which is a pure
   enhancement on top, never a requirement.
   ========================================================== */

.sidebar-toggle-input { display: none; }

.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: 240px;
  flex: 0 0 240px;
  background: var(--brand-black);
  color: #e4e3ee;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  transition: width 0.22s ease, flex-basis 0.22s ease;
  z-index: 20;
}

/* Checked state = collapsed. Icon-only rail, labels hidden. */
#sidebar-toggle:checked ~ .app-shell .sidebar {
  width: 64px;
  flex-basis: 64px;
}
#sidebar-toggle:checked ~ .app-shell .sidebar .sidebar-brand-name,
#sidebar-toggle:checked ~ .app-shell .sidebar .nav-item span:not(.nav-icon),
#sidebar-toggle:checked ~ .app-shell .sidebar .nav-group-label {
  display: none;
}
#sidebar-toggle:checked ~ .app-shell .sidebar .sidebar-collapse-btn svg {
  transform: rotate(180deg);
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 20px 18px;
  white-space: nowrap;
  overflow: hidden;
}
.sidebar-brand img { height: 30px; width: auto; flex: 0 0 auto; }
.sidebar-brand-name { font-weight: 700; font-size: 16px; letter-spacing: 0.01em; color: #fff; }

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 10px;
  flex: 1;
}

.nav-group-label {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #7d7c94;
  padding: 16px 10px 6px;
  white-space: nowrap;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 8px;
  color: #cfcee0;
  text-decoration: none;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
}
.nav-item:hover { background: rgba(255,255,255,0.07); color: #fff; }
.nav-item:active { transform: scale(0.98); }
.nav-item.active { background: var(--accent); color: #fff; }
.nav-icon { width: 17px; height: 17px; flex: 0 0 auto; }

.sidebar-collapse-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  color: #9c9bb2;
  cursor: pointer;
  border-top: 1px solid rgba(255,255,255,0.08);
}
.sidebar-collapse-btn:hover { color: #fff; }
.sidebar-collapse-btn svg { width: 16px; height: 16px; transition: transform 0.22s ease; }

.main-column {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

header.topbar {
  background: var(--surface-1);
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  padding: 16px 28px;
  display: flex;
  align-items: center;
  gap: 16px;
  position: sticky;
  top: 0;
  z-index: 10;
}

.sidebar-open-btn {
  display: none;
  cursor: pointer;
  color: var(--slate);
  padding: 4px;
}
.sidebar-open-btn svg { width: 20px; height: 20px; }

.topbar-title {
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.01em;
}

.theme-toggle-btn {
  margin-left: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface-1);
  color: var(--slate);
  cursor: pointer;
  padding: 0;
  transition: background 0.15s ease, color 0.15s ease;
}
.theme-toggle-btn:hover { background: var(--surface-2); color: var(--ink); }
.theme-toggle-btn svg { width: 17px; height: 17px; }
/* Light mode: show the moon (click to go dark). Dark mode: show the
   sun (click to go light). Pure CSS attribute-selector swap — no JS
   needed to decide which icon is visible, only to change the theme
   attribute itself. */
.theme-toggle-btn .icon-moon { display: block; }
.theme-toggle-btn .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle-btn .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle-btn .icon-sun { display: block; }

.user-badge {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--slate);
}
.user-badge .user-name { font-weight: 700; color: var(--ink); }
.user-badge .user-role {
  background: var(--surface-2);
  color: var(--accent-dark);
  padding: 2px 8px;
  border-radius: 100px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-weight: 600;
}
.user-badge a { color: var(--slate); }

/* Responsive: sidebar becomes an overlay drawer below 900px, closed by
   default, opened via the topbar hamburger (same checkbox drives both). */
@media (max-width: 900px) {
  .sidebar {
    position: fixed;
    left: 0;
    top: 0;
    transform: translateX(-100%);
    width: 240px;
    flex-basis: 240px;
    box-shadow: 4px 0 24px rgba(0,0,0,0.25);
  }
  #sidebar-toggle:checked ~ .app-shell .sidebar {
    transform: translateX(0);
    width: 240px;
    flex-basis: 240px;
  }
  #sidebar-toggle:checked ~ .app-shell .sidebar .sidebar-brand-name,
  #sidebar-toggle:checked ~ .app-shell .sidebar .nav-item span:not(.nav-icon),
  #sidebar-toggle:checked ~ .app-shell .sidebar .nav-group-label {
    display: block;
  }
  #sidebar-toggle:checked ~ .app-shell .sidebar .nav-item {
    display: flex;
  }
  .main-column { width: 100%; }
  .sidebar-open-btn { display: flex; }
  .sidebar-collapse-btn { display: none; }
}

main {
  max-width: 1180px;
  width: 100%;
  margin: 0 auto;
  padding: 32px 28px 60px;
}

/* Typography scale — oversized, bold, generous whitespace (Sep 17
   ask, referencing unitedcarriers.com's hero typography). Bumped from
   the original 22px/17px pass without changing any element's meaning
   or the underlying markup — every template's <h1>/<h2> just reads
   larger and bolder now. */
h1 { font-size: 30px; font-weight: 800; letter-spacing: -0.015em; margin: 0 0 6px; }
h2 {
  font-size: 19px;
  font-weight: 700;
  margin: 36px 0 14px;
  padding-left: 12px;
  border-left: 3px solid var(--accent);
}
.subtitle { color: var(--slate); margin: 0 0 28px; font-size: 15px; }

/* Sep 17 polish pass — subtle base elevation on every card-like
   surface (not just on hover), the "clean, modern, premium" cue every
   researched 2026 dashboard reference shares (Linear/Stripe/Vercel/
   Raycast) — a soft 1-2px shadow reads as "real depth" without looking
   busy, distinct from the stronger hover-lift shadow already in place
   on .stat-card. Applied broadly via the existing shared selectors, so
   every page picks this up automatically. */
.stat-card, .card, table, .draft-card, .category-card, .board-column {
  box-shadow: 0 1px 2px var(--shadow-soft);
}

/* Filters bar — was a loose row of controls sitting directly on the
   page background; now a single cohesive bar (Stripe/Linear treat
   filter controls as one grouped unit, not scattered elements), same
   surface/border/radius language as every other card on the page. */
.filters {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 20px;
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 14px;
}

.flash {
  padding: 10px 14px;
  border-radius: var(--radius);
  margin-bottom: 16px;
  font-size: 14px;
}
.flash.success { background: var(--success-bg); color: var(--good); border: 1px solid var(--success-border); }
.flash.info { background: var(--surface-2); color: var(--slate); border: 1px solid var(--line); }
.flash.danger { background: var(--danger-bg); color: var(--bad); border: 1px solid var(--danger-border); font-weight: 600; }

.suppression-warning {
  background: var(--danger-bg);
  border: 1px solid var(--danger-border);
  color: var(--bad);
  padding: 8px 12px;
  border-radius: var(--radius);
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 10px;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 16px;
  margin-bottom: 32px;
}

.stat-card {
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px 20px;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.25s ease;
}
.stat-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px var(--shadow-soft); }

/* Sep 17 — icon-chip variant, opt-in via .with-icon so the 6 other
   pages already using plain .stat-card (Buyers, Manual Queue, Order
   Detail/Form, Orders, Suppliers — none of which pass an icon) are
   completely unaffected and keep their original stacked layout. Only
   Overview's cards, which now do pass an icon, get the flex treatment. */
.stat-card.with-icon {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}
/* Sep 17 hotfix: real bug — module-summary cards are <a> tags (they
   link to their page), and an anchor's default browser styling is an
   underline + link-color text. Nothing here previously overrode that,
   so every module card showed underlined blue-ish text instead of
   looking like the plain stat cards next to it. */

.stat-icon {
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.stat-icon svg { width: 20px; height: 20px; }
.stat-icon.blue, .module-icon.blue { background: var(--chip-blue-bg); color: var(--chip-blue); }
.stat-icon.teal, .module-icon.teal { background: var(--chip-teal-bg); color: var(--chip-teal); }
.stat-icon.purple, .module-icon.purple { background: var(--chip-purple-bg); color: var(--chip-purple); }
.stat-icon.gold, .module-icon.gold { background: var(--chip-gold-bg); color: var(--chip-gold); }
.stat-icon.pink, .module-icon.pink { background: var(--chip-pink-bg); color: var(--chip-pink); }

.stat-card .num { font-size: 32px; font-weight: 800; color: var(--ink); letter-spacing: -0.01em; }
.stat-card .label { font-size: 12.5px; color: var(--slate); text-transform: uppercase; letter-spacing: 0.03em; }

/* Sep 17 — real chart containers (line + donut on Overview). Fixed
   height so layout doesn't jump while Chart.js initializes; the real
   underlying numbers (stat cards, tables) always render first and
   independently either way, same principle as every other decorative
   layer in this project. */
.chart-card {
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px 20px;
}
.chart-card h3 {
  font-size: 14px;
  font-weight: 700;
  color: var(--slate);
  margin: 0 0 14px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.chart-card canvas { max-height: 240px; }
/* Sep 17 hotfix: explicit min-height on the card itself — without
   this, the card's height depends entirely on the <canvas> inside it,
   and a canvas has no intrinsic height until Chart.js actually runs
   and sizes it. In the brief window before that JS executes (or if it
   fails to load at all), the card could collapse toward zero height,
   which combined with the .two-col grid below is exactly the kind of
   thing that can look like "cards overlapping the next section" in a
   screenshot. A fixed min-height means the layout is stable and
   correct even before/without Chart.js ever running. */
.chart-card { min-height: 300px; }
/* .chart-card's gradient background is now covered by the shared
   .stat-card, .card, ... rule above (Sep 17 hotfix — un-scoped from
   dark-only), so no page-specific override is needed here anymore. */

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  margin-top: 8px;
  margin-bottom: 32px;
}

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  font-size: 13.5px;
}

th, td {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

th {
  background: var(--surface-2);
  font-weight: 600;
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--slate);
}

tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--row-hover); }

a { color: var(--accent); }

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 100px;
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  background: var(--surface-2);
  color: var(--slate);
}
.badge.verified, .badge.strong, .badge.hot, .badge.sent, .badge.interested { background: var(--success-bg); color: var(--good); }
.badge.unconfirmed, .badge.medium, .badge.draft, .badge.pending, .badge.no_answer { background: var(--warn-bg); color: var(--warn); }
.badge.weak, .badge.reject, .badge.rejected, .badge.not_a_buyer_supplier_detected, .badge.not_interested, .badge.failed, .badge.cancelled { background: var(--danger-bg); color: var(--bad); }
.badge.approved, .badge.new, .badge.called { background: var(--accent-soft-bg); color: var(--accent-dark); }

.filters select, .filters button {
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--ink);
  font-size: 13.5px;
}

.filters input[type="text"], .filters input[type="number"], .filters input[type="password"] {
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--ink);
  font-size: 13.5px;
  min-width: 180px;
}

.filters label { font-weight: 700; font-size: 13.5px; color: var(--ink); }
/* Sep 17 hotfix: real bug found live — select/input/option elements
   were never given an explicit color, so browsers fell back to their
   own default text-rendering color (effectively black) regardless of
   this page's dark background, making every filter dropdown and its
   options unreadable in dark mode. options need the rule too — some
   browsers don't inherit color into <option> from its parent <select>
   the way ordinary elements do. */
.filters select option { background: var(--surface-1); color: var(--ink); }

.filters button {
  background: var(--accent);
  color: #fff;
  border: none;
  cursor: pointer;
}
.filters button:hover { background: var(--accent-dark); }

.btn {
  display: inline-block;
  padding: 5px 11px;
  border-radius: var(--radius);
  font-size: 13px;
  border: 1px solid var(--line);
  background: var(--surface-1);
  cursor: pointer;
  text-decoration: none;
  color: var(--ink);
}
.btn.primary { background: var(--accent); color: #fff; border-color: var(--accent); box-shadow: 0 1px 3px var(--shadow-soft); }
.btn.primary:hover { background: var(--accent-dark); transform: translateY(-1px); box-shadow: 0 4px 10px var(--shadow-soft); }
.btn { transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease; }

/* Focus states — visible, consistent, on both themes (2026 dashboard
   research consistently flags this as commonly neglected in dark
   themes specifically; --accent already has enough contrast on both
   --paper and its dark equivalent to double as a focus ring color). */
.filters select:focus-visible, .filters input:focus-visible,
.btn:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.btn.ghost:hover { background: var(--surface-2); }
.btn.danger { color: var(--bad); }
.btn.danger:hover { background: var(--danger-bg); }

.action-row { display: flex; gap: 8px; flex-wrap: wrap; }

.draft-card {
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  margin-bottom: 14px;
}
.draft-card .meta { color: var(--slate); font-size: 12.5px; margin-bottom: 8px; }
.draft-card .subject { font-weight: 700; margin-bottom: 6px; }
.draft-card .body { white-space: pre-wrap; font-size: 14px; margin-bottom: 12px; color: var(--ink); }

.empty-state {
  padding: 30px;
  text-align: center;
  color: var(--slate);
  background: var(--card);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}

/* Sep 17 — .card was used by verify_queue.html with no actual rule
   defined for it anywhere in this file (a real pre-existing gap, found
   while auditing every background: var(--card) usage this round) —
   given a real definition now, consistent with every other card-like
   component here. */
.card {
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
}

/* Sep 17 — module-summary grid (Overview page): one small card per
   sidebar nav item, so the page reads as a genuine at-a-glance summary
   of the whole app rather than just the outreach-pipeline numbers it
   showed before. Deliberately compact (smaller than the main
   .stat-grid cards above) since there are 14 of these. */
.module-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
}
.module-card {
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  text-decoration: none;
  color: var(--ink);
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.module-card:hover { transform: translateY(-2px); box-shadow: 0 8px 20px var(--shadow-soft); }
.module-card .module-icon {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.module-card .module-icon svg { width: 15px; height: 15px; }
.module-card .module-num { font-size: 20px; font-weight: 800; letter-spacing: -0.01em; }
.module-card .module-label { font-size: 12.5px; font-weight: 700; color: var(--ink); }
.module-card .module-sub { font-size: 11px; color: var(--slate); text-transform: uppercase; letter-spacing: 0.02em; }

.company-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 4px;
}

.notes-box {
  background: var(--surface-2);
  border-radius: var(--radius);
  padding: 10px 12px;
  font-size: 13.5px;
  color: var(--slate);
  margin-top: 8px;
}

form.inline { display: inline; }

/* Product-category IA (Sep 5 session, continued) — a category is a
   distinct navigational unit now, not just another filter dropdown
   buried among others. */
.category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}

.category-card {
  display: block;
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-left: 4px solid var(--slate-blue);
  border-radius: var(--radius);
  padding: 14px 16px;
  text-decoration: none;
  color: var(--ink);
}
.category-card:hover { border-left-color: var(--dim-gray); background: var(--row-hover); }
.category-card .cat-name { font-weight: 700; font-size: 14.5px; text-transform: capitalize; }
.category-card .cat-count { font-size: 22px; font-weight: 700; color: var(--slate); margin: 4px 0; }
.category-card .cat-products { font-size: 12px; color: var(--ink-soft); }

/* Freight/shipping-crate icon used as a small inline motif next to
   later pipeline stages (SAMPLE onward — the point where a real
   physical shipment starts to matter) — a single reusable inline SVG,
   not an icon font or external image (performance budget again). */
.stage-icon {
  display: inline-block;
  width: 14px;
  height: 14px;
  vertical-align: -2px;
  margin-right: 4px;
  opacity: 0.75;
}

/* Module 14 — pipeline board view */
.board {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 12px;
}

.board-column {
  min-width: 200px;
  flex: 0 0 200px;
  background: var(--card-gradient);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px;
}

.board-column-header {
  font-size: 12.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--slate);
  margin-bottom: 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.board-column-count {
  background: var(--surface-2);
  border-radius: 100px;
  padding: 1px 7px;
  font-size: 11px;
}

.board-card {
  display: block;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 8px 10px;
  margin-bottom: 8px;
  text-decoration: none;
  color: var(--ink);
}

.board-card:hover { border-color: var(--slate-blue); }

.board-card-company {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 2px;
}

.board-card-meta {
  font-size: 11.5px;
  color: var(--slate);
  margin-bottom: 6px;
}

.board-column-empty {
  color: var(--slate);
  font-size: 12px;
  text-align: center;
  padding: 8px 0;
}

/* Module 14 — lead detail timeline */
.timeline {
  list-style: none;
  padding: 0;
  margin: 0;
}

.timeline li {
  padding: 8px 0 8px 20px;
  border-left: 2px solid var(--line);
  position: relative;
  font-size: 13.5px;
}

.timeline li::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 13px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--slate-blue);
}

.timeline li:last-child { border-left-color: transparent; }

/* ==========================================================
   Sep 17 — global reveal-on-scroll animation, driven by
   ui-effects.js adding/removing the .revealed class via
   IntersectionObserver. Elements start slightly lower and
   faded; ui-effects.js opts elements IN by adding .reveal to
   them at load, so anyone with JS disabled (or the class not
   yet applied) sees the exact same content immediately, fully
   readable, at full opacity — this rule only fires once .reveal
   is present, and .reveal itself is only ever added by JS.
   ========================================================== */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.reveal.revealed {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* Sep 17 hotfix — hero rebuilt as a full-bleed background band, not a
   separate boxed card (owner: the previous version looked like "a
   separate element hovering above the surface" instead of something
   blended into the page, like the unitedcarriers.com reference).
   .page-hero breaks out of <main>'s centered max-width column for
   its BACKGROUND COLOR only (100vw width, negative left margin equal
   to half the viewport width). Sep 17 second hotfix: a real bug in
   that first version — the background broke full-bleed correctly, but
   the world map and title text inside it used the same viewport-
   relative math with no max-width cap, so on any screen wider than
   1180px+56px they'd extend past where <main>'s own content actually
   ends, and the map's right edge would drift out of alignment with
   the stat-grid's right edge below it (exactly what was reported).
   Fixed with a real inner wrapper (.page-hero-inner) using the
   IDENTICAL max-width/padding math as <main> itself, so the map and
   title are guaranteed to line up with the grid below on every screen
   size, not just by coincidence at one viewport width. */
.page-hero {
  position: relative;
  width: 100vw;
  margin-left: calc(-50vw + 50%);
  overflow: hidden;
  background: var(--paper);
}
.page-hero-inner {
  position: relative;
  max-width: 1180px;
  margin: 0 auto;
  padding: 56px 28px 40px;
  min-height: 380px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
#network-hero, #product-scene, #geo-scene {
  position: absolute;
  inset: 0;
  background: var(--paper);
}
.page-hero-content {
  position: relative;
  z-index: 1;
}
.page-hero-content .subtitle { margin-bottom: 0; }
