/* ══════════════════════════════════════════════════════════════════════════════
   Vaste CRM — Design System + Layout
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── Design tokens ──────────────────────────────────────────────────────────── */
/* NOTE: canonical Vaste palette and type scale live in vaste-tokens.css and
   are loaded BEFORE this file. The aliases below map the legacy --vaste-*
   names used throughout this stylesheet onto the new tokens. Brand book v2
   (2026-10) replaced design system v1; the "BRAND BOOK v2" layer at the end
   of this file restyles Bootstrap's components on top of it. */
:root {
  /* The --vaste-* names used throughout this stylesheet alias the green
     scale in vaste-tokens.css. Button fill is green-600 (#048059); links and
     small green text are green-700 (#037A54); Green Haze (green-500,
     #049668) is for graphics only — see tests/Unit/BrandContrastTest. */
  --vaste-green:        var(--green-600);
  --vaste-green-light:  var(--green-400);
  --vaste-green-dark:   var(--green-700);
  --vaste-green-xdark:  var(--green-800);
  --vaste-green-text:   var(--green-700);   /* small text on white — AA */

  /* Spacing — aliases of the canonical --space-* scale in vaste-tokens.css. */
  --sp-1:  var(--space-1);
  --sp-2:  var(--space-2);
  --sp-3:  var(--space-3);
  --sp-4:  var(--space-4);
  --sp-5:  var(--space-5);
  --sp-6:  var(--space-6);
  --sp-8:  var(--space-8);
  --sp-10: var(--space-10);
  --sp-12: var(--space-12);

  /* Radius + shadows come from vaste-tokens.css (4/8/12/16/100, green-tinted
     shadows). Only --shadow-xs is local — a token-tinted extra step. */
  --shadow-xs: 0 1px 2px rgba(10, 40, 20, .06);

  /* Surfaces */
  --content-bg:   var(--neutral-50);
  --card-bg:      var(--neutral-0);
  --border-color: var(--neutral-100);

  /* Topbar / Sidebar — design-system rail: white, muted group labels,
     mint active state. */
  --topbar-h:       60px;
  --sidebar-w:           228px;
  --sidebar-bg:          var(--neutral-0);
  --sidebar-border:      var(--neutral-100);
  --sidebar-text:        var(--neutral-700);
  --sidebar-text-muted:  var(--neutral-500);
  --sidebar-hover-bg:    var(--neutral-50);
  --sidebar-active-bg:   var(--green-50);
  --sidebar-active-text: var(--green-700);
  --sidebar-section-label: var(--neutral-300);

  /* Typography — Inter, via the canonical px scale in vaste-tokens.css. */
  --font-sans: var(--font-body);
}

/* ── Reset ──────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0; padding: 0;
  font-family: var(--font-sans);
  background: var(--content-bg);
  color: var(--neutral-700);
  font-size: var(--text-sm);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Focus ring — brand green, accessible (design system base.css) */
:focus-visible {
  outline: 2px solid var(--green-600);
  outline-offset: 2px;
}

/* Lucide icons render as inline SVGs. createIcons sets 1em; the brand layer
   sizes them 16/18/20px (see "Icons (0.10)") and keeps 1em only where a size
   was set on purpose. The slight negative baseline shift mirrors how icon
   fonts sat in the line box. */
svg.lucide {
  vertical-align: -0.125em;
  flex-shrink: 0;
}


/* ══════════════════════════════════════════════════════════════════════════════
   TOP BAR
   ══════════════════════════════════════════════════════════════════════════════ */
.topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--topbar-h);
  background: #fff;
  border-bottom: 1px solid var(--neutral-100);
  display: flex;
  align-items: center;
  padding: 0 var(--sp-5);
  gap: var(--sp-3);
  z-index: 1000;
  box-shadow: var(--shadow-xs);
}

/* Hamburger (mobile only) */
.topbar-hamburger {
  display: none;
  background: none;
  border: none;
  padding: var(--sp-2);
  cursor: pointer;
  color: var(--neutral-700);
  font-size: 1.2rem;
  border-radius: var(--radius-sm);
  transition: background .15s;
  flex-shrink: 0;
}
.topbar-hamburger:hover { background: var(--neutral-50); }

/* Brand */
.topbar-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  text-decoration: none;
  flex-shrink: 0;
}
.topbar-logo {
  height: 32px;
  width: auto;
  object-fit: contain;
  display: block;
  flex-shrink: 0;
}
/* Brand lockup (logo + strapline PNG) — height set so the wordmark caps roughly
   match Bootstrap's body-text x-height in the topbar. */
.topbar-lockup {
  height: 36px;
  width: auto;
  object-fit: contain;
  display: block;
  flex-shrink: 0;
}

/* Search */
.topbar-search {
  flex: 1; max-width: 420px;
  margin: 0 auto;
  position: relative;
}
.topbar-search-icon {
  position: absolute; left: .75rem; top: 50%;
  transform: translateY(-50%);
  color: var(--neutral-300); font-size: .9rem; pointer-events: none;
}
.topbar-search-input {
  width: 100%;
  padding: .4rem .9rem .4rem 2.1rem;
  border: 1px solid var(--neutral-100); border-radius: var(--radius-md);
  font-size: var(--text-sm); background: var(--neutral-50); color: var(--neutral-900);
  outline: none; transition: border-color .15s, box-shadow .15s;
}
.topbar-search-input:focus {
  border-color: var(--green-200);
  box-shadow: 0 0 0 3px rgba(26,153,85,.12);
  background: #fff;
}
.topbar-search-input::placeholder { color: var(--neutral-300); }

/* Topbar right cluster */
.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }

/* Notification bell */
.topbar-notif-btn {
  position: relative;
  background: none; border: none; cursor: pointer;
  padding: var(--sp-2); border-radius: var(--radius-sm);
  color: var(--neutral-500); font-size: 1.1rem;
  transition: background .15s, color .15s;
}
.topbar-notif-btn:hover { background: var(--neutral-50); color: var(--green-700); }
.notif-badge {
  position: absolute; top: 4px; right: 4px;
  min-width: 16px; height: 16px;
  background: var(--color-error); color: #fff;
  border-radius: var(--radius-pill);
  font-size: .6rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  line-height: 1; padding: 0 3px;
  border: 2px solid #fff;
}

/* Profile */
.topbar-profile { flex-shrink: 0; }
.topbar-profile-btn {
  display: flex; align-items: center; gap: var(--sp-2);
  background: none; border: none; cursor: pointer;
  padding: .3rem var(--sp-2); border-radius: var(--radius-sm);
  color: var(--neutral-700); font-size: var(--text-sm); font-weight: 500;
  transition: background .15s;
}
.topbar-profile-btn:hover { background: var(--neutral-50); }
.topbar-profile-btn::after { display: none; }
.topbar-avatar {
  width: 32px; height: 32px;
  background: var(--vaste-green); color: #fff;
  border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-size: var(--text-xs);
  font-weight: 700; flex-shrink: 0;
}
.topbar-profile-name { font-weight: 600; }

/* ══════════════════════════════════════════════════════════════════════════════
   APP SHELL
   ══════════════════════════════════════════════════════════════════════════════ */
.app-shell { display: flex; min-height: 100vh; padding-top: var(--topbar-h); }

/* ══════════════════════════════════════════════════════════════════════════════
   SIDEBAR
   ══════════════════════════════════════════════════════════════════════════════ */
.sidebar {
  position: fixed; top: var(--topbar-h); left: 0; bottom: 0;
  width: var(--sidebar-w);
  background: var(--sidebar-bg);
  border-right: 1px solid var(--sidebar-border);
  display: flex; flex-direction: column;
  overflow-y: auto; overflow-x: hidden;
  z-index: 900;
  scrollbar-width: thin; scrollbar-color: #d0d8d2 transparent;
  transition: transform .22s cubic-bezier(.4,0,.2,1);
}

/* Mobile overlay */
.sidebar-overlay {
  display: none;
  position: fixed; inset: 0; z-index: 899;
  background: rgba(0,0,0,.35);
}
.sidebar-overlay.show { display: block; }

.sidebar-nav { flex: 1; padding: var(--sp-3) 0; }

/* Section label */
.sidebar-section { margin-bottom: var(--sp-1); }
.sidebar-section-label {
  font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--sidebar-section-label);
  padding: var(--sp-4) var(--sp-4) var(--sp-2);
}

/* Nav link — design-system rail item: inset rounded row, mint active state,
   no left rail. */
.sidebar-link {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  margin: 0 var(--sp-2) 1px;
  color: var(--sidebar-text); text-decoration: none;
  font-size: var(--text-sm); font-weight: 400;
  transition: background .13s, color .13s;
  position: relative; border-radius: 7px;
}
.sidebar-link i, .sidebar-link .lucide { font-size: 1rem; flex-shrink: 0; color: var(--sidebar-text-muted); transition: color .13s; }
.sidebar-link .sidebar-count {
  margin-left: auto;
  background: var(--color-error);
  color: #fff;
  border-radius: var(--radius-pill);
  font-size: 10px; font-weight: 600;
  padding: 1px 6px; line-height: 1.5;
}
.sidebar-link:hover {
  background: var(--sidebar-hover-bg); color: var(--sidebar-text);
}
.sidebar-link.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
  font-weight: 600;
}
.sidebar-link.active i, .sidebar-link.active .lucide { color: var(--green-600); }

/* Footer: primary quick-add + user chip (design-system Sidebar footer). */
.sidebar-footer { padding: var(--sp-3); border-top: 1px solid var(--sidebar-border); }
.sidebar-new-btn {
  display: flex; align-items: center; justify-content: center;
  padding: 9px var(--sp-3); background: var(--green-600); color: #fff;
  border-radius: 6px; text-decoration: none;
  font-size: var(--text-sm); font-weight: 500;
  transition: background .15s;
}
.sidebar-new-btn:hover { background: var(--green-700); color: #fff; }
.sidebar-user {
  display: flex; align-items: center; gap: 10px;
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--sidebar-border);
}
.sidebar-user-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--green-50); color: var(--green-700);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; flex-shrink: 0;
}
.sidebar-user-name {
  font-size: 12px; font-weight: 600; color: var(--neutral-900);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-user-role { font-size: 11px; color: var(--neutral-500); }
.sidebar-user-logout {
  margin-left: auto; background: none; border: none; cursor: pointer;
  color: var(--neutral-300); padding: 4px; display: inline-flex; flex-shrink: 0;
  border-radius: var(--radius-sm); transition: color .13s;
}
.sidebar-user-logout:hover { color: var(--color-error); }

/* ══════════════════════════════════════════════════════════════════════════════
   MAIN CONTENT
   ══════════════════════════════════════════════════════════════════════════════ */
.main-content {
  margin-left: var(--sidebar-w);
  flex: 1; padding: var(--sp-8) var(--sp-8);
  min-width: 0;
}

/* ══════════════════════════════════════════════════════════════════════════════
   AUTH PAGES
   ══════════════════════════════════════════════════════════════════════════════ */
body.auth-page .app-shell { display: block; padding-top: 0; }
body.auth-page .sidebar { display: none; }
body.auth-page .main-content { margin-left: 0; padding: 0; }

/* ══════════════════════════════════════════════════════════════════════════════
   BOOTSTRAP OVERRIDES
   ══════════════════════════════════════════════════════════════════════════════ */
/* Buttons are styled by the brand layer's variables ("BRAND BOOK v2" below).
   The v1 rules that sat here set colours and a 6px radius directly, which
   beat those variables. */

/* Secondary (mint) + ghost variants from the design system. */
.btn-secondary-brand {
  background-color: var(--green-50); border-color: var(--green-50);
  color: var(--green-700);
}
.btn-secondary-brand:hover, .btn-secondary-brand:focus {
  background-color: var(--green-100); border-color: var(--green-100);
  color: var(--green-700);
}
.btn-ghost {
  background-color: transparent; border-color: transparent;
  color: var(--neutral-700);
}
.btn-ghost:hover, .btn-ghost:focus { background-color: var(--neutral-50); color: var(--neutral-900); }


/* A flex item defaults to min-width:auto, which means `text-truncate` inside a
   flex row silently does nothing and long text pushes its siblings out instead
   of ellipsing. Bootstrap 5.3 ships no such utility, and the class was already
   in use across several views expecting it to exist — so it was a no-op
   everywhere until now. */
.min-w-0 { min-width: 0; }

/* Hero gradient utility — apply to splash / login surfaces where a marquee
   feel is wanted. NOT used on in-app pages (those use .page-hero below). */
.bg-gradient-hero {
  background: linear-gradient(135deg, var(--green-600) 0%, var(--green-700) 100%);
  color: #fff;
}
.bg-gradient-hero a { color: rgba(255, 255, 255, 0.92); }
.bg-gradient-hero a:hover { color: #fff; }

/* ── Vaste product page-hero pattern ──────────────────────────────────────
   White card + green icon circle + title + subtitle + outline actions.
   Mirrors the dashboard header from the Vaste feedstock product so the
   CRM feels like part of the same suite. */
.page-hero {
  background: #fff;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  padding: var(--sp-5) var(--sp-6);
  box-shadow: var(--shadow-xs);
}
.page-hero-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--green-600);
  color: #fff;
  font-size: 1.25rem;
  flex-shrink: 0;
}

/* ── Filter pill tabs ────────────────────────────────────────────────────
   Used for "Today / 7 days / 30 days / …" style time-range selectors.
   Active pill fills with brand green; inactive pills are quiet text. */
.filter-pills {
  display: inline-flex;
  background: var(--neutral-50);
  border-radius: var(--radius-pill);
  padding: 4px;
  gap: 2px;
}
.filter-pills .filter-pill {
  border: 0;
  background: transparent;
  color: var(--color-fg-muted);
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  font-size: .8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: all .15s ease;
  text-decoration: none;
}
.filter-pills .filter-pill:hover {
  color: var(--color-fg);
}
.filter-pills .filter-pill.active {
  background: var(--green-600);
  color: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .08);
}

/* ── Stat-card accent variant ────────────────────────────────────────────
   .stat-card.is-accent (legacy alias .is-highlight) = the ONE emphasised
   KPI per row: solid brand-green card with white value, per the design
   system's StatCard accent treatment. */
