/* ═══════════════════════════════════════════════════════════════
   ECOM 360 · BFL Group — Design System V4.0
   ═══════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Figtree:wght@400;500;600;700;800&family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;1,9..40,400&family=JetBrains+Mono:wght@400;500;600&display=swap');

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* ── BFL Brand (kept for login/footer/admin hex hub) ────── */
  --bfl-yellow:        #FFD100;
  --bfl-yellow-hov:    #E6BC00;
  --bfl-yellow-deep:   #C9A400;
  --bfl-yellow-lite:   rgba(255,209,0,0.10);
  --bfl-yellow-glow:   rgba(255,209,0,0.28);
  --bfl-black:         #000000;
  --bfl-charcoal:      #1A1A1A;
  --bfl-graphite:      #2C2C2C;
  --bfl-navy:          #081A34;
  --bfl-navy-mid:      #182B45;

  /* ── Design System — Blue Brand (design.md) ─────────────── */
  --brand:      #2563eb;
  --brand-2:    #7c3aed;
  --brand-hov:  #1d4ed8;
  --brand-lite: rgba(37,99,235,0.08);
  --brand-glow: rgba(37,99,235,0.20);

  /* ── Canvas & Surfaces ──────────────────────────────────── */
  --bg:           #f5f7fb;
  --card:         #ffffff;
  --surf-0:       #ffffff;
  --surf-1:       #ffffff;
  --surf-2:       #f9fafb;
  --surf-3:       #f3f4f6;
  --surf-sidebar: #ffffff;
  --surf-header:  #f8fafc;
  --surf-hdr:     #f9fafb;

  /* ── Borders ────────────────────────────────────────────── */
  --border:           #e6eaf2;
  --border2:          #d1d5db;
  --border-sidebar:   #e6eaf2;
  --border-header:    #e6eaf2;

  /* ── Text ───────────────────────────────────────────────── */
  --text:   #1f2937;
  --text-1: #1f2937;
  --text-2: #6b7280;
  --text-3: #9ca3af;

  /* ── Active Nav (brand blue) ────────────────────────────── */
  --nav-active-bg:     #eff6ff;
  --nav-active-border: #bfdbfe;
  --nav-active-text:   #1e40af;

  /* ── Status Colors ──────────────────────────────────────── */
  --green:    #16a34a; --green-bg:  #dcfce7;
  --amber:    #f59e0b; --amber-bg:  #fef3c7;
  --red:      #dc2626; --red-bg:    #fee2e2;

  /* ── Radius ─────────────────────────────────────────────── */
  --radius-sm:   6px;
  --radius:      12px;
  --radius-lg:   14px;
  --radius-xl:   16px;
  --radius-pill: 999px;

  /* ── Shadows ────────────────────────────────────────────── */
  --shadow-xs: 0 1px 2px rgba(15,23,42,0.04);
  --shadow-sm: 0 1px 3px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
  --shadow:    0 4px 16px rgba(15,23,42,0.08), 0 2px 6px rgba(15,23,42,0.04);
  --shadow-lg: 0 8px 32px rgba(15,23,42,0.12), 0 4px 12px rgba(15,23,42,0.06);
  --shadow-xl: 0 16px 48px rgba(15,23,42,0.14), 0 8px 20px rgba(15,23,42,0.06);
  --shadow-focus: 0 0 0 3px rgba(37,99,235,0.12);
  --shadow-yellow: 0 4px 20px rgba(255,209,0,0.24);
}

body {
  font-family: 'Segoe UI', 'DM Sans', system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text-1);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Monospace for all tabular numbers */
.num { font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums; }

/* ══════════════════════════════════════════════════════════════
   LOGIN PAGE — light warm canvas
   ══════════════════════════════════════════════════════════════ */
.login-overlay {
  position: fixed; inset: 0; z-index: 10001;
  background: #F7F7F5;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  overflow: hidden;
}
.login-overlay.hidden { display: none; }

.splash-bg {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse 70% 50% at 50% 40%, rgba(255,209,0,.10) 0%, transparent 70%);
}
.splash-triangle {
  position: absolute; bottom: 0; left: 0;
  width: 0; height: 0;
  border-style: solid;
  border-width: 0 0 240px 160px;
  border-color: transparent transparent var(--bfl-yellow) transparent;
  opacity: 0.55;
}
.splash-content {
  position: relative; z-index: 1;
  display: flex; flex-direction: column;
  align-items: center; gap: 20px;
  width: 100%; max-width: 460px;
  padding: 40px 24px;
}
.splash-logo-wrap { display: flex; align-items: center; gap: 14px; }
.splash-logo-text {
  font-size: 22px; font-weight: 700;
  color: var(--bfl-navy); letter-spacing: 1px;
  font-family: 'Figtree', sans-serif;
}
.splash-title-card {
  background: #ffffff;
  border: 1px solid rgba(0,0,0,.08);
  border-top: 3px solid var(--bfl-yellow);
  border-radius: var(--radius-lg);
  padding: 20px 40px;
  text-align: center; width: 100%;
  box-shadow: 0 2px 12px rgba(0,0,0,.06);
}
.splash-title-card h1 {
  font-size: 26px; font-weight: 700;
  color: var(--bfl-navy); letter-spacing: 2px;
  font-family: 'Figtree', sans-serif;
}
.login-form-card {
  background: #ffffff;
  border: 1px solid rgba(0,0,0,.08);
  border-radius: var(--radius-xl);
  padding: 20px 22px; width: 100%;
  box-shadow: 0 2px 12px rgba(0,0,0,.06);
}
.login-form-label {
  font-size: 9px; font-weight: 700; color: var(--bfl-navy);
  letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 14px;
  font-family: 'Figtree', sans-serif;
}
.login-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.login-field-label {
  font-size: 8px; font-weight: 700; color: var(--text-3);
  letter-spacing: 1.2px; text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
}
.login-input {
  background: #F7F7F5 !important;
  border: 1px solid rgba(0,0,0,.15) !important;
  border-radius: var(--radius-sm) !important;
  color: var(--bfl-navy) !important;
  font-size: 13px !important;
  padding: 8px 12px !important;
  width: 100% !important;
  outline: none !important;
  font-family: 'DM Sans', sans-serif !important;
  transition: border-color .15s, box-shadow .15s !important;
}
.login-input:focus {
  border-color: var(--bfl-yellow) !important;
  box-shadow: 0 0 0 3px rgba(255,209,0,.18) !important;
}
.login-input::placeholder { color: rgba(0,0,0,.28) !important; }
.login-error {
  font-size: 11px; color: #dc2626; min-height: 16px;
  margin-bottom: 4px; text-align: center;
}
.login-otp-hint {
  text-align: center; margin-bottom: 16px;
  padding: 12px 16px;
  background: rgba(255,209,0,.12);
  border: 1px solid rgba(255,209,0,.40);
  border-radius: var(--radius);
  font-size: 13px; color: var(--text-2);
  letter-spacing: .3px; line-height: 1.6;
}
.login-otp-hint strong {
  display: block; font-size: 28px; font-weight: 700;
  color: var(--bfl-navy); letter-spacing: 10px;
  margin: 4px 0 2px;
  font-family: 'JetBrains Mono', monospace;
}
.splash-launch-btn {
  background: var(--bfl-yellow);
  color: var(--bfl-black);
  border: none; cursor: pointer;
  font-size: 13px; font-weight: 700;
  letter-spacing: 2.5px; text-transform: uppercase;
  padding: 14px 64px;
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-yellow);
  transition: transform .15s, box-shadow .15s, background .15s;
  font-family: 'Figtree', sans-serif;
}
.splash-launch-btn:hover {
  background: var(--bfl-yellow-hov);
  transform: translateY(-2px);
  box-shadow: 0 8px 28px rgba(255,209,0,0.36);
}
.splash-brands {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap; justify-content: center;
}
.splash-brand-badge {
  font-size: 9px; font-weight: 600; color: var(--text-3);
  background: rgba(0,0,0,.04); border: 1px solid rgba(0,0,0,.09);
  border-radius: var(--radius-sm); padding: 4px 10px;
  text-transform: uppercase; letter-spacing: 0.5px;
  font-family: 'Figtree', sans-serif;
}
.splash-brand-badge.highlight { color: var(--bfl-navy); border-color: rgba(255,209,0,.50); }

/* ══════════════════════════════════════════════════════════════
   APP SHELL — outer column wrapper
   ══════════════════════════════════════════════════════════════ */
.app-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: var(--bg);
}

/* ══════════════════════════════════════════════════════════════
   APP HEADER — full-width gradient bar (design.md)
   ══════════════════════════════════════════════════════════════ */