.stat-card.is-accent,
.stat-card.is-highlight {
  background: var(--green-600) !important;
  border-color: var(--green-600) !important;
}
.stat-card.is-accent .fs-2, .stat-card.is-accent .stat-value,
.stat-card.is-highlight .fs-2, .stat-card.is-highlight .stat-value {
  color: #fff;
}
.stat-card.is-accent .text-muted, .stat-card.is-accent .stat-sub,
.stat-card.is-highlight .text-muted, .stat-card.is-highlight .stat-sub {
  color: rgba(255, 255, 255, .75) !important;
}
.stat-card.is-accent .stat-label,
.stat-card.is-highlight .stat-label {
  color: rgba(255, 255, 255, .7) !important;
}
.stat-card.is-accent .stat-unit,
.stat-card.is-highlight .stat-unit {
  color: rgba(255, 255, 255, .65);
}
.stat-card.is-accent .stat-icon i, .stat-card.is-accent .stat-icon .lucide,
.stat-card.is-highlight .stat-icon i, .stat-card.is-highlight .stat-icon .lucide {
  color: rgba(255, 255, 255, .5) !important;
}
.page-link { color: var(--vaste-green); }
.page-item.active .page-link { background-color: var(--vaste-green); border-color: var(--vaste-green); }
.form-control:focus, .form-select:focus {
  border-color: var(--green-200);
  box-shadow: 0 0 0 .2rem rgba(26,153,85,.15);
}
.card { border: 1px solid var(--neutral-100); border-radius: var(--radius-lg); }
.card-header { border-bottom: 1px solid var(--neutral-100); }
.dropdown-menu { border-radius: var(--radius-md); border: 1px solid var(--neutral-100); box-shadow: var(--shadow-md); }
.table > :not(caption) > * > * { padding: .6rem .75rem; }
.alert { border-radius: var(--radius-md); }

/* ══════════════════════════════════════════════════════════════════════════════
   PAGE HEADER (design system: eyebrow / title / subtitle)
   ══════════════════════════════════════════════════════════════════════════════ */
.page-header-eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--green-700);
  margin-bottom: 2px;
}
.page-header-title {
  font-size: 21px;
  font-weight: var(--weight-bold);
  letter-spacing: -0.025em;
  color: var(--neutral-900);
}
.page-header-subtitle {
  font-size: var(--text-sm);
  color: var(--neutral-500);
}

/* ══════════════════════════════════════════════════════════════════════════════
   STAT CARDS (design system: uppercase label / 30px value / trend delta)
   ══════════════════════════════════════════════════════════════════════════════ */
.stat-card { transition: transform var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out); cursor: default; }
.stat-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md) !important; }
.stat-icon { display: inline-flex; align-items: center; justify-content: center; color: var(--neutral-300); font-size: 15px; }
.stat-label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--neutral-500);
}
.stat-card .stat-value {
  font-size: 30px;
  font-weight: var(--weight-bold);
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--neutral-900);
}
.stat-unit { font-size: var(--text-sm); color: var(--neutral-500); }
.stat-sub {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--green-700);
  margin-top: 6px;
}
.stat-sub.is-negative { color: var(--color-warning); }

/* ══════════════════════════════════════════════════════════════════════════════
   VASTE BADGES (design system: pill, tinted bg, leading status dot)
   ══════════════════════════════════════════════════════════════════════════════ */
.vaste-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: -0.01em;
  border-radius: var(--radius-pill);
  padding: 3px 9px;
  white-space: nowrap;
}
.vaste-badge-dot { width: 5px; height: 5px; border-radius: 50%; flex-shrink: 0; background: currentColor; }
.vaste-badge-active  { background: var(--green-50); color: var(--green-700); }
.vaste-badge-active .vaste-badge-dot { background: var(--green-600); }
.vaste-badge-pending { background: var(--color-warning-bg); color: var(--color-warning); }
.vaste-badge-risk    { background: var(--color-error-bg); color: var(--color-error); }
.vaste-badge-info    { background: var(--color-info-bg); color: var(--color-info); }
.vaste-badge-default { background: var(--neutral-100); color: var(--neutral-700); }
.vaste-badge-default .vaste-badge-dot { background: var(--neutral-300); }
.vaste-badge-brand   { background: var(--green-700); color: #fff; }

/* ══════════════════════════════════════════════════════════════════════════════
   EMPTY STATES
   ══════════════════════════════════════════════════════════════════════════════ */
.empty-state {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: var(--sp-12) var(--sp-8);
  text-align: center; color: var(--neutral-500);
}
.empty-state-icon {
  font-size: 3rem; margin-bottom: var(--sp-4);
  opacity: .4;
}
.empty-state-title { font-size: var(--text-md); font-weight: 600; color: var(--neutral-700); margin-bottom: var(--sp-2); }
.empty-state-text  { font-size: var(--text-sm); margin-bottom: var(--sp-4); max-width: 300px; }

/* ══════════════════════════════════════════════════════════════════════════════
   BADGES
   ══════════════════════════════════════════════════════════════════════════════ */
.badge-tag      { background:var(--green-50); color:var(--green-700); font-weight:500; font-size:var(--text-xs); }
.badge-supplier { background:var(--color-info-bg); color:var(--color-info); }
.badge-buyer    { background:var(--green-100); color:var(--green-800); }
.badge-other    { background:var(--neutral-100); color:var(--neutral-700); }
/* Both category badges rendered with no rule at all — Bootstrap's .badge is
   transparent with white text, so they were invisible on a light card.
   `compliance` has been that way since the category was added. */
.badge-partner    { background:var(--green-50); color:var(--green-700); }
.badge-compliance { background:var(--color-info-bg); color:var(--color-info); }

.badge-status-prospect { background:var(--color-info-bg); color:var(--color-info); font-size:var(--text-xs); }
.badge-status-active   { background:var(--green-50); color:var(--green-700); font-size:var(--text-xs); }
.badge-status-dormant  { background:var(--color-warning-bg); color:#9A5E0B; font-size:var(--text-xs); }
.badge-status-lost     { background:var(--color-error-bg); color:var(--color-error); font-size:var(--text-xs); }

.badge-role-admin  { background:var(--green-700); color:#fff; font-size:var(--text-xs); }
.badge-role-editor { background:var(--color-info-bg); color:var(--color-info); font-size:var(--text-xs); }
.badge-role-viewer { background:var(--neutral-100); color:var(--neutral-700); font-size:var(--text-xs); }

/* Deal stage badges */
.badge-deal-identified    { background:var(--neutral-100); color:var(--neutral-700); }
.badge-deal-contacted     { background:var(--color-info-bg); color:var(--color-info); }
.badge-deal-meeting_held  { background:var(--color-info-bg); color:#125A7A; }
.badge-deal-demo          { background:var(--green-100); color:var(--green-800); }
.badge-deal-proposal_sent { background:var(--green-50); color:var(--green-700); }
.badge-deal-negotiation   { background:var(--color-warning-bg); color:#9A5E0B; }
.badge-deal-pilot         { background:var(--color-warning-bg); color:#9A5E0B; }
.badge-deal-won           { background:var(--green-100); color:var(--green-800); }
.badge-deal-deal_signed   { background:var(--green-700); color:#fff; }
.badge-deal-lost          { background:var(--color-error-bg); color:var(--color-error); }

/* RAG */
.rag-green { background:var(--green-50); color:var(--green-700); font-weight:600; }
.rag-amber { background:var(--color-warning-bg); color:#9A5E0B; font-weight:600; }
.rag-red   { background:var(--color-error-bg); color:var(--color-error); font-weight:600; }

.bg-purple-soft { background:var(--color-info-bg); color:var(--color-info); }
.border-dashed  { border: 2px dashed var(--neutral-100) !important; }

/* ══════════════════════════════════════════════════════════════════════════════
   CONTACT TABLE
   ══════════════════════════════════════════════════════════════════════════════ */
.contact-row { transition: background .1s; }
.contact-row:hover { background-color: var(--neutral-50) !important; cursor: pointer; }

/* ══════════════════════════════════════════════════════════════════════════════
   INTERACTION TIMELINE
   ══════════════════════════════════════════════════════════════════════════════ */
.timeline { position: relative; }
.timeline::before {
  content: ''; position: absolute; left: 19px; top: 0; bottom: 0;
  width: 2px; background: var(--neutral-100);
}
.timeline-item {
  display: flex; gap: var(--sp-4);
  padding: var(--sp-3) 0;
  position: relative;
}
.timeline-icon {
  width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: .95rem; flex-shrink: 0; z-index: 1;
  border: 2px solid #fff;
  box-shadow: var(--shadow-xs);
}
.timeline-icon-call    { background:var(--color-info-bg); color:var(--color-info); }
.timeline-icon-email   { background:var(--green-50); color:var(--green-700); }
.timeline-icon-meeting { background:var(--green-100); color:var(--green-800); }
.timeline-icon-note    { background:var(--color-warning-bg); color:var(--color-warning); }
.timeline-body { flex: 1; min-width: 0; }
.timeline-card {
  background: #fff; border: 1px solid var(--neutral-100);
  border-radius: var(--radius-md); padding: var(--sp-4);
  box-shadow: var(--shadow-xs);
  transition: box-shadow .15s;
}
.timeline-card:hover { box-shadow: var(--shadow-sm); }
.timeline-meta { font-size: var(--text-xs); color: var(--neutral-500); }

/* Next-action callout */
.next-action-callout {
  background: var(--green-50);
  border: 1px solid var(--green-200);
  border-left: 4px solid var(--green-600);
  border-radius: var(--radius-md);
  padding: var(--sp-4) var(--sp-5);
}

/* Inline edit */
.inline-editable {
  cursor: pointer;
  border-bottom: 1px dashed transparent;
  transition: border-color .15s;
  padding-bottom: 1px;
}
.inline-editable:hover { border-bottom-color: var(--vaste-green-light); }
.inline-edit-form { display: none; }
.inline-edit-form.active { display: flex; gap: var(--sp-2); align-items: center; }

/* ══════════════════════════════════════════════════════════════════════════════
   TAG INPUT
   ══════════════════════════════════════════════════════════════════════════════ */
.tag-input-wrapper {
  display: flex; flex-wrap: wrap; align-items: center;
  border: 1px solid #dee2e6; border-radius: var(--radius-sm);
  padding: .3rem .6rem; background: #fff; cursor: text;
  min-height: 42px; gap: var(--sp-1);
}
.tag-input-wrapper:focus-within {
  border-color: var(--green-200);
  box-shadow: 0 0 0 .2rem rgba(26,153,85,.15);
}
.tag-pill {
  display: inline-flex; align-items: center;
  background: var(--green-50); color: var(--green-700);
  border-radius: var(--radius-pill); padding: .15rem .55rem;
  font-size: var(--text-xs); user-select: none; line-height: 1.6;
}
.tag-pill .remove-tag { margin-left:.35rem; font-size:.9rem; opacity:.55; cursor:pointer; }
.tag-pill .remove-tag:hover { opacity:1; }
#tagInput { border:none; outline:none; flex:1; min-width:120px; padding:.1rem 0; font-size:.9rem; background:transparent; }
#tagsHidden { display: none; }

/* ══════════════════════════════════════════════════════════════════════════════
   PIPELINE / KANBAN
   ══════════════════════════════════════════════════════════════════════════════ */
.kanban-col { min-height: 120px; transition: background .15s, outline .1s; }
.kanban-col.drag-over { outline: 2px dashed var(--vaste-green-light); outline-offset: -3px; background: #edf7f2 !important; }

/* Batch 18: full-width kanban board and visually-distinct closed columns.
   .kanban-column = the outer flex item that wraps header + drop zone.
   Columns flex-grow to fill the viewport so all 8 stages distribute
   evenly across desktop instead of clustering at the left. */
.kanban-board { width: 100%; align-items: stretch; }
.kanban-column {
  background: transparent;
  border-radius: var(--radius-md);
  padding: 6px;
}
.kanban-column-closed {
  background: rgba(0, 0, 0, .025);
}
.kanban-column-closed .kanban-col { background: rgba(0, 0, 0, .015) !important; }
.kanban-column-closed .fw-semibold { opacity: .75; }
.kanban-card { transition: box-shadow .15s, transform .1s; overflow: hidden; }
.kanban-card:hover { box-shadow: var(--shadow-md) !important; transform: translateY(-1px); }
.kanban-card[draggable="true"] { cursor: grab; }
.kanban-card[draggable="true"]:active { cursor: grabbing; }

/* Quick-edit popover */
.deal-popover {
  position: fixed; z-index: 1050;
  background: #fff; border: 1px solid rgba(0,0,0,.12);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  width: 320px; padding: var(--sp-5);
  display: none;
}
.deal-popover.show { display: block; }

/* Pipeline mini-bar */
.pipeline-bar { display: flex; gap: 2px; align-items: flex-end; height: 40px; }
.pipeline-bar-col { flex: 1; background: var(--vaste-green); border-radius: 3px 3px 0 0; min-height: 4px; transition: height .3s; }

/* ══════════════════════════════════════════════════════════════════════════════
   USER MANAGEMENT
   ══════════════════════════════════════════════════════════════════════════════ */
.user-avatar-lg {
  width: 40px; height: 40px; background: var(--vaste-green); color: #fff;
  border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: .9rem; font-weight: 700; flex-shrink: 0;
}
.invite-link-box {
  background: #f0f4f1; border: 1px dashed var(--vaste-green-light);
  border-radius: var(--radius-sm); padding: .75rem 1rem; word-break: break-all;
  font-size: var(--text-xs); color: var(--green-800); font-family: monospace;
}

/* ══════════════════════════════════════════════════════════════════════════════
   BULK TOOLBAR
   ══════════════════════════════════════════════════════════════════════════════ */
#bulkToolbar { transition: opacity .15s; }

/* ══════════════════════════════════════════════════════════════════════════════
   NOTIFICATION DROPDOWN
   ══════════════════════════════════════════════════════════════════════════════ */
.notif-dropdown {
  position: absolute; right: 0; top: calc(100% + 8px);
  width: 340px; background: #fff;
  border: 1px solid rgba(0,0,0,.1); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); z-index: 1050; display: none;
  max-height: 480px; overflow-y: auto;
}
.notif-dropdown.show { display: block; }
.notif-item { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid rgba(0,0,0,.06); }
.notif-item:last-child { border-bottom: none; }
.notif-item a { text-decoration: none; color: inherit; }
.notif-item:hover { background: #f8faf8; }
.notif-header { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--neutral-100); font-weight: 600; font-size: var(--text-sm); }

/* ══════════════════════════════════════════════════════════════════════════════
   ONBOARDING CHECKLIST
   ══════════════════════════════════════════════════════════════════════════════ */
.onboarding-card {
  background: linear-gradient(135deg, var(--green-700) 0%, var(--green-900) 100%);
  color: #fff; border-radius: var(--radius-lg); padding: var(--sp-8);
  border: none;
}
.onboarding-step {
  display: flex; align-items: center; gap: var(--sp-4);
  padding: var(--sp-3) 0; border-bottom: 1px solid rgba(255,255,255,.1);
}
.onboarding-step:last-child { border-bottom: none; }
.onboarding-step-icon {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: .85rem;
}
.onboarding-step-icon.done { background: var(--green-400); color: #fff; }
.onboarding-step-icon.todo { background: rgba(255,255,255,.15); color: rgba(255,255,255,.6); }

/* ══════════════════════════════════════════════════════════════════════════════
   AUDIT LOG
   ══════════════════════════════════════════════════════════════════════════════ */
.audit-action-create { color: var(--green-700); }
.audit-action-update { color: var(--color-info); }
.audit-action-delete { color: var(--color-error); }
.audit-action-archive { color: var(--color-warning); }

/* Before/after diff on an audit row. Red/green with a leading -/+ marker so
   the direction survives greyscale printing and colour-blind viewing — the
   colour is reinforcement, never the only signal. */
.audit-changes { max-width: 46rem; }
.audit-change-from,
.audit-change-to {
  font-size: .75rem;
  line-height: 1.45;
  padding: .25rem .5rem;
  border-radius: 4px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* --color-error (#C93B20) on --color-error-bg is 4.45:1 — under AA, and this
   is 12px struck-through text, the least legible thing on the page and often
   the part you most need to read. --red-800 is the same hue at 7.39:1,
   matching the green side's 7.12:1 so neither direction is the weak one. */
.audit-change-from {
  background: var(--color-error-bg);
  color: var(--red-800);
  font-weight: 500;
  text-decoration: line-through;
  /* currentColor, not a copy of the token's RGB — a hardcoded rgba() goes
     stale silently the moment anyone edits the colour it was derived from. */
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
}
.audit-change-to {
  background: var(--green-50);
  color: var(--green-800);
  margin-top: .2rem;
}
.audit-change-from::before { content: '- '; font-weight: 600; }
.audit-change-to::before { content: '+ '; font-weight: 600; }
/* Firefox includes ::before content in copied text, so copying a note out of
   the audit log would arrive with a leading "- ". Chrome and Safari already
   exclude it; Firefox honours user-select here. */
.audit-change-from::before,
.audit-change-to::before { user-select: none; }
/* An absent value still needs its direction marker, or the one case where a
   field was cleared is also the one case where colour is the only signal. */
.audit-change-blank {
  background: transparent;
  color: var(--neutral-500);
  font-style: italic;
  text-decoration: none;
}

/* ══════════════════════════════════════════════════════════════════════════════
   COMPANY ROLLUP
   ══════════════════════════════════════════════════════════════════════════════ */
.company-card { transition: box-shadow var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out); }
.company-card:hover { box-shadow: var(--shadow-md) !important; transform: translateY(-2px); }

/* ══════════════════════════════════════════════════════════════════════════════
   RESPONSIVE — Mobile first
   ══════════════════════════════════════════════════════════════════════════════ */
@media (max-width: 991px) {
  .topbar-hamburger { display: flex; }

  .sidebar {
    transform: translateX(calc(-1 * var(--sidebar-w)));
    width: var(--sidebar-w);
  }
  .sidebar.open { transform: translateX(0); }

  .main-content { margin-left: 0; padding: var(--sp-5) var(--sp-4); }

  /* Stack KPI cards 2x2 on tablet */
  .kpi-grid { grid-template-columns: repeat(2, 1fr) !important; }
}

@media (max-width: 576px) {
  .topbar { padding: 0 var(--sp-4); gap: var(--sp-2); }
  .topbar-search { max-width: 200px; }
  .main-content { padding: var(--sp-4) var(--sp-3); }

  /* Kanban scrolls horizontally at full width */
  #kanban-board { min-width: max-content; }

  /* Tables — hide less critical columns */
  .hide-mobile { display: none !important; }

  /* KPI cards full width on small phones */
  .kpi-grid { grid-template-columns: 1fr 1fr !important; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   PRINT — OKR Report
   ══════════════════════════════════════════════════════════════════════════════ */
.print-only { display: none; }

@media print {
  .topbar, .sidebar, .no-print { display: none !important; }
  .app-shell { padding-top: 0 !important; }
  .main-content { margin-left: 0 !important; padding: 0 !important; }
  .print-only { display: block !important; }
  .card { border: 1px solid #dee2e6 !important; box-shadow: none !important; break-inside: avoid; }
  tr { page-break-inside: avoid; }
  .progress, .badge, [class*="badge-deal-"], [class*="rag-"], [class*="badge-status-"] {
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
  body { font-size: 11pt; color: #000; }
  a { color: #000; text-decoration: none; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   VASTE DESIGN SYSTEM v1 — global override layer
   ──────────────────────────────────────────────────────────────────────────────
   Loaded last so it wins over Bootstrap and the legacy palette above.
   Drives every screen with the canonical token set from vaste-tokens.css.
   ══════════════════════════════════════════════════════════════════════════════ */

/* 1. Re-point Bootstrap's CSS variables at our brand tokens — this re-skins
      every Bootstrap component (.btn-primary, .bg-primary, .text-primary,
      .alert-success, links, focus rings, form-check, pagination, etc.) in one
      shot, with no per-component override required. */
:root {
  --bs-primary:        var(--green-600);
  --bs-primary-rgb:    26, 153, 85;
  --bs-success:        var(--green-600);
  --bs-success-rgb:    26, 153, 85;
  --bs-link-color:     var(--green-700);
  --bs-link-hover-color: var(--green-800);
  --bs-link-color-rgb: 21, 122, 66;
  --bs-body-color:     var(--neutral-700);
  --bs-body-color-rgb: 58, 79, 63;
  --bs-body-bg:        var(--neutral-50);
  --bs-border-color:   var(--neutral-100);
  --bs-secondary-color: var(--neutral-500);
  --bs-tertiary-bg:    var(--neutral-50);
  --bs-emphasis-color: var(--neutral-900);
  --bs-heading-color:  var(--neutral-900);
}

/* 2. Body / page surface — green-tinted neutrals replace flat grey */
body {
  background: var(--neutral-50);
  color: var(--neutral-700);
  font-family: var(--font-body);
}
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  color: var(--neutral-900);
  letter-spacing: var(--tracking-tight);
  font-weight: var(--weight-semibold);
}

/* 3. Buttons — primary uses brand green, hover uses green-700, focus ring
      tinted with brand. Outline variants follow the same logic. */
.btn-primary {
  --bs-btn-bg:            var(--green-600);
  --bs-btn-border-color:  var(--green-600);
  --bs-btn-hover-bg:      var(--green-700);
  --bs-btn-hover-border-color: var(--green-700);
  --bs-btn-active-bg:     var(--green-800);
  --bs-btn-active-border-color: var(--green-800);
  --bs-btn-disabled-bg:   var(--green-200);
  --bs-btn-disabled-border-color: var(--green-200);
  --bs-btn-color:         #fff;
  font-weight: var(--weight-medium);
  letter-spacing: 0;
}
.btn-success {
  --bs-btn-bg:            var(--green-600);
  --bs-btn-border-color:  var(--green-600);
  --bs-btn-hover-bg:      var(--green-700);
  --bs-btn-hover-border-color: var(--green-700);
}
.btn-outline-primary,
.btn-outline-success {
  --bs-btn-color:         var(--green-700);
  --bs-btn-border-color:  var(--green-200);
  --bs-btn-hover-bg:      var(--green-50);
  --bs-btn-hover-color:   var(--green-800);
  --bs-btn-hover-border-color: var(--green-400);
}
.btn:focus, .btn:focus-visible,
.form-control:focus, .form-select:focus {
  box-shadow: 0 0 0 3px rgba(26, 153, 85, 0.18) !important;
  border-color: var(--green-400) !important;
}

/* 4. Cards — softer green-tinted shadow, rounder corners, subtle border */
.card {
  border: 1px solid var(--neutral-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  background: var(--neutral-0);
}
.card-header {
  background: var(--neutral-0);
  border-bottom: 1px solid var(--neutral-100);
  font-weight: var(--weight-semibold);
  color: var(--neutral-900);
}
.shadow-sm { box-shadow: var(--shadow-sm) !important; }

/* 5. Forms — brand-tinted labels, neutral borders */
.form-label {
  color: var(--neutral-700);
  font-weight: var(--weight-medium);
  font-size: var(--text-sm);
}
.form-control, .form-select {
  border-color: var(--neutral-100);
  color: var(--neutral-900);
  border-radius: var(--radius-md);
}
.form-control::placeholder { color: var(--neutral-300); }
.form-text { color: var(--neutral-500); }

/* 6. Tables — design system: uppercase 11px headers on the off-white tint,
      13px rows, neutral hover. */
.table {
  --bs-table-color:        var(--neutral-700);
  --bs-table-bg:           transparent;
  --bs-table-border-color: var(--neutral-100);
  --bs-table-hover-bg:     var(--neutral-50);
  --bs-table-hover-color:  var(--neutral-900);
  font-size: var(--text-sm);
}
.table > thead {
  color: var(--neutral-500);
  font-weight: var(--weight-semibold);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.table > thead th, .table > .table-light > * > th {
  background: var(--neutral-50);
}

/* 7. Badges — soft tinted variants, brand-aware */
.badge.bg-primary,
.badge.bg-success { background: var(--green-600) !important; color: #fff; }
.badge.bg-success-subtle { background: var(--green-50) !important; color: var(--green-800) !important; }
.badge.bg-primary-subtle { background: var(--green-50) !important; color: var(--green-800) !important; }
.text-success-emphasis    { color: var(--green-800) !important; }
.text-primary-emphasis    { color: var(--green-800) !important; }

/* 8. Alerts — design-system status tints across all four variants */
.alert-success {
  background: var(--green-50);
  border-color: var(--green-200);
  color: var(--green-800);
}
.alert-warning {
  background: var(--color-warning-bg);
  border-color: #F3D9AE;
  color: var(--color-warning);
}
.alert-danger {
  background: var(--color-error-bg);
  border-color: #F2C3B8;
  color: var(--color-error);
}
.alert-info {
  background: var(--color-info-bg);
  border-color: #BBD9E6;
  color: var(--color-info);
}

/* 9. Sidebar — light surface (matches Vaste product UI, Batch 14/15).
   The canonical sidebar rules live ~line 240 and use --sidebar-* tokens.
   This block previously hard-coded --green-900 + !important and won the
   cascade against the token-based rules. Now intentionally empty — left
   here as a breadcrumb so anyone grepping for "Sidebar" finds the
   canonical rules earlier in the file. */

/* 10. Topbar — neutral-100 divider, brand-coloured search focus */
.topbar { border-bottom-color: var(--neutral-100); }
.topbar-search-input {
  background: var(--neutral-50);
  border: 1px solid var(--neutral-100);
  color: var(--neutral-900);
}
.topbar-search-input:focus {
  background: #fff;
  border-color: var(--green-400);
  box-shadow: 0 0 0 3px rgba(26, 153, 85, 0.12);
}

/* 11. Links default to brand */
a { color: var(--green-700); }
a:hover { color: var(--green-800); }
a.text-muted, a.text-decoration-none.text-muted { color: var(--neutral-500) !important; }

/* 12. Dashboard stat cards / KPI tiles — soft brand tint */
.stat-card, .kpi-card {
  border: 1px solid var(--neutral-100);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.stat-card .stat-value, .kpi-card .kpi-value {
  color: var(--neutral-900);
  font-weight: var(--weight-semibold);
}

/* 13. List groups (used for tasks, deals, notifications) */
.list-group-item {
  border-color: var(--neutral-100);
  color: var(--neutral-700);
}
.list-group-item-action:hover { background: var(--green-50); }

/* 14. Pagination tinted brand */
.page-link { color: var(--green-700); border-color: var(--neutral-100); }
.page-link:hover { background: var(--green-50); color: var(--green-800); }
.page-item.active .page-link {
  background: var(--green-600);
  border-color: var(--green-600);
}

/* ══════════════════════════════════════════════════════════════════════════════
   TOP-BAR LIVE SEARCH DROPDOWN (Batch 28)
   ══════════════════════════════════════════════════════════════════════════════ */
.topbar-search-results {
  position: absolute;
  top: calc(100% + .35rem);
  left: 0; right: 0;
  background: #fff;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md, 0 8px 24px rgba(0,0,0,.12));
  z-index: 1100;
  max-height: 70vh;
  overflow-y: auto;
  padding: .25rem;
}
.topbar-search-results .tsr-item {
  display: flex; align-items: center; gap: .5rem;
  padding: .5rem .6rem;
  border-radius: var(--radius-sm, 6px);
  color: #1a2e1f; text-decoration: none;
  font-size: var(--text-sm);
}
.topbar-search-results .tsr-item:hover,
.topbar-search-results .tsr-item:focus {
  background: var(--green-50, #eef7f1);
}
.tsr-icon { color: var(--neutral-500); flex-shrink: 0; }
.tsr-label { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tsr-sub { color: #6b8a76; font-size: var(--text-xs); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tsr-type { margin-left: auto; flex-shrink: 0; font-size: .65rem; text-transform: uppercase; letter-spacing: .04em; color: #9aaa9f; }
.tsr-empty { padding: .75rem .6rem; color: #6b8a76; font-size: var(--text-sm); }
.tsr-all {
  display: block; width: 100%; text-align: left;
  padding: .5rem .6rem; margin-top: .15rem;
  border: 0; border-top: 1px solid var(--border-color);
  background: transparent; color: var(--green-700);
  font-size: var(--text-sm); font-weight: 500; cursor: pointer;
  border-radius: 0 0 var(--radius-sm, 6px) var(--radius-sm, 6px);
}
.tsr-all:hover { background: var(--green-50, #eef7f1); }

/* ══════════════════════════════════════════════════════════════════════════════
   FROZEN PAGE HEADER / FILTERS (Batch 28)
   The window is the scroll context (.main-content grows, body scrolls). Making
   the header+filters region sticky just below the fixed topbar keeps the page
   title and filter controls in view while the data list scrolls beneath.
   Pages opt in by wrapping their hero + filter block in .page-sticky-head.
   ══════════════════════════════════════════════════════════════════════════════ */
.page-sticky-head {
  position: sticky;
  top: var(--topbar-h);
  z-index: 30;
  background: var(--content-bg);
  /* Span the full content width (cancel the main-content side padding) so
     list rows scrolling underneath are fully covered, not peeking at the edges. */
  margin: calc(-1 * var(--sp-8)) calc(-1 * var(--sp-8)) var(--sp-3);
  padding: var(--sp-4) var(--sp-8) var(--sp-2);
}
/* The hero already carries mb-4; inside the sticky wrapper we tighten it so the
   frozen band isn't unnecessarily tall. */
.page-sticky-head .page-hero { margin-bottom: var(--sp-3) !important; }
.page-sticky-head .page-header { margin-bottom: var(--sp-3) !important; }
.page-sticky-head > form:last-child,
.page-sticky-head > .row:last-child { margin-bottom: 0 !important; }

@media (max-width: 768px) {
  .page-sticky-head {
    margin: calc(-1 * var(--sp-5)) calc(-1 * var(--sp-4)) var(--sp-3);
    padding: var(--sp-3) var(--sp-4) var(--sp-2);
  }
}
/* ≤576px .main-content drops to --sp-3 horizontal padding; the negative
   margins must match exactly or the band overhangs and triggers a
   horizontal scrollbar on phones. */
@media (max-width: 576px) {
  .page-sticky-head {
    margin: calc(-1 * var(--sp-4)) calc(-1 * var(--sp-3)) var(--sp-3);
    padding: var(--sp-3) var(--sp-3) var(--sp-2);
  }
}

/* ══════════════════════════════════════════════════════════════════════════════
   KANBAN — per-column independent scroll (Batch 34, was board-level in Batch 28)
   The board scrolls HORIZONTALLY only. Each column's card area (.kanban-col)
   is its own bounded vertical scroll container, so one busy stage can no
   longer drag the whole board down — every column tops out at the same
   height and scrolls on its own. The stage header sits ABOVE the scroll
   area, so it stays visible without needing sticky.
   ══════════════════════════════════════════════════════════════════════════════ */
#kanban-board {
  overflow-x: auto;
  /* Bound the whole board to the viewport so the page itself doesn't grow a
     second scrollbar; the columns inside scroll. */
  max-height: calc(100vh - var(--topbar-h) - 200px);
}
.kanban-col {
  /* Card area scrolls independently. The reserve covers topbar + page hero +
     filter bar + the column header above this element. */
  max-height: calc(100vh - var(--topbar-h) - 250px);
  overflow-y: auto;
}
.kanban-column-header {
  background: var(--content-bg);
}
@media (max-width: 768px) {
  /* On small screens let the page scroll normally — a short bounded column is
     more annoying than helpful. */
  #kanban-board { max-height: none; }
  .kanban-col { max-height: none; overflow-y: visible; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   SCROLLABLE TABLE WITH FROZEN COLUMN HEADER (Batch 31)
   Self-contained bounded scroll container (same robust approach as #kanban-board)
   so the <thead> can stick regardless of the .page-sticky-head height above it.
   Wrap a table's .table-responsive with .table-sticky-head.
   ══════════════════════════════════════════════════════════════════════════════ */
.table-sticky-head {
  /* The subtraction reserves room for the topbar + frozen page-head + filters
     above. It's a deliberate over-estimate so the table region never grows tall
     enough to push the page itself into a second scrollbar; on shorter/wrapped
     filter bars there's just a little extra slack, which is harmless. The
     breakpoint overrides below widen the reserve as the filter bar wraps. */
  max-height: calc(100vh - var(--topbar-h) - 240px);
  overflow-y: auto;
}
.table-sticky-head thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  /* table-light header background so rows scrolling under it are covered */
  background: var(--neutral-50, #f4f7f5);
}
/* Filter bars wrap (taller frozen head) as the viewport narrows — reserve more
   so the page never gets a competing second scrollbar. */
@media (max-width: 992px) {
  .table-sticky-head { max-height: calc(100vh - var(--topbar-h) - 300px); }
}
@media (max-width: 576px) {
  /* On phones, drop the bounded scroll entirely — the whole page scrolls and a
     sticky thead inside a short container just gets in the way. */
  .table-sticky-head { max-height: none; overflow-y: visible; }
  .table-sticky-head thead th { position: static; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   VOICE NOTES (Batch 40) — mic button injected by voice-notes.js into any
   textarea marked data-voice-notes. Pulses red while listening.
   ══════════════════════════════════════════════════════════════════════════════ */
.voice-notes-btn {
  position: absolute;
  top: 4px;
  right: 4px;
  padding: 2px 8px;
  color: #6b7a70;
  background: rgba(255, 255, 255, .85);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-pill);
  line-height: 1;
  z-index: 3;
}
.voice-notes-btn:hover { color: var(--vaste-green-text); border-color: var(--vaste-green-light); }
.voice-notes-btn.voice-notes-listening {
  color: #fff;
  background: var(--color-error);
  border-color: var(--color-error);
  animation: voiceNotesPulse 1.2s ease-in-out infinite;
}
@keyframes voiceNotesPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(201, 59, 32, .45); }
  50% { box-shadow: 0 0 0 6px rgba(201, 59, 32, 0); }
}
.voice-notes-hint { margin-top: .25rem; }

/* ── Sent Emails (Growth) ─────────────────────────────────────────────── */
.clickable-row[data-href] { cursor: pointer; }
/* Dashboard stat cards wrapped in links must look clickable. */
a .stat-card { cursor: pointer; }
/* Anchored jumps (e.g. #followup-{id}) land below the fixed topbar. */
[id] { scroll-margin-top: 72px; }

@media (prefers-reduced-motion: reduce) {
  .voice-notes-btn.voice-notes-listening { animation: none; }
}

/* Respect reduced-motion: hover lifts and kanban/board transitions settle
   instantly; the voice-notes pulse guard lives beside its keyframes. */
@media (prefers-reduced-motion: reduce) {
  /* Cards: kill both the transition and the hover lift. */
  .stat-card, .stat-card:hover,
  .company-card, .company-card:hover,
  .kanban-card {
    transition: none !important;
    transform: none !important;
  }
  /* Sidebar: only the transition — its mobile off-canvas hiding is
     transform-based, so forcing transform:none would pin it open. */
  .sidebar, .sidebar-link {
    transition: none !important;
  }
}

/* ── Partner lead hover card ───────────────────────────────────────────────────
   The operator name on a partner's lead table opens a status card. See
   resources/views/partners/_lead_card.blade.php and initLeadCards() in app.js.

   The trigger needs an affordance: a hover card nobody knows is there is a
   hover card nobody uses. A dotted underline that solidifies on hover says
   "there is more here" without adding a column to a table that is already
   eight columns of figures. */

.lead-card-link {
  text-decoration: underline dotted var(--bs-secondary-color, #6c757d) 1px;
  text-underline-offset: 3px;
}

.lead-card-link:hover,
.lead-card-link:focus-visible {
  text-decoration: underline solid var(--vaste-green) 1px;
  text-underline-offset: 3px;
}

.lead-card-popover {
  max-width: 22rem;
}

.lead-card-popover .popover-body {
  padding: 0;
}

.lead-card-body {
  padding: .75rem .875rem;
  font-size: .8125rem;
  line-height: 1.45;
}

.lead-card-head {
  padding-bottom: .5rem;
  margin-bottom: .5rem;
  border-bottom: 1px solid var(--bs-border-color, #dee2e6);
}

/* Label/value pairs on one grid so the three values line up whatever the label
   width — a <dl> left to itself stacks them and doubles the card's height. */
.lead-card-facts {
  display: grid;
  grid-template-columns: 3.25rem 1fr;
  gap: .3rem .6rem;
  margin: 0;
}

.lead-card-facts dt {
  font-weight: 500;
  color: var(--bs-secondary-color, #6c757d);
  text-transform: uppercase;
  font-size: .6875rem;
  letter-spacing: .02em;
  padding-top: .1rem;
}

.lead-card-facts dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: break-word;
}

.lead-card-notes {
  margin-top: .625rem;
  padding-top: .5rem;
  border-top: 1px solid var(--bs-border-color, #dee2e6);
  /* Long notes scroll inside the card rather than growing it off-screen; the
     300-character cap in the partial is the first defence, this is the second
     for a note that is 300 characters of unbroken text. */
  max-height: 9rem;
  overflow-y: auto;
}

/* Broadcast review — "+ Add email" / "+ Add first name" on a recipient row.
   Hidden until the row is hovered or focused, so a long list stays calm, but
   ONLY on devices that can hover: on a tablet or phone there is no hover, and
   an invisible-but-tappable button is worse than a visible one. focus-within
   keeps it reachable from the keyboard. Opacity, not display, so it stays in
   the tab order. */
@media (hover: hover) {
  .blast-recipient .blast-fix-open { opacity: 0; transition: opacity .12s ease-in-out; }
  .blast-recipient:hover .blast-fix-open,
  .blast-recipient:focus-within .blast-fix-open { opacity: 1; }
}

/* Newsletter body editor (Trix) */
.newsletter-editor { min-height: 16rem; max-height: 60vh; overflow-y: auto; font-size: .92rem; height: auto; }
.newsletter-editor h1 { font-size: 1.25rem; font-weight: 700; margin: .6em 0 .3em; }
.newsletter-editor ul, .newsletter-editor ol { padding-left: 1.5rem; }
/* Underline is drawn like Trix's own bold and italic icons, so it matches them. */
trix-toolbar .trix-button--icon-underline::before { background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M7%204h2v7a3%203%200%200%200%206%200V4h2v7a5%205%200%200%201-10%200V4Zm-1%2015h12v2H6v-2Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
trix-toolbar .trix-button-row { flex-wrap: wrap; }

/* Email builder (newsletters and client broadcasts): Text blocks start
   compact — the full-height editor is for a whole newsletter body. */
.email-block .newsletter-editor { min-height: 7rem; }
.email-block .card-header { border-bottom: 1px solid var(--bs-border-color-translucent); }
.email-table-editor input { min-width: 6rem; }

/* ══════════════════════════════════════════════════════════════════════════════
   BRAND BOOK v2 — the designer's answers (Oct 2026), loaded last so it wins.
   Colours come from vaste-tokens.css; the contrast adjustments (darker button
   fill and link green, dark text on Flamenco, full-white sidebar text on
   darker gradient stops, #66746F muted text) are asserted in
   tests/Unit/BrandContrastTest. Feel: Linear / Attio / Stripe — calm, flat
   tables, one status-pill system, no coloured edge accents anywhere.
   ══════════════════════════════════════════════════════════════════════════════ */

:root {
  --sidebar-w: 248px;
  --bs-primary: #048059;           --bs-primary-rgb: 4, 128, 89;
  --bs-success: #037A54;           --bs-success-rgb: 3, 122, 84;
  --bs-danger: #C8442E;            --bs-danger-rgb: 200, 68, 46;
  /* Warning is the status colour, never Flamenco (0.2: Flamenco is never a
     badge, border or background). */
  --bs-warning: #9A4300;           --bs-warning-rgb: 154, 67, 0;
  --bs-warning-bg-subtle: #FFE7CF; --bs-warning-border-subtle: #F5D0A9;
  --bs-warning-text-emphasis: #9A4300;
  --bs-info: #026044;              --bs-info-rgb: 2, 96, 68;
  --bs-link-color: #037A54;        --bs-link-color-rgb: 3, 122, 84;
  --bs-link-hover-color: #026044;  --bs-link-hover-color-rgb: 2, 96, 68;
  --bs-body-color: #374440;        --bs-body-color-rgb: 55, 68, 64;
  --bs-body-bg: #F7F9F8;
  --bs-border-color: #E1E7E5;
  --bs-secondary-color: #66746F;   --bs-secondary-rgb: 102, 116, 111;
  --bs-emphasis-color: #131A18;
  --bs-heading-color: #131A18;
  --bs-border-radius: 10px;
  --bs-border-radius-sm: 8px;
  --bs-border-radius-lg: 14px;
  --bs-focus-ring-color: rgba(4, 150, 104, 0.45);
  /* Form errors in the brand danger pair (0.6): text #A8371F, border #C8442E. */
  --bs-form-invalid-color: #A8371F;
  --bs-form-invalid-border-color: #C8442E;
  /* Disabled and sunken controls: #EEF2F1 (0.1 neutrals). */
  --bs-secondary-bg: #EEF2F1;
  --sidebar-bg: transparent;
}

/* ── Type: Inter Tight headings, Inter body, tabular figures ─────────────── */
body { font-family: var(--font-body); font-size: 14px; line-height: 20px; color: #374440; background: #F7F9F8; }
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6,
.page-header-title, .card-header, .card-title, .modal-title {
  font-family: var(--font-display);
  font-weight: 600;
  color: #131A18;
  letter-spacing: 0;
}
.page-header-title { font-size: 24px; line-height: 32px; }
.card-header, .card-title { font-size: 16px; line-height: 24px; }
/* Body 14/20 and small 12/16 (0.3). vaste-tokens.css sets p at 15px. */
p, .body { font-size: 14px; line-height: 20px; }
.small, small { font-size: 12px; line-height: 16px; }
.page-header-eyebrow {
  font-family: var(--font-body); font-size: 12px; line-height: 16px; font-weight: 500;
  text-transform: uppercase; letter-spacing: .08em; color: var(--text-muted);
}
.page-header-subtitle, .text-muted, .form-text { color: var(--text-muted) !important; }
.table td, .table th, .stat-value, .kpi-value, .num, .text-end, .font-monospace-num { font-variant-numeric: tabular-nums; }

/* ── Focus: 3px Green Haze at 45% ────────────────────────────────────────── */
:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.btn:focus-visible, .btn:focus, .form-control:focus, .form-select:focus, .form-check-input:focus {
  box-shadow: var(--focus-ring) !important;
  border-color: #049668 !important;
}

/* ── Icons (0.10): 16px inline and in tables, 18px sidebar, 20px headers ─── */
svg.lucide { width: 16px; height: 16px; stroke-width: 2; }
/* An icon whose size is set on purpose keeps it: its own font-size or fs-*
   class, a parent that sizes it (a font-size, fs-*, or an *-icon container
   such as the empty-state circle and stat tile), and pills — whose icon size
   is an open question for Precious. */
svg.lucide[style*="font-size"], svg.lucide:is(.fs-1, .fs-2, .fs-3, .fs-4, .fs-5, .fs-6),
[style*="font-size"] > svg.lucide, :is(.fs-1, .fs-2, .fs-3, .fs-4, .fs-5, .fs-6) > svg.lucide,
:is(.empty-state-icon, .stat-icon, .timeline-icon) > svg.lucide { width: 1em; height: 1em; }
.sidebar-link svg.lucide { width: 18px; height: 18px; }
/* Small icons (round 5, answer 5): 12px in a pill; 14px in the 28px timeline
   circle and the 32px admin strip (set where those are styled). */
.badge svg.lucide { width: 12px; height: 12px; }
/* A standalone icon is grey; one in text or a link takes the text's colour
   (round 5, answer 4 — marked by vasteMarkStandaloneIcons in app.js). */
svg.lucide.lucide-standalone { color: #66746F; }

/* ── Top bar: white; search, actions and the user menu (no logo) ─────────── */
.topbar {
  left: var(--sidebar-w);
  box-shadow: none;
  border-bottom: 1px solid #E1E7E5;
  padding: 0 var(--sp-6);
}
.topbar-brand-mobile { display: none; }
/* The green "V" at 24px (round 5, answer 9). */
.topbar-lettermark { height: 24px; width: auto; display: block; }
.topbar-search-input { border-color: #CBD4D1; border-radius: 10px; background: #F7F9F8; }
.topbar-search-input:focus { box-shadow: var(--focus-ring); border-color: #049668; background: #fff; }
.topbar-search-input::placeholder { color: #9BA8A3; }
.topbar-avatar { background: #CDEAE1; color: #026044; font-weight: 600; font-size: 11px; }
.topbar-notif-btn:hover { color: #037A54; }

/* ── Sidebar: the brand gradient, full height, white logo on top ─────────── */
.sidebar {
  top: 0;
  width: var(--sidebar-w);
  background: var(--sidebar-gradient);
  border-right: 0;
  z-index: 1001;
  scrollbar-color: rgba(255,255,255,.3) transparent;
}
.sidebar-brand { display: block; padding: 18px 20px 14px; flex-shrink: 0; }
.sidebar-logo { height: 24px; width: auto; display: block; }
.sidebar-nav { padding: 0 0 var(--sp-3); }
.sidebar-section { margin-bottom: 0; }
.sidebar-section-label {
  font-size: 11px; line-height: 16px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .08em;
  color: #FFFFFF;
  padding: 20px 20px 6px;
}
.sidebar-link {
  min-height: 36px;
  padding: 0 12px;
  margin: 0 var(--sp-3) 2px;
  border-radius: 10px;
  color: #FFFFFF;
  font-size: 14px; font-weight: 500;
  gap: 10px;
}
.sidebar-link i, .sidebar-link .lucide { color: #FFFFFF; font-size: 18px; }
.sidebar-link:hover { background: var(--sidebar-hover-bg-dark); color: #FFFFFF; }
.sidebar-link.active { background: var(--sidebar-selected-bg); color: #FFFFFF; font-weight: 600; }
.sidebar-link.active i, .sidebar-link.active .lucide { color: #FFFFFF; }
/* Sidebar counts: #013D2B at 40%, white 11px 600 — quiet numbers that
   pass AA at both ends of the gradient (7.09:1 and 9.25:1). White at 20%
   was 3.49:1 at the top, and more white only lowers it. A count that means
   something needs action (overdue, open P1s) takes the Danger fill. */
.sidebar-link .sidebar-count { background: rgba(1,61,43,.4); color: #FFFFFF; font-size: 11px; font-weight: 600; }
.sidebar-link .sidebar-count.sidebar-count-danger { background: #C8442E; color: #FFFFFF; }
.sidebar-footer { border-top: 1px solid rgba(255,255,255,.18); }
.sidebar-new-btn { background: #FFFFFF; color: #013D2B; border-radius: 10px; font-weight: 600; }
.sidebar-new-btn:hover { background: #EAF6F1; color: #013D2B; }
.sidebar-user { border-top: 1px solid rgba(255,255,255,.18); }
.sidebar-user-avatar { background: #CDEAE1; color: #026044; }
.sidebar-user-name, .sidebar-user-role { color: #FFFFFF; }
.sidebar-user-logout { color: #FFFFFF; }
.sidebar-user-logout:hover { color: #FFE7CF; }
.sidebar .text-muted, .sidebar small { color: #FFFFFF !important; }

@media (max-width: 991px) {
  .topbar { left: 0; padding: 0 var(--sp-4); }
  .topbar-brand-mobile { display: flex; }
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  --bs-btn-border-radius: 10px;
  /* 20px lines: 7+20+7+2 = 36px default, 5+20+5+2 = 32px compact (0.7). */
  --bs-btn-line-height: 20px;
  /* 0.7: 10px. An older rule gave .btn a fixed 6px radius, which beat
     the variable on every button. */
  border-radius: var(--bs-btn-border-radius);
  --bs-btn-font-weight: 500;
  --bs-btn-font-size: 14px;
  --bs-btn-padding-y: .4375rem;
  --bs-btn-padding-x: .875rem;
  min-height: 36px;
  display: inline-flex; align-items: center; justify-content: center; gap: .375rem;
  transition: background-color .12s, border-color .12s, color .12s, transform .12s;
}
.btn:active { transform: translateY(1px); }
.btn-sm { --bs-btn-padding-y: .3125rem; --bs-btn-padding-x: .625rem; --bs-btn-font-size: 13px; --bs-btn-border-radius: 10px; min-height: 32px; }
.btn-lg { min-height: 40px; --bs-btn-font-size: 15px; --bs-btn-border-radius: 10px; }
.btn-sm.py-0, .btn.py-0 { min-height: 0; }
.btn-primary, .btn-success {
  --bs-btn-bg: #048059; --bs-btn-border-color: #048059; --bs-btn-color: #fff;
  --bs-btn-hover-bg: #037A54; --bs-btn-hover-border-color: #037A54; --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #026044; --bs-btn-active-border-color: #026044; --bs-btn-active-color: #fff;
  --bs-btn-disabled-bg: #9BD5C3; --bs-btn-disabled-border-color: #9BD5C3; --bs-btn-disabled-color: #fff;
}
.btn-secondary, .btn-light, .btn-outline-secondary {
  --bs-btn-bg: #FFFFFF; --bs-btn-color: #232D2A; --bs-btn-border-color: #CBD4D1;
  --bs-btn-hover-bg: #F7F9F8; --bs-btn-hover-color: #131A18; --bs-btn-hover-border-color: #CBD4D1;
  --bs-btn-active-bg: #EEF2F1; --bs-btn-active-color: #131A18; --bs-btn-active-border-color: #9BA8A3;
  --bs-btn-disabled-bg: #FFFFFF; --bs-btn-disabled-color: #9BA8A3; --bs-btn-disabled-border-color: #E1E7E5;
}
.btn-outline-primary, .btn-outline-success {
  --bs-btn-bg: transparent; --bs-btn-color: #037A54; --bs-btn-border-color: #049668;
  --bs-btn-hover-bg: #EAF6F1; --bs-btn-hover-color: #026044; --bs-btn-hover-border-color: #049668;
  --bs-btn-active-bg: #CDEAE1; --bs-btn-active-color: #013D2B; --bs-btn-active-border-color: #037A54;
}
.btn-danger {
  --bs-btn-bg: #C8442E; --bs-btn-border-color: #C8442E; --bs-btn-color: #fff;
  --bs-btn-hover-bg: #B33C28; --bs-btn-hover-border-color: #B33C28; --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #A8371F; --bs-btn-active-border-color: #A8371F;
}
/* Red-outline buttons are Secondary with danger text (round 5, answer 7). */
.btn-outline-danger {
  --bs-btn-bg: #FFFFFF; --bs-btn-color: #A8371F; --bs-btn-border-color: #CBD4D1;
  --bs-btn-hover-bg: #F7F9F8; --bs-btn-hover-color: #A8371F; --bs-btn-hover-border-color: #CBD4D1;
  --bs-btn-active-bg: #EEF2F1; --bs-btn-active-color: #A8371F; --bs-btn-active-border-color: #9BA8A3;
  --bs-btn-disabled-bg: #FFFFFF; --bs-btn-disabled-color: #9BA8A3; --bs-btn-disabled-border-color: #E1E7E5;
}
.btn-link { --bs-btn-color: #037A54; --bs-btn-hover-color: #026044; text-decoration: none; }
.btn-link:hover { text-decoration: underline; }
/* Flamenco: the ONE call to action on a screen — only for something that
   leaves Vaste or cannot be undone (send a campaign, send a client email,
   approve & send in the Review Queue). Dark text: white on it is 2.6:1. */
.btn-cta {
  --bs-btn-bg: #FF7B0F; --bs-btn-border-color: #FF7B0F; --bs-btn-color: #131A18;
  --bs-btn-hover-bg: #F06E05; --bs-btn-hover-border-color: #F06E05; --bs-btn-hover-color: #131A18;
  --bs-btn-active-bg: #E06400; --bs-btn-active-border-color: #E06400; --bs-btn-active-color: #131A18;
  --bs-btn-disabled-bg: #FFC79A; --bs-btn-disabled-border-color: #FFC79A; --bs-btn-disabled-color: #4E5B57;
  font-weight: 600;
}
/* While a confirm dialog is open, the page's own orange button is GREY
   (Precious, round 3): the dialog's confirm is then the one orange in view. */
.btn-cta.is-greyed, .btn-cta.is-greyed:disabled {
  --bs-btn-disabled-bg: #E1E7E5; --bs-btn-disabled-border-color: #E1E7E5; --bs-btn-disabled-color: #66746F;
  --bs-btn-disabled-opacity: 1;
}

/* ── Forms ───────────────────────────────────────────────────────────────── */
.form-control, .form-select { border-color: #CBD4D1; border-radius: 10px; color: #131A18; }
.form-control::placeholder { color: #9BA8A3; }
.form-check-input:checked { background-color: #048059; border-color: #048059; }
/* Form errors: no icon inside the field (Precious) — the red border and the
   message under it already say what is wrong, and the browser's own icon
   differs between browsers. Padding goes back to the field's own. */
.form-control.is-invalid, .was-validated .form-control:invalid { background-image: none; padding-right: .75rem; }
/* Bootstrap's own selectors, or theirs win on specificity (a single-line select only;
   a multi-line one never had an icon). A textarea gives back its extra padding too. */
.form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"],
.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"] { --bs-form-select-bg-icon: none; padding-right: 2.25rem; }
textarea.form-control.is-invalid, .was-validated textarea.form-control:invalid { padding-right: .75rem; }
.form-control-sm.is-invalid, .was-validated .form-control-sm:invalid { padding-right: .5rem; }
/* Switch knob: #9BA8A3 at rest, Green Haze on focus, white when on. */
.form-switch .form-check-input { --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%239BA8A3'/%3e%3c/svg%3e"); border-color: #CBD4D1; }
.form-switch .form-check-input:focus { --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23049668'/%3e%3c/svg%3e"); }
.form-switch .form-check-input:checked { --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); }
/* Labels: #374440, 500, 13px, 6px below (round 5, answer 13) — grey or
   bold utilities on a label give way, so every form reads the same. */
.form-label, .form-label.small, .form-label.fw-semibold, .form-label.fw-bold, .form-label.text-muted {
  color: #374440 !important; font-weight: 500 !important; font-size: 13px; line-height: 18px;
}
.form-label, .form-label.mb-1, .form-label.mb-2 { margin-bottom: 6px !important; }
.form-label.mb-0 { margin-bottom: 0 !important; } /* a label inline beside its control */
/* Heights (0.7, round 5 answer 3): 40px inputs, selects and the submit
   button on a full-page form (.form-page); 36px everywhere else, compact
   rows included. Textareas and the Trix editors keep their own height. */
.form-control:not(textarea):not(trix-editor), .form-select { min-height: 36px; padding-top: .3125rem; padding-bottom: .3125rem; }
.form-control-sm:not(textarea):not(trix-editor), .form-select-sm { min-height: 36px; }
.form-page .form-control:not(textarea):not(trix-editor):not(.form-control-sm), .form-page .form-select:not(.form-select-sm) {
  min-height: 40px; padding-top: .4375rem; padding-bottom: .4375rem;
}
.form-page .btn-primary:not(.btn-sm), .form-page [type="submit"].btn:not(.btn-sm) { min-height: 40px; }
/* …and the buttons beside it (Cancel), so the row lines up. A rule of its
   own: a browser without :has drops only this, not the sizes above. */
.form-page :has(> [type="submit"].btn:not(.btn-sm)) > .btn:not(.btn-sm),
.form-page:has(> [type="submit"].btn:not(.btn-sm)) > .btn:not(.btn-sm) { min-height: 40px; }

/* ── Cards and modals ────────────────────────────────────────────────────── */
.card { border: 1px solid #E1E7E5; border-radius: 14px; box-shadow: 0 1px 2px rgba(19,26,24,.06); background: #fff; }
.card.border-0 { border: 1px solid #E1E7E5 !important; }
.card-header { background: #fff; border-bottom: 1px solid #E1E7E5; }
.card-header:first-child { border-radius: 14px 14px 0 0; }
.modal-content { border-radius: 14px; border-color: #E1E7E5; }
/* Confirm dialog: white, title Inter Tight 600 18px (round 5, answer 10). */
.vaste-confirm-title { font-family: var(--font-display); font-weight: 600; font-size: 18px; line-height: 24px; color: #131A18; margin: 0; }
.dropdown-menu { border-radius: 10px; border-color: #E1E7E5; }

/* ── Tables: flat, 44px rows, white sticky header, no stripes ────────────── */
.table {
  --bs-table-bg: transparent;
  --bs-table-border-color: #E1E7E5;
  --bs-table-hover-bg: #F7F9F8;
  --bs-table-striped-bg: transparent;
  --bs-table-active-bg: #EAF6F1;
  color: #374440;
  font-size: 14px;
}
/* 44px rows (0.8): 11.5px + 20px line + 11.5px + the 1px rule. */
.table > :not(caption) > * > * { padding: .71875rem .75rem; }
.table-sm > :not(caption) > * > * { padding: .4375rem .625rem; }
.table > thead th, .table > .table-light > * > th, .table-light th {
  background: #fff !important;
  color: #66746F;
  font-size: 12px; line-height: 16px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em;
  border-bottom: 1px solid #CBD4D1 !important;
  white-space: nowrap;
}
.table > thead { color: #66746F; font-size: 12px; }
.table tr.selected > *, .table tr.table-active > * { background: #EAF6F1; }
/* Header sticky on scroll (0.8). A page-level table sticks under the top
   bar and any sticky page head (--page-head-h, measured in app.js).
   Single-row heads only: two rows stuck at one offset would overlap. */
.table > thead > tr:only-child > th { position: sticky; top: calc(var(--topbar-h) + var(--page-head-h, 0px)); z-index: 2; }
/* A table that scrolls sideways gets its OWN scroll box (the owner's
   answer): at most calc(100vh - 220px) tall, scrolling both ways inside its
   frame, header pinned at the top and the first column on the left — these
   are the tables people work through row by row. "Scrolls sideways" is
   MEASURED (vasteTableBoxes in app.js marks .is-sideways): a wrapped table
   that fits is marked .fits and drops the wrapper's overflow, so the page
   carries its header like any other table and there is no second
   scrollbar. Where the first column is only a row checkbox (.pin-two), the
   column after it is pinned too, so the name stays in view. The
   .table-sticky-head lists keep their own reserve for the filters above
   them. On phones the page scrolls instead (the earlier phone rule).
   Without JS the wrapper is Bootstrap's plain sideways scroller. */
.table-responsive.fits { overflow: visible; }
.table-responsive:not(.fits) .table > thead > tr > th { position: static; }
@media (min-width: 577px) {
  .table-responsive.is-sideways:not(.table-sticky-head) { max-height: calc(100vh - 220px); overflow: auto; }
  .table-sticky-head .table > thead > tr:only-child > th,
  .table-responsive.is-sideways .table > thead > tr:only-child > th { position: sticky; top: 0; z-index: 2; }
  /* Collapsed borders do not travel with a pinned cell; separate ones do.
     Not on .table-bordered: Bootstrap draws its row lines on the <tr>,
     which separate borders never paint. */
  .table-responsive.is-sideways .table:not(.table-bordered) { border-collapse: separate; border-spacing: 0; }
  .table-responsive.is-sideways .table > :is(thead, tbody, tfoot) > tr > :first-child,
  .table-responsive.is-sideways .table.pin-two > :is(thead, tbody, tfoot) > tr > :nth-child(2) {
    position: sticky; left: 0; z-index: 1; background-color: var(--sticky-cell-bg, #FFFFFF);
    /* A tinted row (.table-danger…) sets --bs-table-bg: layer it over the
       white so the pinned cell keeps the row's colour. */
    background-image: linear-gradient(var(--bs-table-bg), var(--bs-table-bg));
  }
  .table-responsive.is-sideways .table.pin-two > :is(thead, tbody, tfoot) > tr > :nth-child(2) { left: var(--pin1-w, 0px); }
  /* The pinned header cells sit above the header cells scrolling under
     them (th + :first-child outranks the tr:only-child > th header rule). */
  .table-responsive.is-sideways .table > thead > tr > th:first-child,
  .table-responsive.is-sideways .table.pin-two > thead > tr > th:nth-child(2) { z-index: 3; }
}
/* Printed, every table is whole: no box, nothing pinned. */
@media print {
  .table-responsive { max-height: none !important; overflow: visible !important; }
  .table-responsive .table > :is(thead, tbody, tfoot) > tr > * { position: static !important; }
}
/* The pinned cell covers what scrolls under it, so it carries the row's
   own selected colour; hover and tinted rows paint over it as before. */
.table tr.selected, .table tr.table-active { --sticky-cell-bg: #EAF6F1; }
/* Row hover #F7F9F8 on every table (0.8) — through the row's OWN hover
   colour, so a tinted row darkens as before; selected rows keep #EAF6F1. */
.table > tbody > tr:not(.selected):not(.table-active):hover > * { --bs-table-bg-state: var(--bs-table-hover-bg); }

/* ── Status pills: ONE system — soft background, darker text, 6px dot ───── */
.vaste-badge, .badge {
  display: inline-flex; align-items: center; gap: 5px;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 12px; line-height: 16px; font-weight: 500;
  padding: 2px 8px;
  letter-spacing: 0;
  white-space: nowrap;
}
.vaste-badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.vaste-badge-active, .vaste-badge-success   { background: var(--status-success-bg); color: var(--status-success-text); }
.vaste-badge-pending, .vaste-badge-warning  { background: var(--status-warning-bg); color: var(--status-warning-text); }
.vaste-badge-risk, .vaste-badge-danger      { background: var(--status-danger-bg);  color: var(--status-danger-text); }
.vaste-badge-info                           { background: var(--status-info-bg);    color: var(--status-info-text); }
.vaste-badge-default, .vaste-badge-neutral  { background: var(--status-neutral-bg); color: var(--status-neutral-text); }
.vaste-badge-default .vaste-badge-dot { background: currentColor; }
/* A pending task with no deadline yet (Precious, Manage people round 6) — grey, set apart from green status pills. */
.vaste-badge-neutral-strong                 { background: #EEF2F1; color: #374440; }
.vaste-badge-brand                          { background: var(--status-info-bg); color: var(--status-info-text); } /* no solid pills but danger */
.vaste-badge-danger-solid                   { background: var(--status-danger-solid); color: #fff; }
/* People's "Active" (Precious, 24 Oct): solid green, at the button fill #048059 — white on her #049668 is 3.77:1. */
.vaste-badge-success-solid                  { background: #048059; color: #fff; }
.vaste-badge-outline                        { background: transparent; color: #4E5B57; box-shadow: inset 0 0 0 1px #CBD4D1; }
/* Compliance category (Precious, answer 11): white, #037A54 text, 1px #9BD5C3. */
.vaste-badge-compliance                     { background: #fff; color: #037A54; box-shadow: inset 0 0 0 1px #9BD5C3; }
/* Bootstrap badges map onto the same five roles, so ~140 existing call
   sites take the brand pill without being touched one by one. A solid red
   badge stays the FILLED danger form (counts, P1); every other tone is soft. */
.badge.bg-success, .badge.text-bg-success, .badge.bg-success-subtle, .badge.bg-primary, .badge.text-bg-primary, .badge.bg-primary-subtle
  { background: var(--status-success-bg) !important; color: var(--status-success-text) !important; }
.badge.bg-warning, .badge.text-bg-warning, .badge.bg-warning-subtle
  { background: var(--status-warning-bg) !important; color: var(--status-warning-text) !important; }
.badge.bg-danger, .badge.text-bg-danger
  { background: var(--status-danger-solid) !important; color: #fff !important; }
.badge.bg-danger-subtle
  { background: var(--status-danger-bg) !important; color: var(--status-danger-text) !important; }
.badge.bg-info, .badge.text-bg-info, .badge.bg-info-subtle
  { background: var(--status-info-bg) !important; color: var(--status-info-text) !important; }
.badge.bg-secondary, .badge.text-bg-secondary, .badge.bg-secondary-subtle, .badge.bg-light, .badge.text-bg-light, .badge.bg-dark-subtle
  { background: var(--status-neutral-bg) !important; color: var(--status-neutral-text) !important; }
.badge.bg-dark, .badge.text-bg-dark { background: #013D2B !important; color: #fff !important; }
.text-success, .text-success-emphasis { color: var(--status-success-text) !important; }
.text-warning, .text-warning-emphasis { color: var(--status-warning-text) !important; }
.text-danger, .text-danger-emphasis   { color: var(--status-danger-text) !important; }
.text-info, .text-info-emphasis       { color: var(--status-info-text) !important; }
.text-primary, .text-primary-emphasis { color: #037A54 !important; }
.bg-success-subtle { background-color: var(--status-success-bg) !important; }
.bg-warning-subtle { background-color: var(--status-warning-bg) !important; }
.bg-danger-subtle  { background-color: var(--status-danger-bg) !important; }
.bg-info-subtle    { background-color: var(--status-info-bg) !important; }
.bg-secondary-subtle, .bg-light { background-color: var(--status-neutral-bg) !important; }

/* ── Alerts: a tinted card, icon, bold title, one action. No edge accents. ── */
.alert { border-radius: 14px; border-width: 1px; border-left-width: 1px !important; padding: .875rem 1rem; }
.alert-success { background: var(--status-success-bg); border-color: #CDEAE1; color: var(--status-success-text); }
.alert-warning { background: var(--status-warning-bg); border-color: #F5D0A9; color: var(--status-warning-text); }
.alert-danger  { background: var(--status-danger-bg);  border-color: #F1C6BD; color: var(--status-danger-text); }
.alert-info    { background: var(--status-info-bg);    border-color: #9BD5C3; color: var(--status-info-text); }
.alert-light, .alert-secondary { background: #fff; border-color: #E1E7E5; color: #374440; }
.alert .alert-link { color: inherit; }
/* The brand rules out coloured edge accents anywhere: a card or box that
   used one (border-start border-4, inline border-left) reads as a plain
   bordered card instead. Thin neutral guide lines inside cards are kept. */
.border-start.border-3, .border-start.border-4 { border-left-width: 1px !important; border-left-color: #E1E7E5 !important; }

/* ── Big-number tiles (the email tile, in the CRM) ───────────────────────── */
.stat-card, .kpi-card {
  background: #EAF6F1;
  border: 0 !important;
  border-radius: 14px;
  box-shadow: none !important;
}
.stat-card .card-body { padding: 20px; }
.stat-card:hover { transform: none; box-shadow: none !important; }
/* Tile labels on the light green tiles are #4E5B57 (Precious, answer 10:
   6.41:1 on #EAF6F1); muted text everywhere else is --text-muted #66746F. */
.stat-label { font-size: 12px; line-height: 16px; font-weight: 500; color: #4E5B57; text-transform: none; letter-spacing: 0; }
.stat-card .text-muted { color: #4E5B57 !important; }
.stat-card .stat-value, .kpi-card .kpi-value {
  font-family: var(--font-display);
  font-size: 32px; line-height: 36px; font-weight: 600;
  color: #049668;
}
.stat-card .stat-unit { color: #4E5B57; }
/* "None outstanding" in place of a 0 (Precious, 30 Oct): muted words, so a
   highlighted tile with nothing to do does not read as an alert. */
.stat-card .stat-value-empty { font-size: 14px; line-height: 20px; font-weight: 500; color: #4E5B57; padding-top: 8px; }
.stat-card .stat-sub { color: #037A54; font-size: 12px; }
.stat-card .stat-sub.is-negative { color: #A8371F; }
.stat-card .stat-icon i, .stat-card .stat-icon .lucide { color: #049668; }
/* The one highlighted tile per screen (Precious, 2026-10): #CDEAE1 against
   #EAF6F1 for the rest, figure #026044 Inter Tight 600 32px, label #4E5B57.
   The tint alone marks it out — no border or shadow change, never a solid
   green block. BrandUsageTest allows one per view. */
.stat-card.is-accent, .stat-card.is-highlight { background: #CDEAE1 !important; border-color: #CDEAE1 !important; }
.stat-card.is-accent .stat-value, .stat-card.is-highlight .stat-value,
.stat-card.is-accent .fs-2, .stat-card.is-highlight .fs-2 { color: #026044 !important; }
.stat-card.is-accent .stat-label, .stat-card.is-highlight .stat-label,
.stat-card.is-accent .text-muted, .stat-card.is-highlight .text-muted,
.stat-card.is-accent .stat-sub, .stat-card.is-highlight .stat-sub,
.stat-card.is-accent .stat-unit, .stat-card.is-highlight .stat-unit { color: #4E5B57 !important; }
.stat-card.is-accent .stat-icon, .stat-card.is-highlight .stat-icon { background: rgba(255,255,255,.6) !important; }
.stat-card.is-accent .stat-icon i, .stat-card.is-accent .stat-icon .lucide,
.stat-card.is-highlight .stat-icon i, .stat-card.is-highlight .stat-icon .lucide { color: #026044 !important; }

/* ── Empty screens: icon in a tint circle, short title, one line ─────────── */
.empty-state { text-align: center; padding: 48px 16px; }
.empty-state-icon {
  width: 48px; height: 48px; border-radius: 50%;
  background: #EAF6F1; color: #049668;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 24px; margin-bottom: 12px;
}
.empty-state-title { font-family: var(--font-display); font-size: 18px; line-height: 24px; font-weight: 600; color: #131A18; margin-bottom: 4px; }
.empty-state-text { color: #66746F; max-width: 32rem; margin: 0 auto 16px; }

/* ── Links, pagination, list groups, progress, nav tabs ──────────────────── */
a { color: #037A54; }
a:hover { color: #026044; }
.page-link { color: #037A54; border-color: #E1E7E5; }
.page-item.active .page-link { background: #048059; border-color: #048059; color: #fff; }
.list-group-item { border-color: #E1E7E5; }
.list-group-item-action:hover { background: #F7F9F8; }
.progress { background: #E1E7E5; border-radius: 999px; }
.progress-bar { background-color: #049668; }
.nav-tabs .nav-link.active { color: #131A18; border-bottom-color: #049668; }
.nav-tabs .nav-link { color: #66746F; }
.nav-pills .nav-link.active { background: #048059; }
.tooltip-inner { background: #013D2B; border-radius: 10px; font-size: 12px; max-width: 280px; text-align: left; }
.tooltip { --bs-tooltip-bg: #013D2B; }

/* ── Tinted cards: the brand book's replacement for coloured edge bars ─────
   The brand rules out a coloured left border as an accent. A callout that
   needs a tone gets a soft fill and a matching hairline instead. */
.tint-success { background: #EAF6F1 !important; border: 1px solid #CDEAE1 !important; }
.tint-info    { background: #CDEAE1 !important; border: 1px solid #9BD5C3 !important; }
.tint-warning { background: #FFE7CF !important; border: 1px solid #F8CFA6 !important; }
.tint-danger  { background: #FBEAE7 !important; border: 1px solid #F2C6BE !important; }
.tint-neutral, .tint-secondary { background: #F7F9F8 !important; border: 1px solid #E1E7E5 !important; }
.tint-note { background: #F7F9F8; border-radius: 6px; padding: 4px 8px; }
.tint-note.is-danger { background: #FBEAE7; }

/* ══════════════════════════════════════════════════════════════════════════
   BRAND BOOK v2 — SECTION VISUALS (PR 2). Patterns the section pages share.
   ══════════════════════════════════════════════════════════════════════════ */

/* Pills: the Admin role, and icons inside a pill. */
.vaste-badge-dark { background: #013D2B; color: #fff; }
.vaste-badge .lucide, .vaste-badge i[data-lucide] { width: 12px; height: 12px; stroke-width: 2; }

/* Round initials avatar (C1). */
.vaste-avatar {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  border-radius: 50%; background: #CDEAE1; color: #026044;
  font-family: 'Inter', system-ui, sans-serif; font-weight: 600; letter-spacing: .02em; line-height: 1;
}

/* Trend under a big number (A4): the colour says good or bad, not direction. */
.trend-good { color: #037A54 !important; }
.trend-bad { color: #A8371F !important; }
.trend-neutral { color: #4E5B57 !important; }   /* Precious, answer 7: the tile label colour — every neutral trend sits on a tile */

/* Thin progress bar beside "5 of 8" (F2, J4). */
.progress-thin { height: 6px; background: #E1E7E5; border-radius: 999px; overflow: hidden; }
.progress-thin > span { display: block; height: 100%; background: #049668; border-radius: 999px; }

/* Checklist step states (F2, J4): done / current / not done. */
.step-mark {
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid #CBD4D1; background: #fff; color: #fff;
}
.step-mark .lucide { width: 12px; height: 12px; stroke-width: 2; }
.step-done .step-mark { background: #049668; border-color: #049668; }
.step-current .step-mark { border-color: #049668; }
.step-current .step-text { font-weight: 600; color: #131A18; }
.step-todo .step-text { color: #66746F; }

/* Timeline (C4): one grey icon circle per type, joined by a hairline, by day. */
.vt-day { font-size: 12px; font-weight: 600; color: #66746F; text-transform: uppercase; letter-spacing: .06em; margin: 16px 0 8px; }
.vt-day:first-child { margin-top: 0; }
.vt-item { position: relative; display: flex; gap: 12px; padding-bottom: 16px; }
.vt-item::before { content: ""; position: absolute; left: 13.5px; top: 28px; bottom: 0; width: 1px; background: #E1E7E5; }
.vt-item:last-child::before { display: none; }
.vt-icon {
  width: 28px; height: 28px; border-radius: 50%; background: #EEF2F1; color: #4E5B57; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.vt-icon > svg.lucide, .vt-icon .lucide { width: 14px; height: 14px; }

/* Kanban (D1–D3): #EEF2F1 lanes, colour only in the stage dot. */
.stage-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; }

/* Ticket thread (G3). */
.msg-card { border-radius: 14px; padding: 12px 16px; margin-bottom: 12px; }
.msg-client { background: #fff; border: 1px solid #E1E7E5; }
.msg-ours { background: #EAF6F1; border: 1px solid #CDEAE1; }
.msg-note, .reply-note-mode {
  background: #F7F9F8 !important; border: 1px dashed #9BA8A3 !important;
}
.msg-note-label { font-weight: 700; color: #374440; font-size: 12px; display: inline-flex; align-items: center; gap: 4px; }

/* Admin strip (J1): slim, deep green, across the top of the content. */
.admin-strip {
  background: #013D2B; color: #fff; height: 32px;
  display: flex; align-items: center; gap: 8px;
  /* Across the top of the content area (J1): cancel .main-content's padding. */
  margin: calc(-1 * var(--sp-8)) calc(-1 * var(--sp-8)) var(--sp-6);
  padding: 0 var(--sp-8);
  font-size: 12px; font-weight: 500;
}
@media (max-width: 991px) {
  .admin-strip { margin: calc(-1 * var(--sp-5)) calc(-1 * var(--sp-4)) var(--sp-5); padding: 0 var(--sp-4); }
}
@media (max-width: 576px) {
  .admin-strip { margin: calc(-1 * var(--sp-4)) calc(-1 * var(--sp-3)) var(--sp-4); padding: 0 var(--sp-3); }
}
.admin-strip .lucide { width: 14px; height: 14px; }

/* "AI draft" marker (H1) — neutral, never a special colour. */
.ai-marker .lucide { width: 12px; height: 12px; }

/* Older status classes, mapped onto the brand tones (BrandPill) so every
   view that still uses them agrees with x-status-badge. */
.badge.badge-tag { background: #EEF2F1 !important; color: #4E5B57 !important; font-weight: 500; }
.badge.badge-supplier { background: var(--status-success-bg) !important; color: var(--status-success-text) !important; }
.badge.badge-buyer, .badge.badge-compliance { background: var(--status-info-bg) !important; color: var(--status-info-text) !important; }
.badge.badge-other, .badge.badge-partner { background: var(--status-neutral-bg) !important; color: var(--status-neutral-text) !important; }
.badge.badge-status-prospect { background: var(--status-info-bg) !important; color: var(--status-info-text) !important; }
.badge.badge-status-active { background: var(--status-success-bg) !important; color: var(--status-success-text) !important; }
.badge.badge-status-dormant { background: var(--status-neutral-bg) !important; color: var(--status-neutral-text) !important; }
.badge.badge-status-lost { background: var(--status-danger-bg) !important; color: var(--status-danger-text) !important; }
.badge.badge-role-admin { background: #013D2B !important; color: #fff !important; }
.badge.badge-role-editor { background: var(--status-info-bg) !important; color: var(--status-info-text) !important; }
.badge.badge-role-viewer { background: var(--status-neutral-bg) !important; color: var(--status-neutral-text) !important; }
/* Deal stages: a neutral pill — the stage's colour lives in its dot (D1). */
.badge[class*="badge-deal-"] { background: var(--status-neutral-bg) !important; color: var(--status-neutral-text) !important; }
.badge.badge-deal-won { background: var(--status-success-bg) !important; color: var(--status-success-text) !important; }
.badge.badge-deal-lost { background: var(--status-danger-bg) !important; color: var(--status-danger-text) !important; }

/* Kanban (D1–D3): columns on #EEF2F1 so they read as lanes against the
   #F7F9F8 page (Precious, answer 9); cards stay white. */
.kanban-col { background: #EEF2F1; border-radius: 14px; }
.kanban-column-closed .kanban-col { background: #EEF2F1 !important; }
.kanban-column-closed .fw-semibold { opacity: 1; }
.kanban-col.drag-over { background: #EAF6F1 !important; outline-color: #049668; }
.kanban-column-header { box-shadow: none !important; background: var(--content-bg, #F7F9F8) !important; }
.kanban-card { background: #fff; border: 1px solid #E1E7E5 !important; border-radius: 10px !important; box-shadow: none !important; }
.kanban-card:hover { box-shadow: 0 1px 2px rgba(19,26,24,.06) !important; transform: none; border-color: #CBD4D1 !important; }
.kanban-card .card-body { padding: 12px; }
/* Card type: ONE scale (owner-approved, 2026-10). The company name and the
   value are the same face and size — 14px/600 Inter — so the money no longer
   reads as a different font; the deal title under it is 12px muted; every
   pill is the brand pill (12px/500, above). The name wraps by WHOLE WORDS:
   `overflow-wrap: anywhere` broke it letter by letter ("H i.", "M a") once
   the action icons and the source tag squeezed the column. */
.kanban-card .deal-card-name {
  min-width: 0;
  font-family: var(--font-body); font-size: 14px; line-height: 20px; font-weight: 600;
  overflow-wrap: break-word; word-break: normal; hyphens: manual;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.kanban-card .deal-card-name a { color: #131A18; }
.kanban-card .deal-card-name a:hover { color: var(--bs-link-color); }
/* The clamp's overflow:hidden would clip the global focus ring: draw it inside. */
.kanban-card .deal-card-name a:focus-visible { box-shadow: none; outline: 2px solid #049668; outline-offset: -2px; }
.kanban-card .deal-card-sub {
  font-family: var(--font-body); font-size: 12px; line-height: 16px; color: var(--text-muted);
  margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kanban-card .deal-card-top { min-height: 18px; margin-bottom: 4px; }
.kanban-card .kanban-actions { flex: 0 0 auto; }
/* Brand inline icon size (16px), with a 24px tap target (WCAG 2.5.8) that
   does not move the layout. */
.kanban-card .kanban-actions [data-lucide], .kanban-card .kanban-actions svg { width: 16px; height: 16px; }
.kanban-card .kanban-actions .btn { padding: 4px !important; margin: -4px; }
.kanban-card .kanban-select { margin: 0; }
.kanban-card .deal-card-meta { margin-top: 10px; }
.kanban-card .deal-card-value { font-family: var(--font-body); font-size: 14px; line-height: 20px; font-weight: 600; color: #131A18; font-variant-numeric: tabular-nums; }
.kanban-card .deal-card-next { margin-top: 8px; }
/* The next action wraps rather than clipping mid-word; full text on hover. */
.kanban-card .deal-card-next .badge { max-width: 100%; white-space: normal; text-align: left; }

/* The step circle as a real checkbox (F2): keyboard and form behaviour stay. */
.step-check {
  appearance: none; -webkit-appearance: none; margin: 0; flex-shrink: 0; cursor: pointer;
  width: 20px; height: 20px; border-radius: 50%; border: 2px solid #CBD4D1; background: #fff;
}
.step-check:checked {
  background: #049668 url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M20 6 9 17l-5-5'/%3e%3c/svg%3e") center / 12px no-repeat;
  border-color: #049668;
}
.step-current .step-check { border-color: #049668; }
.step-check:focus-visible { outline: 0; box-shadow: var(--focus-ring); }
.step-check:disabled { cursor: default; }
.stat-card.stat-neutral .stat-value { color: #131A18; }

/* Warning-coloured text (F5's renewal date): the AA warning text shade. */
.text-warning-brand { color: #9A4300; }

/* Brand book A3: the alert card's icon is 20px. */
.vaste-alert-card .vaste-alert-icon { width: 20px; height: 20px; margin-top: 1px; }

/* Review Queue (H3): Reject is a secondary button in danger text. */
.btn.btn-danger-text, .btn.btn-danger-text:hover { color: #A8371F; }

/* The email builder (H2): a neutral #EEF2F1 canvas with grey controls, so
   the email in the preview is what stands out. */
[data-email-builder] { background: #EEF2F1; border-radius: 14px; padding: 16px; }

/* Chart cards (I2): a 16px Inter Tight title and a muted subtitle stating the
   period. Only a title that CARRIES a .chart-subtitle — scoped this way so the
   12px uppercase eyebrows (0.3) that share `h6.fw-semibold` are untouched. */
.card-body > h6.fw-semibold:has(> .chart-subtitle) { font-family: var(--font-display); font-size: 16px; line-height: 24px; color: #131A18; }
.chart-subtitle { display: block; font-family: 'Inter', system-ui, sans-serif; font-size: 12px; line-height: 16px; font-weight: 400; color: #66746F; margin-top: 2px; }

/* ── Signed-out pages (J3): the split screen ───────────────────────────── */
.auth-body { margin: 0; min-height: 100vh; background: #fff; }
.auth-split { display: flex; min-height: 100vh; }
.auth-panel {
  width: 50%; background: var(--sidebar-gradient, linear-gradient(150deg, #048059 0%, #037A54 50%, #026044 100%));
  color: #fff; display: flex; flex-direction: column; justify-content: space-between;
  padding: 56px 64px;
}
.auth-panel-inner { margin: auto 0; }
.auth-logo { height: 32px; width: auto; display: block; }   /* Precious: 32px, 28px in the narrow band */
.auth-strapline { margin-top: 16px;   /* Precious, answer 5: the logo's 16px clear space wins */ font-family: 'Inter', system-ui, sans-serif; font-size: 14px; font-weight: 400; color: rgba(255,255,255,.85); }
.auth-headline { margin-top: 32px; font-family: var(--font-display); font-size: 28px; line-height: 36px; font-weight: 500; color: #fff; max-width: 420px; }
.auth-main { width: 50%; display: flex; align-items: center; justify-content: center; padding: 48px 24px; }
.auth-form { width: 100%; max-width: 360px; }
.auth-form h1 { font-family: var(--font-display); font-size: 24px; line-height: 32px; font-weight: 600; color: #131A18; margin-bottom: 4px; }
.auth-form .auth-sub { color: #66746F; font-size: 14px; margin-bottom: 28px; }
.auth-form .form-control { height: 40px; }
.auth-form .btn-primary { height: 40px; }
@media (max-width: 899.98px) {
  .auth-split { flex-direction: column; }
  .auth-panel { width: 100%; padding: 20px 24px; }
  .auth-panel-inner { margin: 0; }
  .auth-logo { height: 28px; }
  .auth-strapline, .auth-headline { display: none; }
  .auth-main { width: 100%; padding: 32px 16px 48px; align-items: flex-start; }
}

/* ─────────────────────────────────────────────────────────────────────────
   PEOPLE (HR) — Precious's answers (23 Oct 2026).
   1. CRM | People switcher: two segments, 16px below the logo (its block has
      14px bottom padding, so 2px here) and 16px above the first nav item,
      16px side margins. Track: 1px rgba(255,255,255,.18) border, radius 10,
      padding 3. Segments 32px, radius 6, gap 2; Inter 500 13/1.25 white;
      hover white 8%; selected white with #013D2B 600 (12.3:1).
      CONTRAST FIX (the sidebar counts' precedent): the track is #013D2B at
      40%, not white at 12% — white on a white-tinted track is 4.0:1 at the
      top stop, under AA; on #013D2B 40% it is 7.10:1. More white only lowers
      white text's contrast.
   2. The "Confirm HR access" reminder: amber, no border (.alert-card-quiet).
   3. Owner / HR Admin role pills: their own style, apart from status pills.
   4. Visibility labels: "Team" plain muted text with a people icon; every
      restricted level a #EEF2F1 pill with a lock.
   5. Sidebar focus: a 2px WHITE outline everywhere in the green sidebar —
      the brand ring is ~1.3:1 there (an accessibility exception for the
      sidebar only; the Green Haze ring stays on white and light surfaces).
   ───────────────────────────────────────────────────────────────────────── */
.app-switcher {
  display: flex; gap: 2px; margin: 2px 16px 16px; padding: 3px;
  background: rgba(1, 61, 43, .4); border: 1px solid rgba(255, 255, 255, .18);
  border-radius: 10px;
}
.app-switcher-link {
  flex: 1 1 0; display: flex; align-items: center; justify-content: center;
  height: 32px; border-radius: 6px;
  color: #FFFFFF; font-family: 'Inter', sans-serif; font-size: 13px; line-height: 1.25;
  font-weight: 500; text-decoration: none;
}
.app-switcher-link:hover { color: #FFFFFF; background: rgba(255, 255, 255, .08); }
.app-switcher-link.active, .app-switcher-link.active:hover { background: #FFFFFF; color: #013D2B; font-weight: 600; }
/* 16px from the switcher to the first nav item: a first section label loses its top padding. */
.app-switcher + .sidebar-nav > .sidebar-section:first-child > .sidebar-section-label:first-child { padding-top: 0; }

/* 5. Focus in the green sidebar: white, 2px, 2px off. */
.sidebar a:focus-visible, .sidebar button:focus-visible, .sidebar input:focus-visible,
.sidebar select:focus-visible, .sidebar [tabindex]:focus-visible {
  outline: 2px solid #FFFFFF; outline-offset: 2px; box-shadow: none;
}

/* 2. A quiet amber card (no border, 16px icon, 14px text). */
.vaste-alert-card.alert-card-quiet {
  border: 0; border-radius: 10px; padding: 12px 16px; font-size: 14px;
  background: #FFE7CF; color: #9A4300;
}
.vaste-alert-card.alert-card-quiet .vaste-alert-icon { width: 16px; height: 16px; margin-top: 2px; color: #9A4300; }
.vaste-alert-card.alert-card-quiet .small { font-size: 14px; line-height: 20px; }
/* A quiet green note (Precious, People round 4): the same shape as the quiet
   amber card, in the soft brand tone — something to do before a deadline. */
.hr-note { background: #EAF6F1; color: #037A54; border-radius: 10px; padding: 12px 16px; font-size: 14px; line-height: 20px; }
.hr-note svg.lucide { width: 16px; height: 16px; margin-top: 2px; color: #037A54; flex-shrink: 0; }
/* Round 5: the secondary prompt under the note — 12px, same green, underlined so it reads as a link. */
.hr-note .hr-note-sub { display: inline-block; margin-top: 4px; font-size: 12px; line-height: 16px; color: #037A54; text-decoration: underline; }
/* Archived is history, not active: grey #EEF2F1/#374440, no icon (Precious, 3a; text confirmed 29 Oct). */
.hr-note.hr-note-neutral { background: #EEF2F1; color: #374440; }
/* Its target, the start date field, lands with its label in view below the top bar. */
#j_start { scroll-margin-top: 104px; }

/* 3. HR role pills. */
.hr-role-pill {
  display: inline-flex; align-items: center; height: 20px; padding: 2px 8px;
  border-radius: 999px; font-size: 12px; line-height: 16px; font-weight: 600; white-space: nowrap;
}
.hr-role-pill-owner { background: #013D2B; color: #FFFFFF; }
.hr-role-pill-admin { background: #EEF2F1; color: #374440; }

/* 4. Fields: label as .form-label; visibility inline 8px after it. */
.hr-field { margin-bottom: 16px; }
.hr-field-label {
  display: flex; align-items: center; gap: 8px; margin-bottom: 6px;
  color: #374440; font-size: 13px; line-height: 18px; font-weight: 500;
}
.hr-field-value { color: #131A18; font-size: 14px; line-height: 20px; }
/* An address or a list of contacts keeps its line breaks; the text is escaped, never HTML. */
.hr-multiline { white-space: pre-line; }
/* The issue tooltip: a little space between issues, so a wrapped line never reads as a third. */
.hr-issue-tip li + li { margin-top: 4px; }
/* A pill drawn inside a pre-line value (the right-to-work "Expiring") keeps its own spacing. */
.hr-multiline .vaste-badge { white-space: nowrap; margin-left: 4px; vertical-align: 1px; }
/* The worker type as a quiet label after the job title, not a pill
   (Precious, 24 Oct): Inter 12px #66746F, no background. */
.hr-meta { font-size: 12px; line-height: 16px; color: #66746F; }
.hr-vis { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; line-height: 16px; font-weight: 500; white-space: nowrap; }
.hr-vis .lucide, .hr-vis i[data-lucide] { width: 12px; height: 12px; stroke-width: 2; }
.hr-vis-team { color: #66746F; font-weight: 400; }
.hr-vis-restricted { background: #EEF2F1; color: #4E5B57; padding: 2px 8px; border-radius: 999px; }

/* 6. Users & Access: the Access column fits its control (~140px asked; 156 is the least that shows "CRM and People" beside the arrow); names stay on one line. */
.users-access-col { width: 156px; }
.users-access-col .form-select { width: 156px; }
.users-name { display: inline-block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }

/* A self-saving control's "Saved" (Precious): muted, a 12px check, gone after 2s. */
.saved-tick {
  display: inline-flex; align-items: center; gap: 4px; margin-left: 8px;
  color: #66746F; font-size: 12px; line-height: 16px; white-space: nowrap;
  animation: vaste-saved-fade .4s ease 2s forwards;
}
.saved-tick .lucide, .saved-tick i[data-lucide] { width: 12px; height: 12px; stroke-width: 2; color: #66746F; }
@keyframes vaste-saved-fade { to { opacity: 0; visibility: hidden; } }
@media (prefers-reduced-motion: reduce) {
  .saved-tick { animation: vaste-saved-fade 0s linear 2s forwards; }
}

/* A field's own error (Precious): 1px #C8442E border (--bs-form-invalid-border-color),
   the message directly under it in #A8371F at 12px. */
.invalid-feedback { font-size: 12px; line-height: 16px; color: #A8371F; }
/* Focused with an error, the ring matches the error (Precious): the 1px Danger
   border and a Danger ring at 30%. The focus rule above sets green with
   !important; once the error is fixed the field has no .is-invalid and is green again. */
.form-control.is-invalid, .form-select.is-invalid { border-color: #C8442E; }
.form-control.is-invalid:focus, .form-select.is-invalid:focus {
  border-color: #C8442E !important;
  box-shadow: 0 0 0 3px rgba(200,68,46,.30) !important;
}
/* If a message carries an icon: Lucide alert-circle, 14px, in the message's
   #A8371F, beside the text — never inside the field. */
.invalid-feedback .lucide { width: 14px; height: 14px; vertical-align: -2px; margin-right: 4px; color: #A8371F; }

/* ── People letters (milestone 3b) ───────────────────────────────────────── */
/* A letter on screen, on a sheet of paper: the PDF's own stylesheet inside. */
.letter-sheet { background: #FFFFFF; border: 1px solid #E1E7E5; border-radius: 4px; box-shadow: 0 1px 2px rgba(19,26,24,.06); padding: 48px 56px; max-width: 760px; }
@media (max-width: 575.98px) { .letter-sheet { padding: 24px 20px; } }

/* Script styles for the typed signature: the same OFL fonts the server draws with. */
@font-face { font-family: 'Vaste Sign Dancing'; src: url('../fonts/signature/DancingScript-Medium.ttf') format('truetype'); font-display: swap; }
@font-face { font-family: 'Vaste Sign Vibes'; src: url('../fonts/signature/GreatVibes-Regular.ttf') format('truetype'); font-display: swap; }
@font-face { font-family: 'Vaste Sign Caveat'; src: url('../fonts/signature/Caveat-Medium.ttf') format('truetype'); font-display: swap; }

.sig-methods { display: flex; flex-wrap: wrap; gap: 8px; }
.sig-canvas-wrap { position: relative; border: 1px solid #CBD4D1; border-radius: 10px; background: #FFFFFF; }
.sig-canvas { display: block; width: 100%; height: auto; aspect-ratio: 600 / 180; touch-action: none; cursor: crosshair; border-radius: 10px; }
.sig-baseline { position: absolute; left: 24px; right: 24px; bottom: 34px; border-bottom: 1px dashed #CBD4D1; pointer-events: none; }
.sig-fonts { display: grid; gap: 8px; }
.sig-font { display: block; padding: 8px 14px; border: 1px solid #CBD4D1; border-radius: 10px; background: #FFFFFF; color: #131A18; font-size: 30px; line-height: 1.3; cursor: pointer; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.btn-check:checked + .sig-font { border-color: #048059; box-shadow: 0 0 0 1px #048059; background: #EAF6F1; }
.btn-check:focus-visible + .sig-font { outline: none; box-shadow: 0 0 0 3px rgba(4,150,104,.45); }
.sig-font-dancing { font-family: 'Vaste Sign Dancing', cursive; }
.sig-font-vibes { font-family: 'Vaste Sign Vibes', cursive; }
.sig-font-caveat { font-family: 'Vaste Sign Caveat', cursive; }
.sig-saved { border: 1px solid #E1E7E5; border-radius: 10px; padding: 12px 16px; background: #FFFFFF; display: inline-block; }
.sig-saved img { max-height: 60px; max-width: 100%; }
.sig-saved-sm img { max-height: 36px; }
.sig-decline summary { cursor: pointer; color: #374440; font-weight: 500; }

/* ── People, milestone 4a: time off ──────────────────────────────────────
   The policy check (screen 8): label left, value or pill right, a hairline
   between rows; a long label lets its pill drop to the next line. */
.hr-check-row {
  display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
  gap: 4px 12px; padding: 10px 0; border-bottom: 1px solid #E1E7E5; font-size: 14px; line-height: 20px;
}
.hr-check-row:last-child { border-bottom: 0; }
.hr-check-label { color: #374440; }
.hr-check-value { color: #131A18; text-align: right; }
/* A blocking error (Precious, 29 Oct): a red card above the form — soft
   danger fill, a 1px Danger border at 40%, Danger text, the circle-alert
   icon. The field it belongs to carries the red border and the message. */
.hr-block-alert {
  display: flex; align-items: flex-start; gap: 8px;
  background: #FBEAE7; color: #A8371F; border: 1px solid rgba(200, 68, 46, .4);
  border-radius: 10px; padding: 12px 16px; font-size: 14px; line-height: 20px;
}
.hr-block-alert[hidden] { display: none; }
.hr-block-alert .lucide { width: 16px; height: 16px; flex: none; margin-top: 2px; color: #A8371F; }
/* A balance below zero: allowed and approvable, so a warning in amber text,
   not an error (Precious, 29 Oct). */
.hr-check-negative { color: #9A4300; font-weight: 500; }
/* Working days on the request form: worked out, never typed, so plain text,
   not a box (Precious, 29 Oct). */
.hr-working-days { display: flex; align-items: baseline; gap: 12px; }
.hr-working-days-label { color: #66746F; font-size: 13px; }
.hr-working-days-value { color: #131A18; font-weight: 600; font-size: 14px; }
/* The Requests filters (Precious, 29 Oct): a selected filter is a soft green
   pill with a green border, never a solid green one, which reads as a button.
   36px, the house compact size. */
.hr-filter-pill {
  display: inline-flex; align-items: center; height: 36px; padding: 0 14px; border-radius: 999px;
  background: #FFFFFF; border: 1px solid #CBD4D1; color: #374440; font-size: 14px; text-decoration: none;
}
.hr-filter-pill:hover { background: #F7F9F8; color: #374440; }
.hr-filter-pill.is-selected { background: #EAF6F1; border-color: #048059; color: #037A54; font-weight: 500; }
/* The time-off tiles sit at their content width on a wide screen, as on screen 7. */
@media (min-width: 992px) { .hr-leave-tiles .stat-card { min-width: 160px; } }
/* Who's out (screen 9): even day columns, today marked by its header only. */
.hr-whos-out th[scope="col"]:not(:first-child), .hr-whos-out td { min-width: 76px; }
.hr-whos-out thead th.is-today { color: #037A54; }

/* People Home: one "Absence to-dos" card (Precious, 30 Oct). A needed fit
   note is the amber row — the warning pair, as everywhere it shows. */
.hr-todo-list .hr-todo-icon { width: 16px; height: 16px; color: #66746F; }
.hr-todo-list .hr-todo-warning { background: #FFE7CF; color: #9A4300; }
.hr-todo-list .hr-todo-warning .hr-todo-icon { color: #9A4300; }
.hr-todo-list .hr-todo-warning a { color: #9A4300; }

/* People: a project timesheet week (milestone 5a). Days off the project or
   outside the person's pattern recede; the hours box is narrow and right-aligned. */
.hr-timesheet .hr-hours-input { width: 6.5rem; }
.hr-timesheet-muted td { background: #F7F9F8; color: #66746F; }
.hr-timesheet tfoot th { font-weight: 600; }
.hr-subrow td { background: #F7F9F8; border-top: 0; padding-top: 4px; }