.app-header {
  background: linear-gradient(135deg, #1e40af 0%, #6d28d9 100%);
  color: #ffffff;
  padding: 0 20px;
  height: 60px;
  min-height: 60px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 2px 8px rgba(15,23,42,0.18);
  gap: 16px;
}
.header-left {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: 1;
  min-width: 0;
}
.header-logo {
  width: 38px; height: 38px;
  background: rgba(255,255,255,0.15);
  border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; color: #ffffff;
  font-family: 'Figtree', sans-serif;
  flex-shrink: 0;
  letter-spacing: 0.5px;
}
.header-title-block { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.header-title {
  font-size: 20px; font-weight: 600; color: #ffffff;
  letter-spacing: 0.2px;
  font-family: 'Figtree', sans-serif;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.header-sub {
  font-size: 13px; color: rgba(255,255,255,0.85);
  font-family: 'DM Sans', sans-serif;
  min-height: 14px; opacity: 0.85;
}
.header-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
}
.header-updated-label {
  font-size: 9px; font-weight: 700; color: rgba(255,255,255,0.65);
  letter-spacing: 1px; text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
}
.header-updated-value {
  font-size: 11px; font-weight: 600; color: rgba(255,255,255,0.95);
  font-family: 'JetBrains Mono', monospace;
}

/* ── Notification bell + dropdown panel ─────────────────────── */
.notif-wrap { position: relative; display: flex; align-items: center; }
.notif-bell {
  position: relative;
  background: rgba(255,255,255,0.15);
  border: none;
  color: #ffffff;
  width: 34px; height: 34px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 15px;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s;
}
.notif-bell:hover { background: rgba(255,255,255,0.28); }
.notif-badge {
  position: absolute;
  top: 5px; right: 5px;
  width: 9px; height: 9px;
  background: var(--red);
  border: 1.5px solid #ffffff;
  border-radius: var(--radius-pill);
}
.notif-panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: 340px;
  max-height: 420px;
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 12px;
  z-index: 1200;
  display: flex; flex-direction: column; gap: 8px;
}
.notif-panel-title {
  font-size: 14px; font-weight: 700; color: var(--text-1);
  font-family: 'Figtree', sans-serif;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.notif-empty {
  font-size: 12px; color: var(--text-3);
  text-align: center; padding: 16px 8px;
}

/* ══════════════════════════════════════════════════════════════
   LAYOUT — sidebar | main grid (below header)
   ══════════════════════════════════════════════════════════════ */
.layout {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: calc(100vh - 60px);
  flex: 1;
}

/* ══════════════════════════════════════════════════════════════
   SIDEBAR — V4.0 Light Warm
   ══════════════════════════════════════════════════════════════ */
.sidebar {
  width: 260px;
  min-width: 260px;
  background: var(--surf-sidebar);
  border-right: 1px solid var(--border-sidebar);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 60px;
  height: calc(100vh - 60px);
  overflow-y: auto;
  z-index: 90;
  flex-shrink: 0;
  scrollbar-width: thin;
  scrollbar-color: #cbd5e1 transparent;
}
.sidebar::-webkit-scrollbar { width: 8px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }

.sidebar-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 16px 16px 12px;
  border-bottom: 1px solid var(--border-sidebar);
}
.sidebar-brand-name {
  font-size: 10px; font-weight: 700; color: var(--bfl-charcoal);
  letter-spacing: 1.5px; text-transform: uppercase; line-height: 1.2;
  font-family: 'Figtree', sans-serif;
}
.sidebar-brand-sub {
  font-size: 13px; font-weight: 600; color: var(--text-2);
  letter-spacing: 0.3px; line-height: 1;
  font-family: 'Figtree', sans-serif;
}
.sidebar-brand-sub span { color: var(--brand); }

/* User profile */
.sidebar-user {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px 10px;
}
.sidebar-avatar {
  width: 34px; height: 34px;
  background: var(--brand);
  color: #ffffff;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
  flex-shrink: 0;
  font-family: 'Figtree', sans-serif;
}
.sidebar-username {
  font-size: 12px; font-weight: 600; color: var(--text-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-family: 'DM Sans', sans-serif;
}
.sidebar-role {
  font-size: 8px; font-weight: 700;
  background: var(--nav-active-bg);
  color: var(--nav-active-text);
  border: 1px solid var(--nav-active-border);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
  letter-spacing: 0.8px; text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
  display: inline-block; margin-top: 2px;
}

.sidebar-divider {
  height: 1px; background: var(--border-sidebar);
  margin: 4px 0;
}

/* Navigation */
.sidebar-nav { flex: 1; padding: 8px 0; }

/* Department section header */
.sidebar-dept-header {
  display: flex; align-items: center; gap: 7px;
  padding: 12px 14px 3px;
  margin-top: 2px;
  cursor: default; user-select: none;
}
.dept-hdr-icon {
  font-size: 10px; width: 14px; text-align: center; flex-shrink: 0;
  opacity: 0.8;
}
.dept-hdr-label {
  font-size: 8px; font-weight: 700;
  letter-spacing: 1.2px; text-transform: uppercase;
  opacity: 0.8;
  font-family: 'Figtree', sans-serif;
}

.nav-link-wrapper {
  display: block; text-decoration: none !important;
  color: inherit !important;
}

/* CXO top-level item */
.nav-item-cxo {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px;
  color: var(--nav-active-text);
  font-size: 12px; font-weight: 700;
  cursor: pointer;
  transition: background .15s;
  border-left: 3px solid var(--brand);
  background: var(--nav-active-bg);
  letter-spacing: 0.2px;
  font-family: 'Figtree', sans-serif;
}
.nav-item-cxo:hover { background: #dbeafe; }

/* Sub-items under department headers */
.nav-item-sub {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 16px 7px 28px;
  color: var(--text-2);
  font-size: 12px; font-weight: 400;
  cursor: pointer;
  transition: background .12s, color .12s;
  border-left: 3px solid transparent;
}
.nav-item-sub:hover {
  background: var(--surf-2);
  color: var(--text-1);
  border-left-color: var(--brand);
}

.nav-item-active {
  background: var(--nav-active-bg) !important;
  color: var(--nav-active-text) !important;
  border-left-color: var(--brand) !important;
  font-weight: 600 !important;
}

.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 16px;
  color: var(--text-2);
  font-size: 12px; font-weight: 400;
  cursor: pointer;
  transition: background .12s, color .12s;
  border-left: 3px solid transparent;
}
.nav-item:hover { background: var(--surf-2); color: var(--text-1); }

.nav-icon { width: 16px; text-align: center; font-size: 13px; flex-shrink: 0; }
.nav-label { white-space: nowrap; }

/* Logout */
.sidebar-bottom {
  padding: 12px 16px;
  border-top: 1px solid var(--border-sidebar);
}
.sidebar-logout {
  width: 100%; display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
  background: rgba(209,67,91,.06);
  border: 1px solid rgba(209,67,91,.22);
  border-radius: var(--radius-sm);
  color: var(--red);
  font-size: 11px; font-weight: 600; cursor: pointer;
  transition: all .15s;
  font-family: 'DM Sans', sans-serif;
}
.sidebar-logout:hover { background: rgba(209,67,91,.14); }
.sidebar-logout i { font-size: 12px; }

/* ══════════════════════════════════════════════════════════════
   CONTENT AREA (main flex column inside layout grid)
   ══════════════════════════════════════════════════════════════ */
.content-area {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow-x: hidden;
  flex: 1;
}

/* ── Page header — page-title bar (below gradient, above filters) ── */
.page-header {
  background: var(--card);
  border-bottom: 1px solid var(--border);
  padding: 12px 18px;
  display: flex; align-items: center;
  gap: 8px;
}
.page-header-title {
  font-size: 18px; font-weight: 700; color: var(--text-1);
  letter-spacing: 0.2px;
  font-family: 'Figtree', sans-serif;
  display: flex; align-items: center; gap: 8px;
}
.page-header-title::before {
  content: '';
  display: inline-block; width: 4px; height: 18px;
  background: var(--brand); border-radius: 2px;
  flex-shrink: 0;
}

/* ── AI Insight control (page-header, right side) ──────────────────────────
   Pushed to the far right of the page-title bar so it reads as an action on
   the page rather than part of its name. Labelled, not a bare sparkle: an
   unlabelled icon is a guess, and this one costs an API call to try.        */
.ai-insight-wrap { margin-left: auto; display: flex; align-items: center; }
.ai-insight-btn {
  display: inline-flex; align-items: center;
  font-family: 'Figtree', sans-serif;
  font-size: 12.5px; font-weight: 600;
  color: var(--brand); background: var(--brand-soft, #eff6ff);
  border: 1px solid color-mix(in srgb, var(--brand) 30%, transparent);
  border-radius: 999px; padding: 5px 13px; cursor: pointer;
  transition: background .15s ease, box-shadow .15s ease, transform .1s ease;
  white-space: nowrap;
}
.ai-insight-btn:hover {
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  box-shadow: var(--shadow-xs);
}
.ai-insight-btn:active { transform: translateY(1px); }
.ai-insight-btn:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 2px;
}
/* Inside a trend popup the control has to be small and quiet — the chart is
   the subject there, not the button. */
.sr3-spark-popup .ai-insight-btn {
  font-size: 11px; padding: 3px 10px;
}
.sr3-spark-popup .ai-insight-wrap { margin-left: 0; }
/* Close on the left where it has always been, AI Insight on the right. */
.sr3-popup-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 4px;
}
@media (max-width: 640px) {
  /* The label is the first thing to go on a narrow screen; the icon still
     says enough next to the page title. */
  .ai-insight-btn span { display: none; }
  .ai-insight-btn i { margin-right: 0 !important; }
}
@media (prefers-reduced-motion: reduce) {
  .ai-insight-btn { transition: none; }
  .ai-insight-btn:active { transform: none; }
}

/* ── Topbar — filter bar (non-sticky so it never covers KPI cards) ── */
.topbar {
  background: var(--surf-header);
  border-bottom: 1px solid var(--border);
  padding: 10px 18px;
  display: flex; align-items: center;
  gap: 12px; flex-wrap: wrap;
  min-height: 50px;
  box-shadow: var(--shadow-xs);
}
.topbar-filters {
  flex: 1; display: flex; flex-wrap: wrap;
  gap: 8px; align-items: center;
  padding: 6px 0;
}

/* Filter labels */
.filter-group {
  display: flex; flex-direction: column; gap: 4px;
  flex: 0 0 160px;            /* equal width for every filter control, no shrink */
  width: 160px;
}
.filter-label {
  font-size: 8px; font-weight: 700; color: var(--text-3);
  letter-spacing: 1.2px; text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
  height: 12px; line-height: 12px;   /* uniform label row height */
}
.filter-dropdown { min-width: 0; width: 100%; }

/* ── Uniform filter controls — equal width & 32px height ─────── */
/* Dropdown — covers both Dash dropdown implementations */
.filter-group .filter-dropdown,
.filter-group .Select,
.filter-group .Select-control { width: 100% !important; }
.filter-group button.dash-dropdown,
.filter-group .Select-control {
  height: 32px !important;
  min-height: 32px !important;
  width: 100% !important;
}
.filter-group .date-picker,
.filter-group .date-picker > div:first-child,
.filter-group .SingleDatePicker,
.filter-group .SingleDatePicker > div:first-child,
.filter-group .SingleDatePickerInput,
.filter-group .DateInput {
  width: 100% !important;
  box-sizing: border-box !important;
}
.filter-group .DateInput_input {
  width: 100% !important;
  height: 32px !important;
  padding: 6px 10px !important;
  box-sizing: border-box !important;
}
.filter-group .compare-toggle-btn {
  width: 100%;
  height: 32px;
  margin-top: 0;
  border-radius: var(--radius-sm);
  box-sizing: border-box;
}
/* Compare radio sits in a 32px control slot too */
.filter-group .compare-radio {
  height: 32px;
  padding: 0 4px;
}

/* Dash 4.x dropdown — light topbar context */
button.dash-dropdown {
  background: var(--surf-0) !important;
  border: 1px solid var(--border2) !important;
  border-radius: var(--radius-sm) !important;
  color: var(--text-1) !important;
  font-size: 12px !important;
  height: 28px !important;
  min-height: 28px !important;
  font-family: 'DM Sans', sans-serif !important;
}
button.dash-dropdown:hover {
  border-color: var(--brand) !important;
}
[data-radix-popper-content-wrapper] {
  background: var(--surf-0) !important;
  border: 1px solid var(--border2) !important;
  border-radius: var(--radius) !important;
  box-shadow: var(--shadow) !important;
  color: var(--text-1) !important;
}

/* Updated timestamp (kept for fallback; primary is header-updated-*) */
.updated-label {
  font-size: 7px; font-weight: 700; color: var(--text-3);
  letter-spacing: 1.2px; text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
}
.updated-value {
  font-size: 11px; font-weight: 600; color: var(--brand);
  font-family: 'JetBrains Mono', monospace;
}

/* Compare radio */
.compare-radio { display: flex; gap: 10px; align-items: center; }
.compare-radio label { color: var(--text-2) !important; font-size: 12px; }
.compare-radio input { accent-color: var(--brand); }

/* ── Filter set ──────────────────────────────────────────────── */
.filter-set { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; }

.data-range-label {
  font-size: 10px; font-weight: 500; color: var(--text-3);
  letter-spacing: 0.3px; padding: 5px 10px; height: 32px;
  display: flex; align-items: center;
  background: var(--surf-2); border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  white-space: nowrap; align-self: flex-end;
  margin-left: auto;   /* push data-range info to the far right of the row */
}

/* ── Buttons ─────────────────────────────────────────────────── */
.btn-group { display: flex; gap: 6px; align-items: center; }
.btn-refresh {
  padding: 5px 12px; border-radius: var(--radius-pill);
  cursor: pointer; font-size: 10px; font-weight: 700;
  letter-spacing: 0.5px; text-transform: uppercase; transition: all .15s;
  white-space: nowrap;
  background: var(--surf-0);
  color: var(--text-2);
  border: 1px solid var(--border2);
  font-family: 'Figtree', sans-serif;
}
.btn-refresh:hover {
  border-color: var(--brand);
  color: var(--brand);
  box-shadow: var(--shadow-focus);
}
.btn-load {
  padding: 5px 12px; border-radius: var(--radius-pill);
  cursor: pointer; font-size: 10px; font-weight: 700;
  letter-spacing: 0.5px; text-transform: uppercase; transition: all .15s;
  white-space: nowrap;
  background: var(--brand);
  color: #ffffff;
  border: none;
  font-family: 'Figtree', sans-serif;
}
.btn-load:hover { background: var(--brand-hov); box-shadow: var(--shadow-focus); }
.btn-export {
  background: rgba(14,159,110,.10); color: #0a7d55;
  border: 1px solid rgba(14,159,110,.30);
  padding: 5px 12px; border-radius: var(--radius-pill); cursor: pointer;
  font-size: 10px; font-weight: 700; letter-spacing: 0.5px;
  text-transform: uppercase; transition: all .15s; white-space: nowrap;
  font-family: 'Figtree', sans-serif;
}
.btn-export:hover { background: rgba(14,159,110,.22); }

/* ── Compare toggle ──────────────────────────────────────────── */
.compare-toggle-btn {
  background: var(--surf-0);
  border: 1px solid var(--border2);
  border-radius: var(--radius-pill);
  color: var(--text-2);
  cursor: pointer;
  font-size: 10px; font-weight: 700;
  letter-spacing: 1px; padding: 4px 12px;
  transition: all .15s; margin-top: 2px;
  font-family: 'Figtree', sans-serif;
}
.compare-toggle-btn.compare-toggle-on {
  background: var(--nav-active-bg);
  border-color: var(--nav-active-border);
  color: var(--nav-active-text);
  box-shadow: var(--shadow-focus);
}
.compare-toggle-btn:hover { border-color: var(--brand); color: var(--brand); }

/* ── Compare quick-select buttons ────────────────────────────── */
.cmp-quick-btn {
  background: var(--surf-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  color: var(--text-2);
  cursor: pointer;
  font-size: 9px; font-weight: 700;
  letter-spacing: .5px; padding: 3px 9px;
  transition: all .15s; white-space: nowrap;
  font-family: 'Figtree', sans-serif;
}
.cmp-quick-btn:hover { border-color: var(--brand); color: var(--brand); }
.cmp-quick-btn.cmp-quick-active {
  background: var(--nav-active-bg);
  border-color: var(--nav-active-border);
  color: var(--nav-active-text);
}

/* ── Date picker — light topbar ──────────────────────────────── */
.date-picker .SingleDatePickerInput {
  background: var(--surf-0) !important;
  border: 1px solid var(--border2) !important;
  border-radius: var(--radius-sm) !important;
  overflow: hidden !important;
}
.date-picker .DateInput {
  background: var(--surf-0) !important;
  border-radius: var(--radius-sm) !important;
}
.date-picker .DateInput_input {
  background: var(--surf-0) !important;
  color: var(--text-1) !important;
  font-size: 12px !important;
  font-weight: 500 !important;
  font-family: 'DM Sans', sans-serif !important;
  padding: 5px 10px !important;
  width: 106px !important;
  caret-color: var(--brand) !important;
}
.date-picker .DateInput_input:-webkit-autofill,
.date-picker .DateInput_input:-webkit-autofill:hover,
.date-picker .DateInput_input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px var(--surf-0) inset !important;
  -webkit-text-fill-color: var(--text-1) !important;
  background-color: var(--surf-0) !important;
}
.date-picker .DateInput_input::placeholder { color: var(--text-3) !important; }
.date-picker .DateInput_input__focused {
  background: var(--surf-0) !important;
  color: var(--text-1) !important;
  border-bottom: 2px solid var(--brand) !important;
}
.date-picker .SingleDatePickerInput__withBorder { border-color: var(--border2) !important; }
.DayPicker { font-family: 'DM Sans', sans-serif !important; }
.CalendarDay__selected,
.CalendarDay__selected:hover {
  background: var(--brand) !important;
  border-color: var(--brand-hov) !important;
  color: #ffffff !important;
}

/* ── Load status ─────────────────────────────────────────────── */
.load-status {
  background: rgba(14,159,110,.06); color: var(--green);
  border-bottom: 1px solid rgba(14,159,110,.14);
  font-size: 11px; padding: 5px 20px; min-height: 0;
  font-family: 'JetBrains Mono', monospace;
}

/* ── Page content ────────────────────────────────────────────── */
.page-content {
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 12px;
  flex: 1;
}

/* ── Page loader — chatbot-style bouncing dots (2026-08-03) ──────
   Replaces the old dark card + blue scanning progress bar. The page itself
   stays visible (dimmed via dcc.Loading overlay_style); this small floating
   pill with three bouncing dots is the only loading chrome. */
.bfl-dots-loader {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--card, #ffffff);
  border: 1px solid var(--border, #e6eaf2);
  border-radius: 999px;
  padding: 14px 24px;
  box-shadow: 0 8px 30px rgba(15, 23, 42, 0.18);
}
.bfl-dots-loader .bfl-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #2563eb;
  animation: bfl-dot-bounce 1.2s ease-in-out infinite;
}
.bfl-dots-loader .bfl-dot:nth-child(2) { animation-delay: 0.15s; }
.bfl-dots-loader .bfl-dot:nth-child(3) { animation-delay: 0.30s; }
@keyframes bfl-dot-bounce {
  0%, 80%, 100% { transform: translateY(0);    opacity: 0.45; }
  40%           { transform: translateY(-7px); opacity: 1; }
}

/* Legacy loading-action text — retired with the dark spinner card. */
.loading-action-text { display: none; }

/* Ask Data suppresses the app-wide pill (2026-09-08).
   Reported: "before entering it shows loader — why?" — the centre-screen pill
   appearing with nothing sent, while the reader was still typing.

   Two causes, one cure. Every Ask Data output (the transcript, the rail, the
   composer, the typing dots) sits inside #page-content, which this pill
   watches, so (a) it ran for the whole model call ALONGSIDE .ad-typing — two
   loaders for one wait — and (b) when an answer repaints the follow-up chips
   and the rail, those new components re-fire the two ALL-matched callbacks;
   they return no_update, but the round trip still marks the page loading, and
   the pill came up over a finished answer.

   This page states its own waits in the thread, where the answer will appear,
   so the global one is only ever wrong here. The class is set from the URL in
   ask_data.js, NOT from the page's presence in the DOM — on the way out of
   the page the URL changes before the next render, so leaving Ask Data still
   gets its loader. */
body.ad-route .bfl-dots-loader { display: none; }

/* ── Hourly Sales Trend page (2026-08-07) ──────────────────────────
   Mirrors the approved sample's composition with design.md tokens. */
.hs-alerts { display: flex; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
.hs-alert {
  display: flex; gap: 8px; align-items: center; background: var(--card, #fff);
  border: 1px solid var(--border, #e6eaf2); border-left: 3px solid #dc2626;
  border-radius: 10px; padding: 8px 12px; font-size: 13px; cursor: pointer;
  font-family: inherit; text-align: left; transition: all .15s;
}
.hs-alert:hover { background: #eff6ff; transform: translateY(-1px); }
.hs-chips { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 10px; }
.hs-chip { font-size: 12px; border: 1px solid var(--border, #e6eaf2);
           border-radius: 999px; padding: 4px 10px; color: var(--muted, #6b7280); }
.hs-chip b { font-weight: 650; color: var(--text, #1f2937); }
.hs-chip.bad b { color: #dc2626; }
.hs-chip.ok b { color: #16a34a; }
.hs-sub { font-size: 12.5px; font-weight: 650; margin: 2px 0 0 4px; }
.hs-drill-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
.hs-drill-grid > * { min-width: 0; }
.hs-eq { font-size: 13px; color: var(--muted, #6b7280); line-height: 1.55;
         padding-bottom: 12px; }
.hs-eq code { background: #eef2ff; border-radius: 6px; padding: 2px 7px;
              font-size: 12.5px; color: var(--text, #1f2937); }
.hs-page .kpi-row { margin-bottom: 12px; }
@media (max-width: 1100px) { .hs-drill-grid { grid-template-columns: 1fr; } }

/* ── PANEL HEADINGS THAT WERE NEVER DEFINED (fixed 2026-09-07) ──
   .panel-title, .panel-sub and .kpi-label are used 56 times across the Hourly,
   Omni 360, Returns 360, Cancellations 360 and Category Analysis pages — and
   none of them existed in this stylesheet. A className with no rule behind it
   fails silently: the markup is correct, the element renders, and it simply
   looks like unstyled body text. That is why the Hourly page's section
   headings had no hierarchy.

   The values mirror .bg-panel-title / .bg-panel-sub / .bg-kpi-label, the
   prefixed twins that DO exist and that Merchandise 360 uses — clearly the
   intended look, so this makes the unprefixed pages match rather than
   inventing a second style for the same thing. */
.panel-title { font-size: 14px; font-weight: 700; margin: 0 0 4px;
               color: var(--text, #1f2937); letter-spacing: .2px; }
.panel-sub { font-size: 12px; color: var(--muted, #6b7280);
             margin-bottom: 10px; line-height: 1.5; }
.kpi-label { font-size: 11px; text-transform: uppercase;
             letter-spacing: .5px; color: var(--muted, #6b7280); }

/* ══════════════════════════════════════════════════════════════
   REPORT BUILDER (2026-09-07)
   The page styles most things inline, but `rb-dd` and `rb-input` were
   already being used as classNames with no rule behind them — a className
   with no CSS fails silently, so those controls were simply unstyled. Named
   here so they match, and so the saved-views row has something to inherit.
   ══════════════════════════════════════════════════════════════ */
.rb-dd .Select-control, .rb-dd .Select-value { font-size: 12.5px; }
.rb-input { padding: 8px 11px; font-size: 12.5px;
            border: 1px solid #e9e7f2; border-radius: 9px; outline: none;
            background: #fafafc; color: #1f2937; box-sizing: border-box; }
.rb-input:focus { border-color: #7c3aed; background: #fff; }

/* Saved views: choose one, or name and save the current composition. Sits
   above the dataset tabs and is entirely optional — the manual path is
   unchanged. */
.rb-views-row { display: flex; gap: 14px; align-items: flex-end;
                flex-wrap: wrap; padding: 14px 18px; background: #fff;
                border: 1px solid #e9e7f2; border-radius: 14px;
                box-shadow: 0 1px 3px rgba(30,27,58,.04);
                margin-bottom: 12px; }
.rb-view-btn { display: inline-flex; align-items: center; cursor: pointer;
               border: none; border-radius: 10px; padding: 10px 16px;
               font-weight: 800; font-size: 12.5px; white-space: nowrap;
               flex-shrink: 0; background: #7c3aed; color: #fff;
               box-shadow: 0 2px 8px rgba(124,58,237,.27);
               transition: filter .15s ease, transform .15s ease; }
.rb-view-btn:hover { filter: brightness(1.07); transform: translateY(-1px); }
.rb-view-btn-quiet { background: #fff; color: #6b7280;
                     border: 1px solid #e9e7f2; box-shadow: none;
                     font-weight: 700; }
.rb-view-btn-quiet:hover { color: #dc2626; border-color: #dc2626;
                           filter: none; }
.rb-view-msg { font-size: 11.5px; font-weight: 650; line-height: 1.4;
               flex-basis: 100%; min-height: 15px; color: #6b7280; }
.rb-view-msg.ok { color: #16a34a; }
.rb-view-msg.err { color: #dc2626; }

/* ── Filters ON HOVER (2026-09-07) ──────────────────────────────
   "In all pages show the current filters when we mouse over, not always
   required." A quiet control that carries the whole selection in its title
   attribute — see components.helpers.filter_hint for why a native tooltip
   rather than a hover panel. */
.filter-hint { display: inline-flex; align-items: center; cursor: help;
               font-size: 11.5px; font-weight: 600; line-height: 1.4;
               color: var(--muted, #6b7280);
               border: 1px dashed var(--border, #e6eaf2); border-radius: 999px;
               padding: 3px 10px; background: transparent;
               white-space: nowrap; transition: color .15s ease,
               border-color .15s ease, background .15s ease; }
.filter-hint:hover { color: var(--brand, #2563eb);
                     border-color: var(--brand, #2563eb);
                     border-style: solid; background: var(--card, #fff); }

/* ── The drill's AI control: THE ICON ONLY (2026-09-07) ─────────
   The always-on purple ANALYSIS panel is gone — the business circled it and
   asked for the insight to appear only on click. What remains is a prompt and
   the button. */
.hs-ai-only { display: flex; align-items: center; gap: 10px;
              flex-wrap: wrap; margin: 8px 0 4px; }
.hs-ai-prompt { font-size: 12.5px; font-weight: 650; cursor: help;
                color: var(--text-2, #52514e); }

/* ── Selection chips (2026-09-07) ───────────────────────────────
   Every visual states the metric, date and filters it was built under. The
   chip row is the page-level version of the same context the hovers carry. */
.hs-sel-chips { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 10px; }
.hs-sel-chip { font-size: 11.5px; line-height: 1.5;
               border: 1px solid var(--border, #e6eaf2); border-radius: 999px;
               padding: 3px 10px; background: var(--card, #fff);
               color: var(--text, #1f2937); white-space: nowrap; }
.hs-sel-chip b { font-weight: 650; }
.hs-sel-chip-note { border-color: #fcd34d; background: #fffbeb;
                    color: #92400e; font-weight: 650; }

/* ── Manual refresh (2026-09-07) ────────────────────────────────
   The page no longer polls; this is the only way to fetch newer data. */
.hs-refresh-btn { display: inline-flex; align-items: center;
                  font-size: 12.5px; font-weight: 650; cursor: pointer;
                  border: 1px solid var(--brand, #2563eb); border-radius: 8px;
                  background: var(--brand, #2563eb); color: #fff;
                  padding: 7px 14px; height: 38px; white-space: nowrap;
                  transition: filter .15s ease, transform .15s ease; }
.hs-refresh-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.hs-refresh-btn:active { transform: translateY(0); }
.hs-refresh-note { font-size: 12px; color: var(--muted, #6b7280);
                   margin: -2px 0 10px 2px; }
.hs-refresh-note .hs-stale { color: #92400e; }

/* ── Drill-down detail (2026-09-07) ─────────────────────────────
   Sixteen dimensions as compact tables rather than sixteen more Plotly
   figures: same comparison, a quarter of the space, no hover needed. */
.hs-drill-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
                gap: 14px; margin: 4px 0 10px; }
.hs-drill-metrics { max-height: 300px; overflow-y: auto; }
.hs-drill-dim-grid { display: grid; gap: 10px;
                     grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.hs-drill-dim { border: 1px solid var(--border, #e6eaf2); border-radius: 8px;
                padding: 8px 10px; background: var(--card, #fff);
                min-width: 0; overflow-x: auto; }
@media (max-width: 1100px) {
  .hs-drill-top { grid-template-columns: 1fr; }
}

/* ══════════════════════════════════════════════════════════════
   CATEGORY ANALYSIS — merchandise view (2026-09-07)
   Mostly tables by design: a merchandise team reads a range line by line,
   and a chart shows one column at a time.
   ══════════════════════════════════════════════════════════════ */
/* The KPI card's third line. The hourly page styled this inline; naming it
   means every card that has a delta line looks the same. */
.kpi-delta { font-size: 11.5px; font-weight: 600; margin-top: 3px; }

/* A grid of small finding blocks. Category Analysis no longer uses this —
   its findings were cut to one line on business instruction — but Brand
   Analysis does, for the grew / fell / new / stopped groups, which are four
   distinct lists rather than one sentence. */
.ca-findings { display: grid; gap: 10px;
               grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.ca-finding { border: 1px solid var(--border, #e6eaf2); border-radius: 8px;
              padding: 9px 12px; background: var(--card, #fff);
              min-width: 0; }

/* Cell tone in the performance tables — a class, not an inline style, so the
   table stays on the house design. */
.data-table td.ca-good { color: #16a34a; font-weight: 650; }
.data-table td.ca-bad  { color: #dc2626; font-weight: 650; }
.data-table td.ca-warn { color: #C98200; font-weight: 650; }
/* 'Not Tagged', 'No Size', 'Unmapped' and Other: real rows, but residues
   rather than findings, so they recede instead of competing. */
.data-table td.ca-dim  { color: var(--muted, #6b7280); font-style: italic; }
/* The widget's own filter row sits inside a card, so it needs less outer
   spacing than the page-level row and must not inherit its sticky offsets. */
.ca-widget-filters { margin: 2px 0 10px; padding: 0; background: transparent;
                     border: 0; box-shadow: none; position: static; }
/* Every group the same width, stated on the FLEX BASIS as well as the box —
   .filter-group sets `flex: 0 0 160px`, so a min-width alone leaves the two
   disagreeing and the row's spacing depends on which rule the browser
   resolves last (2026-09-08: the attribute row was visibly out of step). */
.ca-widget-filters .filter-group { flex: 0 0 190px; width: 190px;
                                   min-width: 190px; }
/* One group is legitimately wider: an attribute name runs to "Sleeve Length"
   and a colour value to "Multicolor | Black". The width belongs here, on the
   group, so the label and the control move together. */
.ca-widget-filters .filter-group.ca-filter-wide {
  flex: 0 0 300px; width: 300px; min-width: 300px;
}
@media (max-width: 720px) {
  .ca-widget-filters .filter-group,
  .ca-widget-filters .filter-group.ca-filter-wide {
    flex: 1 1 46%; width: auto; min-width: 0;
  }
}
.ca-page .kpi-row { margin-bottom: 12px; }

/* ══════════════════════════════════════════════════════════════
   KPI CARDS — V4.0
   ══════════════════════════════════════════════════════════════ */
.kpi-row { display: flex; gap: 10px; flex-wrap: wrap; }

.kpi-card {
  flex: 1; min-width: 155px;
  background: var(--card);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  /* No coloured top accent — uniform card. !important neutralises any
     per-page inline borderTopColor so every KPI card matches. */
  border-top-color: var(--border) !important;
  padding: 14px 16px;
  box-shadow: var(--shadow-sm);
  position: relative; overflow: hidden;
  transition: box-shadow .15s, transform .15s;
  cursor: default;
}
.kpi-card:hover {
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}
.kpi-title {
  font-size: 12px; font-weight: 500; color: var(--text-3);
  letter-spacing: 0.6px; text-transform: uppercase; margin-bottom: 6px;
  font-family: 'Figtree', sans-serif;
}
/* One standard colour for every KPI value — !important overrides per-page
   inline value colours so the set reads as one uniform group. Semantic
   colour lives only on the comparison badges. */
.kpi-value {
  font-size: 28px; font-weight: 700; color: var(--text-1) !important;
  font-family: 'Figtree', sans-serif;
  letter-spacing: -0.3px; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.kpi-ach  { font-size: 12px; font-weight: 600; margin-top: 5px; }
.kpi-mom  { font-size: 12px; color: var(--text-3); margin-top: 2px; }
.kpi-sub  { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.kpi-target {
  font-size: 11px; color: var(--text-3); margin-top: 5px;
  border-top: 1px solid var(--border); padding-top: 4px;
  font-family: 'JetBrains Mono', monospace;
}

.mom-up   { color: var(--green); }
.mom-down { color: var(--red); }

/* ══════════════════════════════════════════════════════════════
   PROGRESS BAR
   ══════════════════════════════════════════════════════════════ */
.progress-section {
  background: var(--surf-0);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  padding: 10px 14px;
  box-shadow: var(--shadow-sm);
}
.progress-meta {
  display: flex; align-items: center; gap: 14px;
  flex-wrap: wrap; margin-bottom: 7px;
}
.progress-label {
  font-size: 8px; font-weight: 700; color: var(--text-3);
  text-transform: uppercase; letter-spacing: 1.2px;
  font-family: 'Figtree', sans-serif;
}
.progress-amounts {
  font-size: 12px; font-weight: 600; color: var(--text-1);
  font-family: 'JetBrains Mono', monospace;
}
.progress-pct     { font-size: 20px; font-weight: 700; font-family: 'Figtree', sans-serif; }
.progress-runrate { font-size: 10px; color: var(--text-3); margin-left: auto; font-family: 'JetBrains Mono', monospace; }
.progress-track   { height: 6px; background: var(--surf-3); border-radius: 3px; overflow: hidden; }

/* ══════════════════════════════════════════════════════════════
   GRID LAYOUTS
   ══════════════════════════════════════════════════════════════ */
.two-col-grid   { display: grid; grid-template-columns: 1fr 1fr;       gap: 12px; }
/* Grid children default to min-width:auto, so a WIDE table stretches its
   track and pushes the neighbouring cards off-layout (2026-08-07: the new
   FULL PRICE %/MD % columns shoved Channel Mix + Delivery Type rightward).
   min-width:0 keeps every track at its fraction — wide content scrolls
   INSIDE its card via .table-scroll instead. (Was mobile-only before.) */
.two-col-grid > *, .three-col-grid > * { min-width: 0; }
.three-col-grid { display: grid; grid-template-columns: 1fr 1fr 1fr;   gap: 12px; }
@media (max-width: 1100px) { .two-col-grid   { grid-template-columns: 1fr; } }
@media (max-width: 1200px) { .three-col-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 768px)  { .three-col-grid { grid-template-columns: 1fr; } }

/* ══════════════════════════════════════════════════════════════
   SECTION CARDS — V4.0
   ══════════════════════════════════════════════════════════════ */
.section-card {
  background: var(--card);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  padding: 14px 16px;
  box-shadow: var(--shadow-sm);
}

.section-title {
  font-size: 15px; font-weight: 700; color: var(--text-1);
  text-transform: uppercase; letter-spacing: 0.5px;
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 2px;
  font-family: 'Figtree', sans-serif;
}
.section-title::before {
  content: '';
  display: inline-block; width: 4px; height: 16px;
  background: var(--brand); border-radius: 2px;
  flex-shrink: 0;
}
.section-subtitle {
  font-size: 13px; color: var(--text-2);
  margin-bottom: 10px; margin-left: 12px;
}

/* Card header row */
.section-card-header {
  display: flex; align-items: flex-start; justify-content: space-between;
}
.section-card-header > div:first-child { flex: 1; }

/* Per-card CSV export icon button */
.export-card-btn {
  background: var(--surf-2);
  border: 1px solid var(--border2);
  border-radius: var(--radius-sm);
  color: var(--text-2);
  cursor: pointer;
  font-size: 10px; font-weight: 600;
  padding: 3px 8px; line-height: 1.4;
  transition: all .15s;
  flex-shrink: 0; margin-top: 1px;
  letter-spacing: 0.3px; white-space: nowrap;
  font-family: 'Figtree', sans-serif;
}
.export-card-btn:hover {
  background: var(--brand-lite);
  border-color: var(--brand);
  color: var(--brand);
  box-shadow: var(--shadow-focus);
}

/* ══════════════════════════════════════════════════════════════
   TABLES — V4.0 charcoal headers
   ══════════════════════════════════════════════════════════════ */
.table-scroll { overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table th, .data-table td {
  padding: 7px 10px; text-align: right; white-space: nowrap;
}
.data-table th:first-child, .data-table td:first-child { text-align: left; }

.table-header-row th {
  background: #f9fafb;
  color: var(--text-3);
  font-size: 12px; font-weight: 600;
  letter-spacing: 0.5px; text-transform: uppercase;
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0;
  font-family: 'Figtree', sans-serif;
}

.data-table td {
  font-family: 'JetBrains Mono', monospace;
  color: var(--text-1);
}
.data-table td:first-child {
  font-family: 'DM Sans', sans-serif;
}
.table-row { border-bottom: 1px solid var(--border); }
.table-row:hover { background: #f9fafb; }

.table-total-row td {
  background: var(--surf-2); border-top: 2px solid var(--border2);
  font-weight: 700; color: var(--text-1);
  font-family: 'JetBrains Mono', monospace;
}
/* ── Tables on a phone or a narrow window ───────────────────────────
   Reported 2026-09-24: "many pages visuals are not properly visible on
   mobile ... especially tables", with Stock Position's grey-inventory
   split named.

   The cause is not the viewport meta tag, which is set. It is that cells
   are `white-space: nowrap` by design — a wrapped figure column is
   unreadable — so a wide table CANNOT shrink to fit. Only the tables
   whose page happened to wrap them in .table-scroll could scroll; every
   other one pushed the whole page sideways, which is what makes a
   dashboard unusable on a phone rather than merely tight.

   Making the TABLE ITSELF the scroll container fixes all of them at once,
   with no wrapper element needed in the ~40 places that render one. The
   obvious alternative — overflow-x on .section-card — was rejected: it
   would also clip anything that escapes the card, and several cards hold
   dropdown menus that do exactly that.

   `display: block` on a <table> keeps thead/tbody/tr/td at their own
   display types inside an anonymous table box, so column alignment is
   preserved; the element simply gains a scrollbar. Desktop is untouched:
   the whole rule is inside the query.                                   */
@media (max-width: 900px) {
  .data-table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    font-size: 12.5px;
  }
  .data-table th, .data-table td { padding: 6px 8px; }
  /* A sticky header inside a now-scrolling block fights the scroll and
     detaches on iOS; the table is short enough on a phone to lose it. */
  .table-header-row th { position: static; }
  /* Cards lose some of their side padding so the table gets the width. */
  .section-card { padding-left: 12px; padding-right: 12px; }
}

.fw-bold      { font-weight: 700 !important; }
.country-name { font-weight: 600; color: var(--text-1); font-family: 'DM Sans', sans-serif !important; }
.event-tag    { color: var(--text-2) !important; font-family: 'DM Sans', sans-serif !important; font-size: 11px; }
.wow-up       { color: var(--green) !important; font-weight: 600; }
.wow-down     { color: var(--red) !important;   font-weight: 600; }

/* ══════════════════════════════════════════════════════════════
   STATUS BADGES (RAG)
   ══════════════════════════════════════════════════════════════ */
.rag-green { color: var(--green) !important; }
.rag-amber { color: var(--amber) !important; }
.rag-red   { color: var(--red) !important; }

/* ══════════════════════════════════════════════════════════════
   CHANNEL MIX / EVENT GRIDS
   ══════════════════════════════════════════════════════════════ */
.channel-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 8px; }
.event-grid   { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 8px; }
.event-col    { min-width: 0; overflow: hidden; }
@media (max-width: 900px) {
  .channel-grid, .event-grid { grid-template-columns: 1fr; }
}

/* ══════════════════════════════════════════════════════════════
   GAP ANALYSIS + USER ANALYTICS — stat pills
   ══════════════════════════════════════════════════════════════ */
.gap-pills, .user-stat-pills { display: flex; gap: 8px; flex-wrap: wrap; }

.user-stat-pill {
  flex: 1; min-width: 105px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  border-left: 3px solid var(--brand);
  padding: 10px 12px;
  box-shadow: var(--shadow-sm);
}
.pill-label {
  font-size: 8px; font-weight: 700; color: var(--text-3);
  letter-spacing: 1.2px; text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
}
.pill-value {
  font-size: 18px; font-weight: 700;
  font-family: 'Figtree', sans-serif;
  margin: 3px 0 2px; color: var(--text-1);
}
.pill-sub { font-size: 10px; color: var(--text-3); }

/* ══════════════════════════════════════════════════════════════
   INSIGHTS — block callout style (design.md .insight)
   ══════════════════════════════════════════════════════════════ */
.insight-list { list-style: none; display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.insight-item {
  font-size: 12.5px; color: var(--text-2); line-height: 1.6;
  padding: 9px 12px;
  background: linear-gradient(90deg, #eff6ff 0%, #f5f3ff 100%);
  border-radius: 6px;
  border-left: 3px solid var(--brand);
}
.insight-item strong { color: var(--brand); }
/* Individual callout variant (used in some pages as .insight) */
.insight {
  background: linear-gradient(90deg, #eff6ff 0%, #f5f3ff 100%);
  border-left: 3px solid var(--brand);
  border-radius: 6px;
  padding: 9px 12px;
  font-size: 12.5px; color: var(--text-2); line-height: 1.6;
  margin-top: 8px;
}
.insight strong { color: var(--brand); }

/* ══════════════════════════════════════════════════════════════
   COMING SOON PAGES
   ══════════════════════════════════════════════════════════════ */
.coming-soon-wrapper {
  display: flex; align-items: center; justify-content: center;
  flex: 1; padding: 60px 20px;
}
.coming-soon-card {
  background: var(--card);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  border-top: 3px solid var(--brand);
  padding: 48px 60px;
  text-align: center;
  box-shadow: var(--shadow);
  max-width: 500px;
}
.coming-soon-icon {
  font-size: 44px; color: var(--brand);
  margin-bottom: 20px; display: block;
}
.coming-soon-title {
  font-size: 22px; font-weight: 700;
  color: var(--text-1); margin-bottom: 12px;
  font-family: 'Figtree', sans-serif;
}
.coming-soon-desc {
  font-size: 13px; color: var(--text-2);
  line-height: 1.6; margin-bottom: 24px;
}
.coming-soon-badge {
  display: inline-block;
  background: var(--nav-active-bg);
  color: var(--nav-active-text);
  border: 1px solid var(--nav-active-border);
  border-radius: var(--radius-pill);
  padding: 5px 18px;
  font-size: 10px; font-weight: 700;
  letter-spacing: 1.5px;
  font-family: 'Figtree', sans-serif;
}

/* ══════════════════════════════════════════════════════════════
   FOOTER
   ══════════════════════════════════════════════════════════════ */
.dashboard-footer {
  background: var(--bfl-charcoal);
  padding: 10px 20px;
  display: flex; align-items: center;
  justify-content: space-between; flex-wrap: wrap; gap: 10px;
}
.footer-copy { font-size: 9px; color: rgba(255,255,255,.35); }
.footer-brands { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.footer-brand {
  font-size: 8px; font-weight: 700; color: rgba(255,255,255,.35);
  letter-spacing: 0.5px; text-transform: uppercase;
  padding: 3px 8px; border: 1px solid rgba(255,255,255,.12);
  border-radius: var(--radius-sm);
  font-family: 'Figtree', sans-serif;
}
.footer-brand.highlight { color: var(--bfl-yellow); border-color: rgba(255,209,0,.35); }

/* ══════════════════════════════════════════════════════════════
   MISC
   ══════════════════════════════════════════════════════════════ */
.no-data { text-align: center; padding: 60px; color: var(--text-3); }

/* ── Background load status pulse dot ───────────────────────── */
.bg-pulse-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--amber);
  animation: bg-pulse 1.2s ease-in-out infinite;
  flex-shrink: 0;
}
@keyframes bg-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%       { opacity: .4; transform: scale(.7); }
}

/* ── Header user info / logout (legacy classes kept) ─────────── */
.header-user-info {
  display: flex; align-items: center; gap: 8px;
  padding-right: 12px; border-right: 1px solid var(--border);
  margin-right: 12px;
}
.header-username { font-size: 11px; font-weight: 600; color: var(--text-1); }
.header-role-badge {
  font-size: 8px; font-weight: 700;
  background: var(--nav-active-bg); color: #6B5500;
  border: 1px solid var(--nav-active-border);
  border-radius: var(--radius-sm); padding: 2px 7px;
  text-transform: uppercase; letter-spacing: 0.8px;
  font-family: 'Figtree', sans-serif;
}

/* ══════════════════════════════════════════════════════════════
   ADMIN PANEL
   ══════════════════════════════════════════════════════════════ */
.admin-panel {
  display: flex; flex-direction: column; gap: 0;
  background: var(--surf-0);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.admin-tabs { display: none !important; }

/* Hex Hub Navigation */
.admin-hex-hub-wrap {
  position: relative;
  width: 520px; height: 440px;
  margin: 8px auto 4px;
}
.admin-hub-center {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 110px; height: 110px;
  border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, var(--bfl-graphite), var(--bfl-charcoal));
  border: 2px solid rgba(255,209,0,.50);
  box-shadow: 0 0 28px rgba(255,209,0,.16), 0 0 55px rgba(37,99,235,.10);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 5px;
  z-index: 5;
}
.admin-hub-ring {
  position: absolute; left: 50%; top: 50%;
  border-radius: 50%; border: 1px solid rgba(255,209,0,.12);
  transform: translate(-50%,-50%);
  animation: hub-ring-pulse 3.5s ease-in-out infinite;
  pointer-events: none; z-index: 2;
}
@keyframes hub-ring-pulse {
  0%,100% { opacity:.4; transform: translate(-50%,-50%) scale(1); }
  50%      { opacity:.9; transform: translate(-50%,-50%) scale(1.04); }
}
.admin-hub-svg {
  position: absolute; top: 0; left: 0;
  width: 100%; height: 100%;
  pointer-events: none; z-index: 3;
}
.admin-hex-tile {
  position: absolute;
  width: 110px; height: 110px;
  cursor: pointer;
  transition: transform .2s, filter .2s;
  z-index: 10;
}
.admin-hex-tile:hover { transform: scale(1.1); }
.admin-hex-tile.hex-active { filter: drop-shadow(0 0 14px rgba(255,209,0,.85)); }
.admin-hex-outer {
  width: 100%; height: 100%;
  clip-path: polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
  display: flex; align-items: center; justify-content: center;
}
.admin-hex-outer.hc-yellow { background: rgba(255,209,0,.30); }
.admin-hex-outer.hc-blue   { background: rgba(37,99,235,.30); }
.admin-hex-outer.hc-green  { background: rgba(14,159,110,.30); }
.admin-hex-outer.hc-purple { background: rgba(111,86,217,.30); }
.admin-hex-outer.hc-red    { background: rgba(209,67,91,.30); }
.admin-hex-outer.hc-slate  { background: rgba(100,116,139,.20); }
.admin-hex-tile:hover .admin-hex-outer.hc-yellow { background: rgba(255,209,0,.50); }
.admin-hex-tile:hover .admin-hex-outer.hc-blue   { background: rgba(37,99,235,.50); }
.admin-hex-tile:hover .admin-hex-outer.hc-green  { background: rgba(14,159,110,.50); }
.admin-hex-tile:hover .admin-hex-outer.hc-purple { background: rgba(111,86,217,.50); }
.admin-hex-tile:hover .admin-hex-outer.hc-red    { background: rgba(209,67,91,.50); }
.admin-hex-tile.hex-active .admin-hex-outer { filter: brightness(1.25); }
.admin-hex-inner {
  width: 93%; height: 93%;
  clip-path: polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
  background: rgba(10,22,40,.92);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 6px;
}
.admin-hex-label {
  font-size: 9px; font-weight: 700; text-align: center;
  text-transform: uppercase; letter-spacing: .05em;
  color: rgba(255,255,255,.82); line-height: 1.3; max-width: 72px;
  font-family: 'Figtree', sans-serif;
}
.admin-hex-section-label {
  font-size: 10px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-3); text-align: center;
  padding: 6px 0 14px; font-family: 'Figtree', sans-serif;
}

/* Tab body */
.admin-tab-body {
  padding: 18px 20px;
  display: flex; flex-direction: column; gap: 14px;
}

/* Section headers */
.admin-section-hdr {
  display: flex; align-items: center; justify-content: space-between;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.admin-section-title {
  font-size: 11px; font-weight: 700; letter-spacing: 1px;
  color: var(--text-2); text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
}
.admin-subsection-title {
  font-size: 10px; font-weight: 700; letter-spacing: .8px;
  color: var(--text-3); text-transform: uppercase;
  margin-bottom: 8px; font-family: 'Figtree', sans-serif;
}

/* Table */
.admin-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.admin-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.admin-table-matrix th, .admin-table-matrix td { text-align: center; }
.admin-table-matrix th:first-child,
.admin-table-matrix td:first-child { text-align: left; }
.admin-thead-row th {
  background: #f9fafb;
  padding: 7px 12px;
  font-size: 10px; font-weight: 600; letter-spacing: .5px;
  color: var(--text-3); text-transform: uppercase;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  font-family: 'Figtree', sans-serif;
}
.admin-tr td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--surf-3);
  vertical-align: middle;
  color: var(--text-1);
}
.admin-tr:last-child td { border-bottom: none; }
.admin-tr:hover td { background: var(--surf-2); }
.admin-td-bold  { font-weight: 600; color: var(--text-1) !important; }
.admin-td-small { font-size: 11px; color: var(--text-2); }
.admin-td-muted { color: var(--text-3); }
.admin-td-actions { display: flex; gap: 6px; align-items: center; }

/* Row action buttons */
.admin-row-btn {
  padding: 3px 8px; font-size: 11px; font-weight: 600;
  border: 1px solid var(--border2);
  background: var(--surf-0); color: var(--text-2);
  border-radius: var(--radius-sm); cursor: pointer;
  transition: background .12s, color .12s;
}
.admin-row-btn:hover { background: var(--surf-2); color: var(--text-1); }
.admin-row-btn-del { border-color: rgba(209,67,91,.3); color: var(--red); }
.admin-row-btn-del:hover { background: var(--red-bg); }
.admin-row-btn-test { border-color: rgba(37,99,235,.3); color: var(--brand); }
.admin-row-btn-test:hover { background: var(--brand-lite); color: var(--brand-hov); }

/* Badges */
.admin-badge {
  display: inline-block; padding: 2px 8px; border-radius: var(--radius-pill);
  font-size: 10px; font-weight: 700; letter-spacing: .4px;
  font-family: 'Figtree', sans-serif;
}
.admin-badge-blue   { background: rgba(37,99,235,.10); color: #1d4ed8; border: 1px solid rgba(37,99,235,.25); }
.admin-badge-green  { background: var(--green-bg); color: var(--green); border: 1px solid rgba(14,159,110,.25); }
.admin-badge-orange { background: rgba(201,133,18,.10); color: #9a6200; border: 1px solid rgba(201,133,18,.25); }
.admin-badge-yellow { background: var(--nav-active-bg); color: var(--nav-active-text); border: 1px solid var(--nav-active-border); }
.admin-badge-purple { background: rgba(111,86,217,.10); color: #6f56d9; border: 1px solid rgba(111,86,217,.25); }

/* Role badges */
.role-badge {
  display: inline-block; padding: 2px 9px; border-radius: var(--radius-pill);
  font-size: 10px; font-weight: 700; letter-spacing: .3px;
  font-family: 'Figtree', sans-serif;
}
.role-admin           { background: var(--nav-active-bg); color: var(--nav-active-text); border: 1px solid var(--nav-active-border); }
.role-cxo             { background: rgba(37,99,235,.10); color: #1d4ed8; border: 1px solid rgba(37,99,235,.28); }
.role-country_manager { background: var(--green-bg); color: var(--green); border: 1px solid rgba(14,159,110,.28); }
.role-analyst         { background: rgba(111,86,217,.10); color: #6f56d9; border: 1px solid rgba(111,86,217,.28); }
.role-viewer          { background: var(--surf-2); color: var(--text-2); border: 1px solid var(--border2); }

/* Form grid & fields */
.admin-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px; }
.admin-field { display: flex; flex-direction: column; gap: 5px; }
.admin-field:last-child { grid-column: 1 / -1; }
.admin-field-label {
  font-size: 10px; font-weight: 700; letter-spacing: .5px;
  color: var(--text-3); text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
}
.admin-field-hint { font-size: 10px; color: var(--text-3); margin-top: 2px; }

/* Inputs */
.admin-input {
  width: 100%; padding: 7px 10px;
  border: 1px solid var(--border2);
  border-radius: var(--radius-sm);
  background: var(--surf-0); color: var(--text-1);
  font-size: 13px; font-family: 'DM Sans', sans-serif;
  outline: none; transition: border-color .15s, box-shadow .15s;
}

/* ══════════════════════════════════════════════════════════════
   DAILY SALES REPORT (DSR)
   ══════════════════════════════════════════════════════════════ */
.dsr-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  margin-bottom: 16px;
}
.dsr-page-title {
  font-size: 18px; font-weight: 800; letter-spacing: .5px;
  color: var(--text-1); font-family: 'Figtree', sans-serif;
}
.dsr-page-date {
  font-size: 12px; color: var(--text-3); margin-top: 2px;
}

/* KPI strip */
.dsr-kpi-strip {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
  margin-bottom: 12px;
}
@media (max-width: 1100px) { .dsr-kpi-strip { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 700px)  { .dsr-kpi-strip { grid-template-columns: repeat(2, 1fr); } }

.dsr-kpi-card {
  background: var(--surf-0);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
}
.dsr-kpi-label {
  font-size: 11px; font-weight: 700; letter-spacing: .8px;
  color: var(--text-3); text-transform: uppercase;
  font-family: 'Figtree', sans-serif; margin-bottom: 4px;
}
.dsr-kpi-value {
  font-size: 24px; font-weight: 800; color: var(--text-1);
  font-family: 'JetBrains Mono', monospace; line-height: 1.1;
}
.dsr-kpi-target {
  font-size: 10px; color: var(--text-3); margin-top: 5px;
}
.dsr-kpi-ach {
  font-size: 12px; font-weight: 700; margin-top: 1px;
}

/* MTD pacing chips */
.dsr-pace-row {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px;
}
.dsr-pace-chip {
  font-size: 10px; color: var(--text-2);
  background: var(--surf-2); border-radius: 20px;
  padding: 3px 10px; white-space: nowrap;
}

/* Two-column rows */
.dsr-two-col {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0;
}
@media (max-width: 900px) { .dsr-two-col { grid-template-columns: 1fr; } }

.dsr-half {
  margin-right: 12px;
}
.dsr-two-col > .dsr-half:last-child { margin-right: 0; }

/* No-target notice */
.dsr-notice {
  font-size: 11px; color: var(--amber);
  background: rgba(243,156,18,.08);
  border-left: 3px solid var(--amber);
  border-radius: 4px;
  padding: 8px 12px; margin-bottom: 12px;
}
.admin-input:focus {
  border-color: var(--brand);
  box-shadow: var(--shadow-focus);
}
.admin-textarea { resize: vertical; min-height: 64px; }

/* Dropdown override inside admin panel */
.admin-dropdown .Select-control,
.admin-dropdown .dash-dropdown .Select-control {
  border: 1px solid var(--border2) !important;
  border-radius: var(--radius-sm) !important;
  font-size: 13px !important;
  min-height: 32px !important;
}

/* Toggle */
/* ══════════════════════════════════════════════════════════════
   WIDGET / METRIC VISIBILITY MATRICES
   Added 2026-09-10. These grids are 37 and 73 columns wide, so the
   two things that make them usable are a DEPARTMENT column that
   stays put while you scroll right, and column headings that fit
   without pushing every column to the width of its label.
   ══════════════════════════════════════════════════════════════ */
.dv-matrix { min-width: max-content; }

/* The group name spans its columns, so you can tell where "Returns &
   cancellations" ends and "Orders & customers" begins. */
.dv-matrix .dv-group-head {
  background: var(--surf-3, #f3f4f6);
  border-left: 2px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 5px 10px;
  font-size: 10px; font-weight: 700; letter-spacing: .4px;
  color: var(--text-2); text-transform: uppercase;
  text-align: left !important; white-space: nowrap;
  font-family: 'Figtree', sans-serif;
}

/* Vertical column labels: 73 horizontal headings would make the table
   ten screens wide. Each column then costs ~34px instead of ~120px. */
.dv-matrix .dv-col-head {
  padding: 4px 2px 6px;
  vertical-align: bottom;
  background: #f9fafb;
  border-bottom: 1px solid var(--border);
  height: 132px;
}
.dv-matrix .dv-col-label {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  max-height: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10px; font-weight: 600;
  color: var(--text-2);
  text-transform: none; letter-spacing: 0;
  margin: 0 auto;
  font-family: 'Figtree', sans-serif;
}

/* The department column stays readable at any scroll offset. Both the
   header and the body cell need it, and the header needs the higher
   z-index so it wins where they cross. */
.dv-matrix .dv-sticky-head,
.dv-matrix .dv-sticky-cell {
  position: sticky;
  left: 0;
  background: #ffffff;
  border-right: 2px solid var(--border);
  text-align: left !important;
  white-space: nowrap;
  min-width: 150px;
}
.dv-matrix .dv-sticky-head { background: #f9fafb; z-index: 3; }
.dv-matrix .dv-sticky-cell { z-index: 2; }
.dv-matrix tbody tr:hover .dv-sticky-cell { background: var(--surf-2, #fafafa); }

/* A FAMILY switch — one of the seven legacy can_see_* permissions — sitting
   at the head of the metric group it gates. Tinted so it reads as a
   different KIND of control from the metric switches beside it: it turns
   off a whole family at once, and it writes to a boolean column rather than
   the deny-list. */
.dv-matrix .dv-cell-family {
  background: rgba(255, 209, 0, .10);
  border-left: 2px solid var(--border);
}
.dv-matrix tbody tr:hover .dv-cell-family { background: rgba(255, 209, 0, .16); }

/* A card whose PAGE this department cannot open: the switch is disabled,
   and the cell says why on hover. Business instruction 2026-09-10 —
   "only allowed page should have access to all widget and data
   visibility" — a live switch there would imply it did something. */
.dv-matrix .dv-cell-blocked {
  background: repeating-linear-gradient(
    135deg, transparent, transparent 4px,
    rgba(148, 163, 184, .18) 4px, rgba(148, 163, 184, .18) 8px);
}
.dv-matrix .dv-cell-blocked .form-check-input { opacity: .35; cursor: not-allowed; }

.admin-toggle .form-check { margin: 0; }
.admin-toggle .form-check-input {
  width: 32px !important; height: 18px !important; cursor: pointer;
}
.admin-toggle .form-check-input:checked {
  background-color: var(--brand) !important;
  border-color: var(--brand-hov) !important;
}
.admin-check .form-check-label { font-size: 13px; color: var(--text-1); }

/* Panel action buttons */
.admin-btn-add {
  padding: 6px 14px; font-size: 11px; font-weight: 700;
  background: var(--brand); color: #ffffff;
  border: none; border-radius: var(--radius-sm);
  cursor: pointer; transition: all .12s;
  letter-spacing: .3px; font-family: 'Figtree', sans-serif;
}
.admin-btn-add:hover { background: var(--brand-hov); box-shadow: var(--shadow-focus); }
.admin-btn-save {
  padding: 7px 20px; font-size: 12px; font-weight: 700;
  background: var(--bfl-charcoal); color: #fff;
  border: none; border-radius: var(--radius-sm);
  cursor: pointer; transition: opacity .12s;
  font-family: 'Figtree', sans-serif;
}
.admin-btn-save:hover { opacity: .85; }
.admin-btn-cancel {
  padding: 7px 16px; font-size: 12px; font-weight: 600;
  background: var(--surf-2); color: var(--text-2);
  border: 1px solid var(--border2); border-radius: var(--radius-sm);
  cursor: pointer; transition: background .12s;
  font-family: 'DM Sans', sans-serif;
}
.admin-btn-cancel:hover { background: var(--surf-3); }

/* Status / error messages */
.admin-msg { min-height: 18px; font-size: 12px; }
.admin-msg-err { color: var(--red); font-size: 11px; }

/* ══════════════════════════════════════════════════════════════
   WIDGET PANELS — chart containers with in-panel filter controls
   Mirrors the reference design (compact filter pill in header)
   ══════════════════════════════════════════════════════════════ */
.widget-panel {
  background: var(--surf-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  flex: 1;
  min-width: 0;
}

.widget-panel-hdr {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  gap: 8px;
}

.widget-panel-title {
  font-size: 12px; font-weight: 700;
  color: var(--text-2); letter-spacing: 0.6px;
  text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
  flex: 1;
}

/* Compact select filter inside chart header */
.widget-filter select,
.widget-filter-select {
  appearance: none;
  background: var(--surf-0);
  border: 1px solid var(--border2);
  border-radius: var(--radius-sm);
  color: var(--text-2);
  cursor: pointer;
  font-size: 10px;
  font-family: 'DM Sans', sans-serif;
  font-weight: 500;
  height: 22px;
  line-height: 22px;
  padding: 0 20px 0 7px;
  transition: border-color .12s;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath fill='%239A9A92' d='M0 0l4 5 4-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 6px center;
}
.widget-filter select:hover,
.widget-filter-select:hover {
  border-color: var(--brand);
  color: var(--text-1);
}
.widget-filter select:focus,
.widget-filter-select:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: var(--shadow-focus);
}

/* Dash dcc.Dropdown used as a mini widget filter */
.widget-filter button.dash-dropdown {
  font-size: 10px !important;
  height: 24px !important;
  min-height: 24px !important;
  min-width: 90px !important;
  max-width: 150px !important;
  padding: 0 24px 0 8px !important;
  border-radius: var(--radius-sm) !important;
}

/* Chart insight text below a chart */
.chart-insight {
  margin-top: 8px;
  padding: 7px 10px;
  background: linear-gradient(90deg, #eff6ff 0%, #f5f3ff 100%);
  border-left: 3px solid var(--brand);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 11px;
  color: var(--text-2);
  line-height: 1.5;
}
.chart-insight strong { color: var(--text-1); }

/* Delta badge — positive/negative pill used in KPI or table */
.delta-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12px; font-weight: 700;
  border-radius: var(--radius-pill);
  padding: 2px 8px;
  white-space: nowrap;
  font-family: 'Figtree', sans-serif;
}
.delta-badge-up   { background: var(--green-bg); color: var(--green); }
.delta-badge-down { background: var(--red-bg);   color: var(--red);   }
.delta-badge-flat { background: var(--amber-bg); color: var(--amber); }

/* DSR section heading */
.dsr-section-title {
  font-size: 11px; font-weight: 700; letter-spacing: 0.6px;
  color: var(--text-2); text-transform: uppercase;
  display: flex; align-items: center; gap: 8px;
  margin: 14px 0 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
  font-family: 'Figtree', sans-serif;
}

/* Metric comparison pill in KPI footer */
.kpi-delta-row {
  display: flex; align-items: center; gap: 6px;
  margin-top: 7px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
}

/* Section card improved header layout */
.section-card-hdr-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.section-card-hdr-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

/* Improved data table alternating rows */
.data-table tbody tr:nth-child(even) td {
  background: rgba(249, 250, 251, 0.7);
}
.data-table tbody tr:hover td { background: #f9fafb !important; }

/* DSR KPI improvements */
.dsr-kpi-value {
  font-size: 24px !important;
  font-weight: 800 !important;
}
.dsr-kpi-label {
  font-size: 11px !important;
  letter-spacing: 0.5px !important;
}

/* Info / code */
.admin-info-text {
  font-size: 11px; color: var(--text-2);
  background: var(--brand-lite);
  border-left: 4px solid var(--brand);
  padding: 8px 12px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.admin-code {
  font-family: 'JetBrains Mono', monospace; font-size: 11px;
  background: var(--surf-2); color: var(--text-1);
  padding: 2px 6px; border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}
.admin-code-sm { font-size: 10px; }

/* ══ DEPARTMENT OVERVIEW CARDS ══════════════════════════════════════════════ */

.dept-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-bottom: 0;
}
@media (max-width: 1200px) { .dept-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 700px)  { .dept-grid { grid-template-columns: 1fr; } }

.dept-card {
  background: var(--surf-0);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);  /* overridden inline per dept */
  border-radius: var(--radius);
  padding: 14px 15px 10px;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 0;
  transition: box-shadow .15s;
}
.dept-card:hover { box-shadow: var(--shadow-md, 0 4px 16px rgba(0,0,0,0.08)); }

.dept-card-badge {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  font-family: 'Figtree', sans-serif;
  margin-bottom: 8px;
}

.dept-primary-value {
  font-size: 27px;
  font-weight: 800;
  color: var(--text-1);
  line-height: 1.1;
  font-family: 'Figtree', sans-serif;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dept-primary-label {
  font-size: 11px;
  color: var(--text-3);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  margin-bottom: 6px;
}

.dept-metrics-row {
  display: flex;
  gap: 0;
  border-top: 1px solid var(--border);
  padding-top: 8px;
  margin-top: 6px;
}

.dept-metric {
  flex: 1;
  min-width: 0;
  padding: 0 6px;
  border-right: 1px solid var(--border);
}
.dept-metric:first-child { padding-left: 0; }
.dept-metric:last-child  { border-right: none; }

.dept-metric-val {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-1);
  font-family: 'JetBrains Mono', monospace;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dept-metric-lbl {
  font-size: 8.5px;
  color: var(--text-3);
  text-transform: uppercase;
  letter-spacing: 0.4px;
  margin-top: 2px;
  white-space: nowrap;
}

/* ══ CHART PANELS (cleaner widget-panel variant) ═══════════════════════════ */

/* Improved widget-panel — whiter background */
.widget-panel {
  background: var(--surf-0) !important;
  border: 1px solid var(--border) !important;
  border-radius: var(--radius) !important;
  padding: 12px 14px 8px !important;
  flex: 1 !important;
  min-width: 0 !important;
  box-shadow: var(--shadow-sm) !important;
}

/* Modal overrides */
.modal-header { border-bottom: 1px solid var(--border) !important; }
.modal-footer { border-top: 1px solid var(--border) !important; gap: 8px; }
.modal-title  {
  font-size: 14px !important; font-weight: 700 !important;
  color: var(--text-1) !important;
  font-family: 'Figtree', sans-serif !important;
}

/* ══════════════════════════════════════════════════════════════
   MOBILE / TABLET — everything below is scoped to the breakpoint or
   is display:none on desktop, so the existing (desktop) view is
   completely unaffected outside these rules.
   ══════════════════════════════════════════════════════════════ */

/* Hamburger button — hidden on desktop, shown only below the breakpoint */
.sidebar-toggle-btn {
  display: none;
  background: rgba(255,255,255,.12);
  border: none;
  border-radius: 8px;
  color: #ffffff;
  width: 36px; height: 36px;
  font-size: 16px;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sidebar-toggle-btn:hover { background: rgba(255,255,255,.22); }

.sidebar-backdrop {
  position: fixed;
  inset: 60px 0 0 0;
  background: rgba(15, 23, 42, .45);
  z-index: 999;
}

@media (max-width: 900px) {
  /* Sidebar becomes an off-canvas overlay instead of a fixed grid column. */
  .sidebar-toggle-btn { display: inline-flex; }

  .layout { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed;
    top: 60px;
    left: 0;
    height: calc(100vh - 60px);
    z-index: 1000;
    transform: translateX(-100%);
    transition: transform .25s ease;
    box-shadow: 2px 0 16px rgba(0,0,0,.35);
  }
  #sidebar-container.sidebar-open .sidebar { transform: translateX(0); }

  /* Filter dropdowns: fixed 160px boxes don't fit a phone screen — let them
     flex and shrink instead, while still wrapping onto new rows as before. */
  .filter-group {
    flex: 1 1 140px;
    width: auto;
    min-width: 120px;
  }

  /* KPI / section grids already collapse to 1 column via their own media
     queries at narrower widths (768/700/900px) — nothing to add here beyond
     what the existing rules for .two-col-grid / .three-col-grid provide. */

  /* Wide tables and charts: scroll horizontally inside their own card rather
     than squeezing/breaking the page layout. */
  .data-table { min-width: 480px; }
  .table-scroll, .admin-table-wrap { -webkit-overflow-scrolling: touch; }
}

@media (max-width: 640px) {
  .header-title { font-size: 15px !important; }
  .header-logo  { width: 32px; height: 32px; font-size: 12px; }
  .section-card { padding: 10px 12px; }
}

/* ══════════════════════════════════════════════════════════════
   SALES REPORTS — sparkline hover/click-to-expand popup
   Pure CSS reveal (no callback): the small trend chart sits inside a
   wrapper; a full-size Actual-vs-Target chart is already in the DOM,
   hidden, and only shown on hover (or touch, via :focus for tap support).
   ══════════════════════════════════════════════════════════════ */
.sr3-spark-wrap { position: relative; display: inline-block; }
/* Dash's dcc.Graph resizes itself to fill its container via a ResizeObserver,
   ignoring the figure's own height/width unless the OUTER element is also
   hard-constrained -- without this the "mini" sparkline stretches to fill
   the whole table cell and looks like a permanently-shown big chart. */
.sr3-spark-mini-wrap {
  width: 130px; height: 40px; overflow: hidden; cursor: pointer;
}
.sr3-spark-mini-wrap, .sr3-spark-mini-wrap .js-plotly-plot,
.sr3-spark-mini-wrap .plot-container, .sr3-spark-mini-wrap .svg-container {
  width: 130px !important; height: 40px !important;
}
/* position:fixed + viewport-centered (not anchored to the hovered row) —
   anchoring to the row clipped off-screen for rows near the bottom of a long
   table (e.g. the last couple of metrics); centering guarantees every
   popup is fully visible and comfortably readable regardless of which row
   triggered it or how far the table is scrolled. */
/* Hidden via visibility/opacity, NOT display:none. Dash's dcc.Graph measures
   its container's layout size once at mount time (Dash mounts every row's
   popup upfront; hover only toggles CSS). A display:none container has zero
   layout size, so the chart would permanently lock in at ~0 width the moment
   it mounts -- and with config.responsive:False (needed to stop the
   ResizeObserver from re-stretching the mini sparkline elsewhere) it never
   gets a chance to re-measure later, no matter how the popup is revealed.
   visibility:hidden keeps the full 640x400 box in layout (so Plotly measures
   it correctly from the first render) while still hiding it visually and
   from interaction until hovered/focused. */
.sr3-spark-popup {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  position: fixed;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 5000;
  width: 640px; height: 400px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md, 0 12px 40px rgba(0,0,0,.30));
  padding: 10px;
}
/* Same fix as the mini sparkline: without a stable, already-correct-size
   container, dcc.Graph's ResizeObserver negotiates the chart down to a
   smaller/cropped render on its first paint. Force both the Graph wrapper
   and the actual Plotly-rendered elements to the figure's own dimensions. */
.sr3-spark-popup, .sr3-spark-popup .js-plotly-plot,
.sr3-spark-popup .plot-container, .sr3-spark-popup .svg-container {
  width: 640px !important; height: 400px !important;
}
/* CLICK-ONLY reveal (business 2026-08-03): focus (click/tap) opens on ALL
   devices; the ✕ Close (or clicking anywhere else) blurs the wrap and the
   popup hides. The old desktop :hover reveal is GONE — it also broke ✕
   Close, because after the blur the pointer was still hovering the popup
   area and the :hover rule instantly re-showed it. */
.sr3-spark-wrap:focus-within .sr3-spark-popup {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
}
/* ✕ Close inside the popup — the ONLY dismiss control besides clicking
   elsewhere (assets/sr3_popup_close.js drops focus on click/tap). */
.sr3-popup-close {
  position: absolute;
  top: 8px;
  right: 10px;
  z-index: 1;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-3);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  cursor: pointer;
  transition: all .15s;
}
.sr3-popup-close:hover { color: #dc2626; border-color: #dc2626; }
/* The popup's ancestor <td> is position:sticky + z-index:2 (required so the
   METRIC/comparison/TREND columns stay frozen while the detail columns
   scroll). Every row's frozen cells share that same z-index, and later rows
   are later in DOM order, so their sticky cells painted OVER this row's
   popup wherever it overlapped the frozen-column area -- the popup's own
   z-index:5000 only wins fights within its own row's local stacking context,
   never against a sibling row's. Promoting the whole hovered/focused row to
   a much higher z-index escapes that trap: everything nested inside it,
   including the popup several levels down, now stacks above every other
   row's cells instead of being capped by its immediate ancestor. */
.table-row:has(.sr3-spark-wrap:focus-within) {
  position: relative;
  z-index: 10000;
}
/* Dim the page behind the popup so the expanded chart is easy to read —
   shown/hidden by the same focus rule via a sibling pseudo-element trick:
   the wrap itself grows an ::before backdrop while the popup is open. */
.sr3-spark-wrap:focus-within::before {
  content: "";
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, .35);
  z-index: 4999;
  /* The fullscreen backdrop is part of the wrap for hit-testing — without
     this, hovering ANYWHERE kept the wrap ':hover' once the popup opened,
     so the popup could never be dismissed by moving the mouse away. */
  pointer-events: none;
}
/* Matrix cells never wrap their numbers, and the sticky frozen columns need
   an opaque background so scrolling detail-column content doesn't show
   through underneath them. */
.sr3-matrix td, .sr3-matrix th { background-clip: padding-box; }

/* The generic .data-table rule sets width:100% with the default table-layout
   (auto). For widgets with few detail columns (Week Report ~5 columns, Month
   Report 12, Country Report ~8-10), that stretches the table to fill its
   container and lets the browser redistribute column widths proportionally,
   which no longer matches the pixel offsets _frozen_style() precomputed in
   Python for the sticky columns -- the frozen METRIC/comparison/TREND columns
   end up overlapping the first detail column(s), and because the table now
   exactly fills its container there's nothing left to overflow, so no
   scrollbar appears either. Forcing the table to size to its own content
   (never stretched, never shrunk) keeps the sticky offsets accurate and lets
   overflow -- and the scrollbar -- trigger only when the content genuinely
   exceeds the container, regardless of how many detail columns there are.
   .data-table.sr3-matrix has higher specificity than plain .data-table. */
.data-table.sr3-matrix { width: max-content; table-layout: fixed; }


/* ==============================================================================
   LAST MILE — tab strip, segmented control, slide-over panel.
   Token values only (design.md): --brand #2563eb, --border, --card, --text-3.
   .lm-tab implements the design.md .tab spec (muted 14px/600, transparent 3px
   bottom border, active = brand text + brand underline); .lm-seg matches the
   existing compare-toggle button treatment.
   ============================================================================== */
.lm-tabs {
  display: flex; gap: 4px; border-bottom: 2px solid var(--border);
  margin-bottom: 2px; flex-wrap: wrap;
}
.lm-tab {
  padding: 9px 16px; font-size: 14px; font-weight: 600;
  color: var(--text-3); text-decoration: none;
  border-bottom: 3px solid transparent; margin-bottom: -2px;
  transition: all .15s;
}
.lm-tab:hover { color: var(--brand, #2563eb); }
.lm-tab-active {
  color: var(--brand, #2563eb);
  border-bottom-color: var(--brand, #2563eb);
}

.lm-seg { display: inline-flex; gap: 0; border: 1px solid var(--border);
          border-radius: 8px; overflow: hidden; background: var(--card); }
.lm-seg-btn {
  padding: 7px 14px; font-size: 12.5px; font-weight: 600;
  color: var(--text-3); background: transparent; border: none;
  border-right: 1px solid var(--border); cursor: pointer; transition: all .15s;
  white-space: nowrap;
}
.lm-seg-btn:last-child { border-right: none; }
.lm-seg-btn:hover { color: var(--brand, #2563eb); }
.lm-seg-active { background: var(--brand, #2563eb); color: #ffffff; }
.lm-seg-active:hover { color: #ffffff; }

/* AWB slide-over: fixed right panel, hidden until .lm-slide-open. */
.lm-slide {
  position: fixed; top: 0; right: 0; height: 100vh; width: min(560px, 92vw);
  background: var(--card); border-left: 1px solid var(--border);
  box-shadow: -12px 0 40px rgba(15, 23, 42, .18);
  transform: translateX(105%); transition: transform .2s ease;
  z-index: 6000; overflow-y: auto;
}
.lm-slide-open { transform: translateX(0); }
.lm-slide-inner { padding: 18px; }
.lm-slide-close {
  border: 1px solid var(--border); background: var(--card); color: var(--text-3);
  border-radius: 8px; width: 30px; height: 30px; cursor: pointer;
  font-size: 13px; transition: all .15s;
}
.lm-slide-close:hover { color: #dc2626; border-color: #dc2626; }


/* ==============================================================================
   MOBILE RESPONSIVE PASS (2026-07-29) — CSS ONLY, no logic/server changes,
   zero runtime cost on desktop (rules live behind max-width media queries).
   ============================================================================== */
@media (max-width: 768px) {
  /* Daily/Weekly/Monthly Sales Report matrix: the frozen METRIC/comparison/
     TREND columns total ~800px of sticky width — wider than a phone screen,
     so they covered the whole viewport and the detail block (and its
     sparklines) could never scroll into view. On phones, drop the frozen-
     pane behaviour entirely: the table scrolls as one normal unit. */
  .sr3-matrix td, .sr3-matrix th { position: static !important; }

  /* Sparkline popup chart: fixed 640x400 overflows a phone viewport. Fit the
     popup to the screen and let the chart (kept at its rendered size for
     crispness) pan inside it. */
  .sr3-spark-popup {
    width: 94vw !important;
    height: min(400px, 70vh) !important;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* KPI strips: cards go 2-up instead of 6 squeezed into one row. */
  .kpi-card { min-width: calc(50% - 10px); }

  /* Last Mile: metric segmented control wraps instead of clipping. */
  .lm-seg { flex-wrap: wrap; }
  .lm-seg-btn { flex: 1 1 auto; }
  .lm-tabs { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }

  /* Grid children default to min-width:auto, so a wide table inside a
     .two-col-grid card forces the grid TRACK wider than the phone screen —
     the overflow then belongs to the page, not to the card's .table-scroll,
     which is why the Country Performance table could not be swiped
     horizontally. min-width:0 lets the card shrink to the viewport so its
     own .table-scroll becomes the scroll container. */
  .two-col-grid > *, .three-col-grid > * { min-width: 0; }
  .table-scroll { overflow-x: auto; }
}

@media (max-width: 640px) {
  /* Ask Data assistant: desktop floating window (460x570 anchored bottom-
     right) becomes a native-feeling full-width bottom sheet. !important is
     required because the component carries inline styles. */
  #voc-modal {
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    top: auto !important;
    width: 100vw !important;
    height: 85vh !important;
    max-height: calc(100vh - 56px);
    border-radius: 16px 16px 0 0 !important;
    border-left: none !important;
    border-right: none !important;
    border-bottom: none !important;
  }
  #voc-open-btn {
    bottom: 14px !important;
    right: 14px !important;
    padding: 10px 16px !important;
  }

  /* Date pickers + filter rows on the report pages: full-width stacking. */
  .DateInput, .DateInput_input { max-width: 100%; }
  .filter-dropdown { min-width: 0 !important; }
}


/* ==============================================================================
   BUYER'S GUIDE (/buyers-guide) — 1:1 port of the approved
   Buyers_Guide_Dashboard.html styles (values verbatim; documented in
   design.md). All classes bg- prefixed and scoped under .bg-page so nothing
   collides with the app's own kpi-card/panel/tab classes.
   ============================================================================== */
.bg-page { font-size: 14px; }
.bg-layout { display: grid; grid-template-columns: 260px 1fr; gap: 0; align-items: start; }
.bg-side { background: #ffffff; border: 1px solid #e6eaf2; border-right: none;
  border-radius: 12px 0 0 12px; padding: 18px; position: sticky; top: 70px;
  max-height: calc(100vh - 90px); overflow-y: auto; }
.bg-side-h3 { font-size: 12px; text-transform: uppercase; letter-spacing: .8px;
  color: #6b7280; margin: 0 0 12px; font-weight: 700; }
.bg-filter-group { margin-bottom: 14px; }
.bg-filter-group label { display: block; font-size: 12px; font-weight: 600;
  color: #374151; margin-bottom: 4px; }
.bg-filter-actions { display: flex; gap: 8px; margin-top: 6px; }
.bg-btn-sm { padding: 7px 10px; font-size: 12px; border-radius: 7px; cursor: pointer;
  border: 1px solid #e6eaf2; background: #fff; color: #1f2937; font-weight: 600; flex: 1; }
.bg-btn-sm:hover { background: #f3f4f6; }
.bg-main { padding: 18px 20px; background: #f5f7fb; border: 1px solid #e6eaf2;
  border-radius: 0 12px 12px 0; min-width: 0; overflow-x: auto; }

.bg-tabs { display: flex; gap: 4px; border-bottom: 2px solid #e6eaf2; margin-bottom: 18px; }
.bg-tab { padding: 10px 18px; cursor: pointer; font-size: 14px; font-weight: 600;
  color: #6b7280; border-bottom: 3px solid transparent; margin-bottom: -2px;
  transition: all .15s; text-decoration: none; }
.bg-tab:hover { color: #1f2937; }
.bg-tab-active { color: #2563eb; border-bottom-color: #2563eb; }

.bg-breadcrumb { display: flex; align-items: center; gap: 6px; background: #eef2ff;
  padding: 8px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 13px; flex-wrap: wrap; }
.bg-crumb { color: #2563eb; font-weight: 600; cursor: pointer; text-decoration: none; }
a.bg-back-btn { text-decoration: none; color: inherit; display: inline-block; }
.bg-crumb:hover { text-decoration: underline; }
.bg-crumb-active { color: #1f2937; cursor: default; }
.bg-crumb-active:hover { text-decoration: none; }
.bg-sep { color: #9ca3af; }
.bg-back-btn { margin-left: auto; background: white; border: 1px solid #e6eaf2;
  padding: 4px 10px; border-radius: 6px; cursor: pointer; font-size: 12px;
  font-weight: 600; color: #1f2937; }
.bg-back-btn:hover { background: #f9fafb; }

.bg-kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 14px; margin-bottom: 18px; }
.bg-kpi-card { background: #ffffff; border: 1px solid #e6eaf2; border-radius: 12px;
  padding: 14px 16px; box-shadow: 0 1px 3px rgba(15,23,42,.06), 0 1px 2px rgba(15,23,42,.04);
  transition: all .15s; }
.bg-kpi-card:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(15,23,42,.08); }
.bg-kpi-label { font-size: 11px; text-transform: uppercase; color: #6b7280;
  font-weight: 600; letter-spacing: .5px; }
.bg-kpi-value { font-size: 22px; font-weight: 700; margin: 6px 0 4px; color: #1f2937; }
.bg-kpi-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.bg-kpi-growth { font-size: 12px; font-weight: 600; padding: 2px 8px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 3px; }
.bg-growth-up { background: #dcfce7; color: #16a34a; }
.bg-growth-down { background: #fee2e2; color: #dc2626; }
.bg-growth-flat { background: #fef3c7; color: #f59e0b; }
.bg-kpi-cmp { font-size: 11px; color: #6b7280; margin-top: 2px; }

.bg-row { display: grid; gap: 14px; margin-bottom: 14px; }
.bg-cols-2 { grid-template-columns: 1fr 1fr; }
.bg-cols-3 { grid-template-columns: 2fr 1fr; }
@media (max-width: 1100px) { .bg-cols-2, .bg-cols-3 { grid-template-columns: 1fr; } }
.bg-row > * { min-width: 0; }
.bg-panel { background: #ffffff; border: 1px solid #e6eaf2; border-radius: 12px;
  padding: 14px 16px; box-shadow: 0 1px 3px rgba(15,23,42,.06), 0 1px 2px rgba(15,23,42,.04);
  margin-bottom: 14px; }
.bg-panel-title { font-size: 14px; font-weight: 700; margin: 0 0 4px; color: #1f2937; }
.bg-panel-sub { font-size: 12px; color: #6b7280; margin-bottom: 10px; }
.bg-panel-controls { display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
  flex-wrap: wrap; }
.bg-panel-controls label { font-size: 12px; font-weight: 600; color: #6b7280; }
.bg-scale-badge { font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 999px;
  background: #eff6ff; color: #2563eb; }

.bg-insight { background: linear-gradient(90deg, #eff6ff 0%, #f5f3ff 100%);
  border-left: 3px solid #2563eb; padding: 8px 12px; border-radius: 6px;
  font-size: 12.5px; margin-top: 10px; color: #1e293b; }
.bg-insight b { color: #2563eb; }

.bg-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.bg-table thead th { text-align: left; font-weight: 600; color: #6b7280; font-size: 11px;
  text-transform: uppercase; letter-spacing: .5px; padding: 8px 10px;
  border-bottom: 1px solid #e6eaf2; background: #f9fafb; }
.bg-table tbody td { padding: 8px 10px; border-bottom: 1px solid #e6eaf2; }
.bg-table tbody tr:hover { background: #f9fafb; }
.bg-pill { padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600;
  display: inline-block; }
.bg-pill.g { background: #dcfce7; color: #16a34a; }
.bg-pill.r { background: #fee2e2; color: #dc2626; }
.bg-pill.a { background: #fef3c7; color: #f59e0b; }

.bg-gauge-wrap { display: flex; align-items: center; justify-content: center;
  flex-direction: column; height: 260px; }
.bg-gauge-value { font-size: 32px; font-weight: 700; margin-top: -70px; }
.bg-gauge-label { font-size: 12px; color: #6b7280; margin-top: 4px; }
.bg-loading { padding: 40px; text-align: center; color: #6b7280; }

.bg-country-pills { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
.bg-c-pill { padding: 5px 14px; border-radius: 999px; border: 1.5px solid #10b981;
  font-size: 12px; font-weight: 700; cursor: pointer; color: #10b981; background: #fff;
  transition: all .15s; }
.bg-c-pill-active { background: #10b981; color: white; }
.bg-c-pill:hover { transform: translateY(-1px); }

.bg-heatmap-wrap { overflow-x: auto; }
.bg-heatmap { width: 100%; border-collapse: separate; border-spacing: 2px;
  font-size: 12px; min-width: 1100px; }
.bg-heatmap th { background: transparent; color: #6b7280; font-size: 11px; font-weight: 700;
  padding: 6px 4px; text-align: center; border: none; }
.bg-heatmap th.bg-slab-h { text-align: left; padding-left: 8px; }
.bg-heatmap td { padding: 8px 4px; text-align: center; border-radius: 4px; font-weight: 500;
  border: none; font-variant-numeric: tabular-nums; }
.bg-heatmap td.bg-slab-c { text-align: left; font-weight: 700; color: #1f2937;
  background: transparent !important; padding-left: 8px; }
.bg-heatmap td.bg-delta { background: transparent !important; font-weight: 700;
  padding-left: 10px; }
.bg-heatmap td.bg-delta-up { color: #16a34a; }
.bg-heatmap td.bg-delta-dn { color: #dc2626; }
.bg-heatmap td.bg-delta-flat { color: #f59e0b; }
.bg-heatmap tr:hover td:not(.bg-slab-c):not(.bg-delta) { outline: 1.5px solid #059669; }

.bg-core-pill { padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 700;
  display: inline-block; margin-left: 6px; }
.bg-core-pill.core { background: #dcfce7; color: #16a34a; }
.bg-core-pill.non { background: #f3f4f6; color: #6b7280; }

@media (max-width: 900px) {
  .bg-layout { grid-template-columns: 1fr; }
  .bg-side { border-radius: 12px 12px 0 0; border-right: 1px solid #e6eaf2;
    border-bottom: none; position: static; max-height: none; }
  .bg-main { border-radius: 0 0 12px 12px; }
}


/* Buyer's Guide filter row (top, horizontal, wrapping) + full-width main —
   replaces the earlier left side-panel layout per business instruction. */
.bg-filter-row {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
  margin-bottom: 16px;
}
.bg-main-full { min-width: 0; }


/* ==============================================================
   TALL TABLES - capped height + sticky header (2026-08-19)
   Business feedback: long lists (Core Size sizes, Attribute values, hour x
   date grids) stretched the page over several screens. .table-scroll only
   ever handled HORIZONTAL overflow, so height was unbounded. .table-scroll-y
   caps the height and scrolls INSIDE the card, keeping the header visible
   while the body moves.
   ============================================================== */
.table-scroll-y {
  overflow: auto;
  max-height: 420px;
  /* Contain the sticky header: without a positioned ancestor the header can
     detach from the body while scrolling in Safari. */
  position: relative;
}
.table-scroll-y-sm { max-height: 300px; }
.table-scroll-y-lg { max-height: 560px; }

/* thead sticks to the top of the SCROLL CONTAINER, not the viewport. The
   background must be opaque or rows show through as they pass under it. */
.table-scroll-y thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: #f9fafb;
  /* inset box-shadow rather than border-bottom: a sticky cell's border does
     not repaint reliably while scrolling in Chrome. */
  box-shadow: inset 0 -1px 0 #e5e7eb;
}
/* A total row pinned to the BOTTOM stays readable on a long grid. */
.table-scroll-y tfoot td {
  position: sticky;
  bottom: 0;
  z-index: 2;
  background: #f9fafb;
  font-weight: 600;
  box-shadow: inset 0 1px 0 #e5e7eb;
}

/* Wide grids (hour x date): freeze the label column so a row stays
   identifiable after scrolling right. */
.table-sticky-first thead th:first-child,
.table-sticky-first tbody td:first-child,
.table-sticky-first tfoot td:first-child {
  position: sticky;
  left: 0;
  background: #fff;
  z-index: 1;
}
.table-sticky-first thead th:first-child { background: #f9fafb; z-index: 3; }
.table-sticky-first tfoot td:first-child { background: #f9fafb; z-index: 3; }

@media (max-width: 768px) {
  .table-scroll-y    { max-height: 320px; }
  .table-scroll-y-lg { max-height: 380px; }
}


/* ==============================================================
   FILTER ROWS MUST OUT-STACK THE TABLE BELOW THEM (2026-08-19 fix)
   The sticky table cells added for .table-scroll-y sit in a positioned
   container with z-index up to 3. A filter row appears BEFORE the table in the
   DOM, so at equal stacking level the table painted ON TOP of an open date
   calendar: the calendar was visible through the rows but every click landed on
   the table, making the date unselectable. Raising the filter row (and the
   react-dates popup itself) puts the calendar back in front.
   ============================================================== */
.bg-filter-row, .filter-row { position: relative; z-index: 30; }
/* While a picker inside the row is focused, lift that group further still so it
   also clears any sibling filter group to its right. */
.filter-group:focus-within { position: relative; z-index: 40; }
/* react-dates renders the calendar inline (no portal), so its own z-index has
   to beat the sticky cells as well. */
.SingleDatePicker_picker,
.DateRangePicker_picker,
.DayPicker_portal { z-index: 60 !important; }

/* ==============================================================
   Hourly grid: week-on-week cell tint (2026-08-21)
   Each sold-qty cell is compared with the SAME HOUR one week earlier, so a
   Tuesday 14:00 is judged against the previous Tuesday 14:00. A tint rather
   than coloured text: at 24 rows x 31 columns the reader is scanning for
   shape, and a background reads at a glance where a digit colour does not.
   Kept deliberately pale so the number stays the thing you read.
   ============================================================== */
.data-table td.hs-cell-up { background: rgba(22, 163, 74, 0.13); }
.data-table td.hs-cell-dn { background: rgba(220, 38, 38, 0.13); }
/* The TOTAL row is position:sticky at the bottom of the scroll container, so its
   background MUST be fully opaque — a translucent tint here let the data rows
   scroll visibly through the pinned row and the numbers overlapped (reported
   2026-08-21). These are the same two tints pre-composited over the sticky
   footer's own #f9fafb, so they look identical and hide what passes beneath.
   Never use rgba() on a sticky cell. */
.table-total-row td.hs-cell-up,
.table-scroll-y tfoot td.hs-cell-up { background: #c7e7d4; }
.table-total-row td.hs-cell-dn,
.table-scroll-y tfoot td.hs-cell-dn { background: #f3cbcc; }
.data-table td.hs-chg { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Legend swatches under the grid, so the tints are explained in place. */
.hs-legend-chip {
    display: inline-block;
    padding: 1px 7px;
    margin: 0 2px;
    border-radius: 3px;
    font-weight: 600;
}


/* ==============================================================
   KPI card carrying a marketplace figure (redesigned 2026-08-26)
   ==============================================================
   THE PROBLEM WITH THE PREVIOUS VERSION
   Two numbers sat side by side in a card whose min-width is 155px. To make
   them fit, the labels had been shrunk to 7.5px — below the point where they
   can be read — the values to 19px against the 28px of every single-value
   card in the same row, and both were given text-overflow: ellipsis, so a
   large figure was simply clipped. Each side could also stack four lines
   (label, value, delta, baseline), so cards in one row ended up different
   heights. `.kpi-pair` was additionally declared twice with conflicting
   align-items, in two separate places in this file.

   THE SHAPE NOW
   One DOMINANT figure at the same 28px as every other KPI card, so a row of
   cards reads as one set, with the marketplace figure on its own line below a
   hairline. One number per line means nothing is truncated, every pair card
   has the same height, and the labels are back to a readable size.
   ============================================================== */
.kpi-primary {
    display: flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
}
.kpi-primary .kpi-value { flex: 0 1 auto; min-width: 0; }
/* Names what the big number is, without spending a whole line on it. */
.kpi-qual {
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .4px;
    text-transform: uppercase;
    color: var(--text-3);
    white-space: nowrap;
    flex-shrink: 0;
}

/* The marketplace line: label, figure and its own change, on one row. */
.kpi-mkt-strip {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: 8px;
    padding-top: 7px;
    border-top: 1px solid var(--border);
}
.kpi-mkt-label {
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .5px;
    text-transform: uppercase;
    color: var(--text-3);
    white-space: nowrap;
}
.kpi-mkt-value {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-2);
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
    margin-left: auto;      /* figure and delta sit together on the right */
    white-space: nowrap;
}
.kpi-mkt-delta {
    font-size: 10.5px;
    font-weight: 800;
    white-space: nowrap;
    flex-shrink: 0;
}
.kpi-mkt-cmp {
    font-size: 9.5px;
    color: var(--text-3);
    white-space: nowrap;
    flex-shrink: 0;
}
/* Below this the cards are one per row anyway, so the strip has room. */
@media (max-width: 700px) {
    .kpi-mkt-strip { flex-wrap: wrap; gap: 4px 8px; }
    .kpi-mkt-value { margin-left: 0; }
}

/* ==============================================================
   Customers dept tile height (2026-08-24)
   Every other department tile IS the .dept-card, so the grid stretches it to
   the row height. The Customers tile is the one exception: it is wrapped in an
   id'd div so the Omni callback can swap the card without re-rendering the
   page. The grid therefore stretched the WRAPPER while the card inside kept its
   own content height, leaving that tile visibly short next to its neighbours.
   Making the wrapper a flex container hands the stretch through to the card.
   ============================================================== */
#cxo-customers-card {
    display: flex;
    min-width: 0;
}
#cxo-customers-card > .dept-card {
    flex: 1;
    min-width: 0;
}

/* ==============================================================
   Hourly Sales — drill-down popup (2026-08-24)
   The drill panel used to sit in the page flow showing three empty axes until
   an hour was clicked, which read as broken. It now opens over the page.

   It is NEVER display:none. Two reasons, both already paid for elsewhere in
   this file (see .sr3-spark-popup): a dcc.Graph measures its container once at
   mount, and a zero-size box locks the chart at zero width permanently; and
   hs_drill has eight Outputs, so the panel cannot be conditionally rendered.
   position:fixed keeps a real, measurable box out of the page flow, and
   visibility/opacity do the hiding.
   ============================================================== */
.hs-drill-popup {
    /* Full-viewport layer. The dim MUST live on this element, not on the card:
       the first version put the backdrop on a pseudo-element of the same box
       that carried overflow:auto, which CLIPPED the backdrop to the card's
       1180px and left the page behind undimmed (reported 2026-08-24). Scrolling
       now belongs to the inner card, so nothing clips the overlay. */
    position: fixed;
    inset: 0;
    z-index: 5000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3vh 2vw;
    /* Strong dim: the business asked for the page behind to stop competing with
       the drill-down, not merely to tint. */
    background: rgba(15, 23, 42, .72);
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity .12s;
}
.hs-drill-popup-open {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
}
.hs-drill-popup-inner {
    /* The scrolling box. Fixed width so the Plotly charts inside always have a
       real, measurable container even while the overlay is hidden — a zero-size
       box would lock them at zero width for good. */
    width: 1180px;
    max-width: 100%;
    max-height: 94vh;
    overflow: auto;
    position: relative;
}
.hs-drill-popup .hs-drill-card {
    position: relative;
    margin: 0;
    /* Fully opaque, so nothing of the page shows through the panel itself. */
    background: var(--surf-0, #fff);
    box-shadow: 0 24px 64px rgba(0, 0, 0, .45);
}
.hs-drill-close {
    position: absolute;
    top: 10px;
    right: 12px;
    z-index: 2;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-3);
    background: var(--card, #fff);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 4px 12px;
    cursor: pointer;
    transition: all .15s;
}
.hs-drill-close:hover { color: #dc2626; border-color: #dc2626; }

/* Tab strip reuses the Merchandise 360 look (.bg-tabs / .bg-tab), but those are
   anchors there and buttons here, so the button chrome has to be reset. */
.bg-tabs button.bg-tab {
    background: none;
    border: none;
    border-bottom: 3px solid transparent;
    font-family: inherit;
}
.bg-tabs button.bg-tab-active { border-bottom-color: #2563eb; }



/* ==============================================================================
   ASK DATA (2026-09-08)
   ==============================================================================
   The assistant as a page instead of a floating widget, per the business
   instruction. The layout is the one every chat tool converges on because it
   is the one that works: a thread rail you can go back through on the left, a
   scrolling transcript, and a composer pinned under it.

   Two things to know before editing:

   * The whole page is ONE fixed-height box and only .ad-thread scrolls. A chat
     that scrolls the page instead moves the composer off screen as the answer
     grows, which is the single worst thing this layout can do.
   * Tokens only. This page joins the app, so it wears --brand / --card /
     --border / --text-* like every other page rather than the widget's dark
     yellow-on-navy treatment, which only ever made sense as an overlay.
   ============================================================================== */
.ad-page { display: flex; height: calc(100vh - 190px); min-height: 440px; }

.ad-shell {
  display: flex; flex: 1; min-width: 0; overflow: hidden;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-sm);
}

/* ── Thread rail ────────────────────────────────────────────── */
.ad-rail {
  width: 248px; min-width: 248px; display: flex; flex-direction: column;
  background: var(--surf-2); border-right: 1px solid var(--border);
}
.ad-new-btn {
  margin: 12px 12px 8px; padding: 9px 12px;
  background: var(--brand); color: #fff; border: 1px solid var(--brand);
  border-radius: 10px; font-size: 12.5px; font-weight: 700;
  font-family: inherit; cursor: pointer; text-align: center;
  box-shadow: 0 1px 3px rgba(37,99,235,.28);
}
.ad-new-btn:hover { background: var(--brand-hov); }
.ad-rail-list { flex: 1; overflow-y: auto; padding: 0 8px 12px;
                scrollbar-width: thin; }
.ad-rail-heading {
  font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .6px; color: var(--text-3);
  padding: 12px 6px 5px; position: sticky; top: 0;
  background: var(--surf-2);
}
.ad-rail-empty { font-size: 12px; color: var(--text-2); line-height: 1.55;
                 padding: 10px 8px; }

/* The delete control is revealed on hover, and on keyboard focus — an
   opacity-only reveal is unreachable by tab otherwise. */
.ad-conv-row {
  display: flex; align-items: center; gap: 2px;
  border-radius: 8px; border-left: 3px solid transparent;
}
.ad-conv-row:hover { background: var(--surf-3); }
.ad-conv-row:hover .ad-del-btn,
.ad-conv-row .ad-del-btn:focus-visible { opacity: 1; }
.ad-conv-active { background: var(--nav-active-bg);
                  border-left-color: var(--brand); }
.ad-conv-active .ad-conv-btn { color: var(--nav-active-text);
                               font-weight: 650; }
.ad-conv-btn {
  flex: 1; min-width: 0; text-align: left; background: none; border: none;
  font-family: inherit; font-size: 12.5px; line-height: 1.45;
  color: var(--text-1); cursor: pointer; padding: 8px 4px 8px 7px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ad-del-btn {
  opacity: 0; background: none; border: none; cursor: pointer;
  color: var(--text-3); font-size: 15px; line-height: 1;
  padding: 4px 7px; border-radius: 6px; flex-shrink: 0;
  transition: opacity .12s ease, color .12s ease;
}
.ad-del-btn:hover { color: var(--red); background: var(--red-bg); }

/* ── Transcript ─────────────────────────────────────────────── */
.ad-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ad-thread {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 18px 22px 8px; display: flex; flex-direction: column; gap: 14px;
  scroll-behavior: smooth; scrollbar-width: thin;
}
.ad-turn { display: flex; }
.ad-turn-user { justify-content: flex-end; }
.ad-turn-bot { justify-content: flex-start; }

.ad-user-bubble {
  max-width: 76%; padding: 10px 14px; font-size: 14px; line-height: 1.55;
  background: var(--brand-lite); border: 1px solid var(--nav-active-border);
  color: var(--text-1); border-radius: 14px 14px 4px 14px;
  overflow-wrap: anywhere;
}
.ad-bot-bubble {
  max-width: 92%; padding: 12px 16px 10px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 14px 14px 14px 4px; box-shadow: var(--shadow-xs);
  overflow-wrap: anywhere;
}
.ad-who-row { display: flex; align-items: baseline; gap: 7px;
              margin-bottom: 6px; }
.ad-who { font-size: 10.5px; font-weight: 800; letter-spacing: .6px;
          text-transform: uppercase; color: var(--brand); }
.ad-who-sub { font-size: 10px; color: var(--text-3); }

/* Markdown, since the model answers in it: tables of figures are the whole
   point of the tool, so they get the house tabular treatment. */
.ad-md { font-size: 14px; line-height: 1.65; color: var(--text-1); }
.ad-md p { margin: 0 0 8px; }
.ad-md p:last-child { margin-bottom: 0; }
.ad-md ul, .ad-md ol { margin: 4px 0 8px; padding-left: 20px; }
.ad-md li { margin: 2px 0; }
.ad-md strong { font-weight: 700; }
.ad-md h1, .ad-md h2, .ad-md h3 {
  font-size: 13.5px; font-weight: 700; margin: 10px 0 5px;
  color: var(--text-1); font-family: 'Figtree', sans-serif;
}
.ad-md code { font-family: 'JetBrains Mono', monospace; font-size: 12.5px;
              background: var(--surf-3); padding: 1px 5px;
              border-radius: 4px; }
.ad-md table { border-collapse: collapse; margin: 8px 0; font-size: 13px;
               display: block; overflow-x: auto; max-width: 100%; }
.ad-md th, .ad-md td { padding: 6px 10px; text-align: right;
                       border-bottom: 1px solid var(--border);
                       white-space: nowrap;
                       font-family: 'JetBrains Mono', monospace;
                       font-variant-numeric: tabular-nums; }
.ad-md th:first-child, .ad-md td:first-child {
  text-align: left; font-family: 'DM Sans', sans-serif; }
.ad-md th { background: var(--surf-2); color: var(--text-2);
            font-size: 11.5px; font-weight: 700; text-transform: uppercase;
            letter-spacing: .4px; font-family: 'Figtree', sans-serif; }
.ad-chart { margin-top: 10px; padding-top: 8px;
            border-top: 1px solid var(--border); }

/* ── Chips: starters, and the model's own follow-ups ─────────── */
.ad-chip-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
               margin-top: 10px; }
.ad-chip-label { font-size: 10.5px; font-weight: 700; letter-spacing: .5px;
                 text-transform: uppercase; color: var(--text-3);
                 margin-right: 2px; }
.ad-chip {
  background: var(--card); border: 1px solid var(--border);
  border-radius: 999px; padding: 6px 13px; font-size: 12.5px;
  font-family: inherit; color: var(--text-1); cursor: pointer;
  text-align: left; line-height: 1.4;
}
.ad-chip:hover { border-color: var(--brand); color: var(--brand);
                 background: var(--brand-lite); }

/* ── Empty state ────────────────────────────────────────────── */
.ad-empty { margin: auto; max-width: 620px; text-align: center;
            padding: 20px 10px; }
.ad-empty-title { font-family: 'Figtree', sans-serif; font-size: 21px;
                  font-weight: 700; color: var(--text-1); margin-bottom: 7px; }
.ad-empty-sub { font-size: 13px; color: var(--text-2); line-height: 1.6;
                margin-bottom: 16px; }
.ad-empty .ad-chip-row { justify-content: center; }

/* ── Typing indicator ───────────────────────────────────────── */
.ad-typing { align-items: center; gap: 5px; padding: 2px 24px 6px; }
.ad-dot { width: 6px; height: 6px; border-radius: 50%;
          background: var(--brand); display: inline-block;
          animation: ad-bounce 1.3s infinite ease-in-out; }
.ad-dot:nth-child(2) { animation-delay: .18s; }
.ad-dot:nth-child(3) { animation-delay: .36s; }
.ad-typing-text { font-size: 11.5px; color: var(--text-2); margin-left: 6px; }
@keyframes ad-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: .45; }
  30%           { transform: translateY(-4px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .ad-dot { animation: none; opacity: .7; }
  .ad-thread { scroll-behavior: auto; }
}

/* ── Composer ───────────────────────────────────────────────── */
.ad-composer { padding: 8px 22px 12px; border-top: 1px solid var(--border);
               background: var(--card); }
.ad-composer-box {
  display: flex; align-items: flex-end; gap: 8px;
  border: 1px solid var(--border2); border-radius: 14px;
  padding: 7px 8px 7px 14px; background: var(--card);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.ad-composer-box:focus-within { border-color: var(--brand);
                                box-shadow: var(--shadow-focus); }
.ad-input {
  flex: 1; min-width: 0; border: none; outline: none; resize: none;
  background: transparent; font-family: inherit; font-size: 14px;
  line-height: 1.55; color: var(--text-1);
  min-height: 24px; max-height: 168px; padding: 4px 0; overflow-y: auto;
}
.ad-input::placeholder { color: var(--text-3); }
.ad-send {
  width: 34px; height: 34px; flex-shrink: 0; border-radius: 50%;
  background: var(--brand); color: #fff; border: none; cursor: pointer;
  font-size: 12px; display: flex; align-items: center;
  justify-content: center; box-shadow: 0 1px 3px rgba(37,99,235,.3);
}
.ad-send:hover { background: var(--brand-hov); }
.ad-composer-note { display: flex; justify-content: space-between; gap: 12px;
                    flex-wrap: wrap; font-size: 10.5px; color: var(--text-3);
                    padding: 6px 4px 0; }
.ad-composer-note-2 { text-align: right; }

/* ── Narrow screens ─────────────────────────────────────────── */
/* The rail becomes a strip above the transcript rather than disappearing:
   it is an Output of a callback, so it must stay in the DOM, and history is
   the reason this page exists. */
@media (max-width: 900px) {
  .ad-page { height: calc(100vh - 150px); }
  .ad-shell { flex-direction: column; }
  .ad-rail { width: auto; min-width: 0; max-height: 132px;
             border-right: none; border-bottom: 1px solid var(--border); }
  .ad-new-btn { margin: 8px 10px 4px; }
  .ad-user-bubble, .ad-bot-bubble { max-width: 100%; }
  .ad-thread { padding: 14px 14px 6px; }
  .ad-composer { padding: 8px 14px 10px; }
}

/* ==============================================================================
   AI INSIGHT — the impact card (redesigned 2026-09-08)
   ==============================================================================
   The business supplied a mock and asked for "something like this but
   shorter". The structural idea taken from it: the FIGURE leads and the
   sentence explains it, so a manager scanning eleven pages reads the number
   first and the prose only if it matters.

   What was NOT taken: the mock's normal-band sparklines. Drawing a band means
   computing one, the pages publish their facts as text rather than as a
   series, and a band the model made up would be the worst thing on the
   screen. Where a driver quotes a signed movement, that movement is pulled
   out as a pill instead — real deviation, visible before the words are read.
   ============================================================================== */
.ai-insight-body { display: flex; flex-direction: column; }

.ai-impact {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 14px 16px; border-radius: 12px;
  background: linear-gradient(135deg, #1e1b4b 0%, #312e81 100%);
  color: #fff; margin-bottom: 4px;
}
.ai-impact-fig {
  font-size: 34px; font-weight: 800; line-height: 1.05;
  letter-spacing: -.5px; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.ai-impact-said {
  flex: 1; min-width: 190px; font-size: 14px; font-weight: 600;
  line-height: 1.45; color: rgba(255,255,255,.93);
}

/* ==============================================================================
   WIDGET STACK — the space BETWEEN widgets
   ------------------------------------------------------------------------------
   Reported 2026-10-08 against Omni Customer 360 and Customer Life Cycle:
   "widget between space is not aligned properly".

   The cause is not those pages. `.section-card` sets background, border,
   radius, padding and shadow — and no vertical margin, in any of its three
   rules. Nothing else in this file spaces its siblings either: there is no
   `.section-card + .section-card`, no `> *` rule on a page container. So a
   page that stacks cards renders them flush, border touching border, and the
   only separation anywhere comes from whatever inline marginTop a page
   happened to add — which is why Omni alone had ten different marginTop
   values. The gaps were not inconsistent by accident; there was no rule to
   be consistent with.

   Adding the margin to `.section-card` itself would have been the one-line
   fix, but 21 pages use that class and only two have been reviewed, so the
   rhythm is OPT-IN: put `widget-stack` on the container that holds the
   cards. The remaining pages keep rendering exactly as they do today, and
   adopt it one at a time.

   flex + gap, not margins, for two reasons. Adjacent vertical margins
   collapse, so a card's bottom margin and the next element's top margin
   silently become one unpredictable value; a gap is the distance it says it
   is. And these stacks hold placeholders that stay empty until a callback
   fills them (`omni-insight`, the Life Cycle comparison row) — `:empty`
   below takes those out of the flow entirely, so no space is reserved for a
   widget that is not on screen. That empty-placeholder gap is a second,
   quieter half of the same complaint: a hole where nothing is drawn.
   ============================================================================== */
.widget-stack { display: flex; flex-direction: column; gap: 14px; }

/* Same distance side to side, so a two-up row inside the stack is not a
   different gap from the stack around it. */
.widget-row {
  display: flex; gap: 14px; flex-wrap: wrap; align-items: stretch;
}
.widget-row > * { min-width: 0; }

/* A child that brings its own trailing margin would ADD to the gap — the KPI
   row's 12px on top of 14px reads as a misaligned 26px. The stack owns the
   spacing between its own children; only DIRECT children are reset, so a
   .kpi-row nested inside a card keeps the margin that separates it from the
   rest of that card's contents. */
.widget-stack > .kpi-row,
.widget-stack > .panel-sub,
.widget-stack > .section-subtitle { margin-bottom: 0; }

/* Placeholders waiting on a callback, and sections a page chose not to
   render, occupy no space. */
.widget-stack > div:empty { display: none; }

.ai-sub { font-size: 11.5px; color: var(--text-3, #9ca3af);
          margin: 8px 0 2px; }

.ai-head {
  font-size: 10.5px; font-weight: 800; letter-spacing: .6px;
  text-transform: uppercase; color: var(--brand, #2563eb);
  margin: 14px 0 6px;
}
.ai-head-act { color: #047857; }

.ai-line {
  position: relative; padding-left: 19px; margin-bottom: 6px;
  font-size: 13.5px; line-height: 1.6; color: var(--text-1, #1f2937);
}
.ai-dot, .ai-tick {
  position: absolute; left: 0; top: 0; font-weight: 700;
}
.ai-dot  { color: var(--brand, #2563eb); }
.ai-tick { color: #047857; }

/* The signed movement out of a driver line. Status colour, and it always
   carries its own sign, so the colour is never the only cue. */
.ai-pill {
  display: inline-block; margin-left: 7px; padding: 1px 8px;
  border-radius: 999px; font-size: 11.5px; font-weight: 800;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  vertical-align: 1px;
}
.ai-pill-up { color: #b42318; background: #fee4e2; }
.ai-pill-dn { color: #027a48; background: #d1fadf; }

/* ── The same answer, inline in a drill-down ──────────────────── */
/* Business 2026-09-08: the hourly drill's insight renders here rather than in
   a modal, so the figures it describes stay visible underneath it. */
.ai-inline {
  margin: 10px 0 4px; padding: 12px 14px 10px;
  background: var(--card, #fff); border: 1px solid var(--border, #e6eaf2);
  border-left: 3px solid var(--brand-2, #7c3aed);
  border-radius: 10px; box-shadow: var(--shadow-xs);
}
.ai-inline-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  font-size: 11px; font-weight: 800; letter-spacing: .6px;
  text-transform: uppercase; color: var(--brand-2, #7c3aed);
}
.ai-inline .ai-impact { padding: 11px 13px; }
.ai-inline .ai-impact-fig { font-size: 27px; }
.ai-inline .ai-impact-said { font-size: 13px; min-width: 160px; }
.ai-inline-foot {
  margin-top: 10px; padding-top: 8px;
  border-top: 1px solid var(--border, #e6eaf2);
  font-size: 10.5px; color: var(--text-3, #9ca3af);
}

@media (max-width: 640px) {
  .ai-impact { gap: 8px; }
  .ai-impact-fig { font-size: 27px; }
}

/* ==============================================================================
   MERCHANDISING — the 2026-09-08 redesign
   ==============================================================================
   Panels built to the business's reference layout: a portfolio list with
   inline bars, a category x attribute grid, and a previous-vs-current mix
   shift. Tokens only, so both Merchandising pages still read as part of the
   app rather than as an import from the mock.
   ============================================================================== */

/* ── Portfolio / coverage list ────────────────────────────────── */
.mp-list { display: flex; flex-direction: column; gap: 2px; }
.mp-row {
  display: grid;
  grid-template-columns: minmax(88px, 1.25fr) minmax(60px, 3fr) auto 62px;
  align-items: center; gap: 10px;
  padding: 6px 2px; border-bottom: 1px solid var(--border, #e6eaf2);
}
.mp-row:last-of-type { border-bottom: none; }
.mp-row:hover { background: var(--surf-2, #f9fafb); }
.mp-name {
  font-size: 12.5px; font-weight: 650; color: var(--text-1, #1f2937);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mp-bar {
  height: 12px; border-radius: 3px; background: var(--surf-3, #f3f4f6);
  overflow: hidden; min-width: 40px;
}
.mp-bar-fill { height: 100%; border-radius: 3px; }
.mp-val {
  font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums;
  font-size: 12px; text-align: right; color: var(--text-1, #1f2937);
  white-space: nowrap;
}
.mp-share {
  font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums;
  font-size: 11.5px; text-align: right; color: var(--text-2, #6b7280);
  white-space: nowrap;
}

.mp-foot {
  display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px;
  padding-top: 10px; border-top: 1px solid var(--border, #e6eaf2);
}
.mp-foot-cell {
  flex: 1; min-width: 130px; background: var(--surf-2, #f9fafb);
  border: 1px solid var(--border, #e6eaf2); border-radius: 8px;
  padding: 7px 11px;
}
.mp-foot-lab {
  font-size: 9.5px; font-weight: 800; letter-spacing: .5px;
  text-transform: uppercase; color: var(--text-3, #9ca3af);
  margin-bottom: 2px;
}
.mp-foot-val {
  font-size: 14.5px; font-weight: 750; color: var(--text-1, #1f2937);
  font-variant-numeric: tabular-nums;
}
.mp-foot-mv { font-size: 11.5px; font-weight: 700; margin-left: 7px; }

/* ── Mix shift: two tracks per row, previous above current ────── */
.mp-row.ms-row {
  grid-template-columns: minmax(84px, 1.1fr) minmax(70px, 2.6fr)
                         46px 46px 62px;
}
.ms-pair { display: flex; flex-direction: column; gap: 3px; }
.ms-track {
  height: 8px; border-radius: 2px; background: var(--surf-3, #f3f4f6);
  overflow: hidden;
}
.ms-fill { height: 100%; border-radius: 2px; }
/* Previous period recedes — it is the reference, not the reading. */
.ms-prev { background: #c9c8c0; }

/* ── Category x attribute grid ────────────────────────────────── */
.mx-wrap { overflow-x: auto; }
.mx-table { border-collapse: separate; border-spacing: 0; width: 100%; }
.mx-table th {
  font-family: 'Figtree', sans-serif; font-size: 10.5px; font-weight: 800;
  letter-spacing: .4px; text-transform: uppercase;
  color: var(--text-2, #6b7280); text-align: center;
  padding: 7px 6px; border-bottom: 1px solid var(--border2, #d1d5db);
  white-space: nowrap;
}
.mx-table th.mx-corner { text-align: left; }
.mx-table th.mx-tot, .mx-table td.mx-tot { text-align: right; }
.mx-tr:hover td { background: var(--surf-2, #f9fafb); }
.mx-rowhead {
  padding: 7px 10px 7px 2px; border-bottom: 1px solid var(--border, #e6eaf2);
  white-space: nowrap;
}
.mx-rowname {
  font-size: 12.5px; font-weight: 650; color: var(--text-1, #1f2937);
}
.mx-rowsub { font-size: 10px; color: var(--text-3, #9ca3af); }
.mx-td {
  padding: 5px 6px; border-bottom: 1px solid var(--border, #e6eaf2);
  text-align: center; vertical-align: middle;
}
.mx-cell {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  cursor: help;
}
/* A 2px surface ring, so touching bubbles stay separate marks. */
.mx-bub { border-radius: 50%; box-shadow: 0 0 0 2px #fff; flex-shrink: 0; }
.mx-cellnum {
  font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums;
  font-size: 10.5px; color: var(--text-2, #6b7280); white-space: nowrap;
}
.mx-arrow { font-size: 9px; margin-left: 2px; font-weight: 700; }
.mx-empty {
  padding: 5px 6px; text-align: center; color: var(--text-3, #d1d5db);
  border-bottom: 1px solid var(--border, #e6eaf2); font-size: 12px;
}
.mx-table td.mx-tot {
  font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums;
  font-size: 11.5px; color: var(--text-2, #6b7280);
  padding: 5px 2px 5px 10px; white-space: nowrap;
  border-bottom: 1px solid var(--border, #e6eaf2);
}

@media (max-width: 780px) {
  .mp-row { grid-template-columns: minmax(70px, 1fr) minmax(40px, 2fr)
                                   auto 52px; gap: 7px; }
  .mp-row.ms-row { grid-template-columns: minmax(66px, 1fr)
                                          minmax(50px, 1.8fr) 40px 40px 54px; }
}

/* ── AI Insight: the modal's waiting state (2026-09-08) ─────────
   The modal now opens on the click and fills a beat later, so it needs
   something to show in between. Reported: "when we click AI insight it is not
   showing loader" — it never had one visible, because the modal only opened
   once the answer was already computed. */
.ai-thinking { display: flex; flex-direction: column; align-items: center;
               justify-content: center; gap: 14px; padding: 46px 20px; }
.ai-thinking-dots { display: flex; gap: 7px; }
.ai-thinking-text { font-size: 12.5px; color: var(--text-2, #6b7280); }
/* The app's own loader mark, reused so the wait looks like every other wait
   in the product rather than like a second loading style. */
.ai-thinking .bfl-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--brand, #2563eb); display: inline-block;
  animation: ai-thinking-bounce 1.3s infinite ease-in-out;
}
.ai-thinking .bfl-dot:nth-child(2) { animation-delay: .18s; }
.ai-thinking .bfl-dot:nth-child(3) { animation-delay: .36s; }
@keyframes ai-thinking-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: .4; }
  30%           { transform: translateY(-6px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .ai-thinking .bfl-dot { animation: none; opacity: .7; }
}

/* ── The comparison window, stated on every card (2026-09-08) ───
   Reported: "the comparison showing on which date?" The dates were only in
   filter_hint's tooltip, so a reader looking at "-16%" had to hover to learn
   what the 16% was against. A movement without its baseline is not a fact,
   so this one is always on screen — the hover rule covers FILTERS, and this
   is part of the reading. */
.ca-hint-row { display: flex; align-items: center; gap: 8px;
               flex-wrap: wrap; justify-content: flex-end; }
.cmp-chip {
  display: inline-flex; align-items: center; cursor: help;
  font-size: 11.5px; font-weight: 650; line-height: 1.4;
  white-space: nowrap; padding: 3px 10px; border-radius: 999px;
  color: var(--nav-active-text, #1e40af);
  background: var(--nav-active-bg, #eff6ff);
  border: 1px solid var(--nav-active-border, #bfdbfe);
}
/* A window nobody chose reads quieter than one they did. */
.cmp-chip-default {
  color: var(--text-2, #6b7280);
  background: var(--surf-2, #f9fafb);
  border-color: var(--border, #e6eaf2);
}
