/* ============================================================
   IES Hub v3 — Design System
   Canonical tokens, component classes, layout patterns
   ============================================================ */

/* ---- CSS Custom Properties (Design Tokens) ---- */
:root {
  /* Brand Colors */
  --ies-orange: #ff3a00;
  --ies-blue: #0047AB;
  --ies-navy: #1c1c1c;
  --ies-sidebar-dark: #1c1c1c;  /* 2026-04-29 (Brock): align with --ies-navy near-black; was navy #1a1f2e which clashed with GXO orange brand accent */

  /* Grays */
  --ies-gray-50: #f8f9fa;
  --ies-gray-100: #f1f3f5;
  --ies-gray-200: #e2e5e9;
  --ies-gray-300: #ced4da;
  --ies-gray-400: #adb5bd;
  --ies-gray-500: #6c757d;
  --ies-gray-600: #495057;
  --ies-gray-700: #343a40;
  --ies-gray-800: #212529;

  /* Status Colors */
  --ies-green: #28a745;
  --ies-red: #dc3545;
  --ies-yellow: #ffc107;
  --ies-teal: #20c997;

  /* Typography Scale (6 sizes only) */
  --fs-caption: 11px;
  --fs-body: 13px;
  --fs-subtitle: 14px;
  --fs-section: 16px;
  --fs-page: 20px;
  --fs-hero: 32px;

  /* Font Weights */
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-extrabold: 800;

  /* Border Radius (3 values only) */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-pill: 20px;

  /* Spacing Scale */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 40px;
  --sp-9: 48px;
  --sp-10: 64px;

  /* Shadows */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);

  /* Layout */
  --sidebar-width: 240px;
  --sidebar-collapsed: 60px;
  --topbar-height: 0px;
  --content-max-width: 1400px;
  --form-max-width: 1100px; /* 2026-04-29 layout pass — was 640px (legacy chrome era) */

  /* Transitions */
  --ease-default: 0.2s ease;
  --ease-slow: 0.35s ease;
}

/* ---- Reset & Base ---- */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: var(--fs-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: 'Montserrat', sans-serif;
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  color: var(--ies-navy);
  background: var(--ies-gray-50);
  line-height: 1.5;
  overflow: hidden;
  height: 100vh;
}

a { color: var(--ies-blue); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---- Typography ---- */
.text-caption {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.text-body { font-size: var(--fs-body); font-weight: var(--fw-medium); }
.text-subtitle { font-size: var(--fs-subtitle); font-weight: var(--fw-bold); }
.text-section { font-size: var(--fs-section); font-weight: var(--fw-bold); }
.text-page { font-size: var(--fs-page); font-weight: var(--fw-extrabold); }
.text-hero { font-size: var(--fs-hero); font-weight: var(--fw-extrabold); }

/* ---- Buttons (.hub-btn) ---- */
.hub-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 20px;
  font-family: 'Montserrat', sans-serif;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: all var(--ease-default);
  line-height: 1;
  white-space: nowrap;
}

.hub-btn:focus-visible {
  outline: 2px solid var(--ies-blue);
  outline-offset: 2px;
}

.hub-btn-primary {
  background: var(--ies-blue);
  color: #fff;
  border-color: var(--ies-blue);
}
.hub-btn-primary:hover { background: #003d94; }

.hub-btn-secondary {
  background: #fff;
  color: var(--ies-gray-600);
  border-color: var(--ies-gray-200);
}
.hub-btn-secondary:hover {
  border-color: var(--ies-blue);
  color: var(--ies-blue);
}

.hub-btn-success {
  background: #059669;
  color: #fff;
  border-color: #059669;
}
.hub-btn-success:hover { background: #047857; border-color: #047857; }

.hub-btn-danger {
  background: var(--ies-red);
  color: #fff;
  border-color: var(--ies-red);
}
.hub-btn-danger:hover { background: #c82333; }

.hub-btn-sm {
  padding: 8px 14px;
  font-size: var(--fs-caption);
}

.hub-btn-icon { gap: 6px; }

.hub-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* ---- Inputs ---- */
.hub-input,
.hub-select {
  height: 40px;
  padding: 10px 12px;
  font-family: 'Montserrat', sans-serif;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ies-navy);
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  transition: border-color var(--ease-default), box-shadow var(--ease-default);
  width: 100%;
}

.hub-input:focus,
.hub-select:focus {
  outline: none;
  border-color: var(--ies-blue);
  box-shadow: 0 0 0 3px rgba(0, 71, 171, 0.1);
}

.hub-input::placeholder { color: var(--ies-gray-400); font-weight: var(--fw-medium); }

textarea.hub-input {
  height: auto;
  min-height: 80px;
  resize: vertical;
}

/* ---- Cards ---- */
.hub-card {
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-md);
  padding: var(--sp-5);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--ease-default), box-shadow var(--ease-default), transform var(--ease-default);
}

.hub-card-interactive:hover {
  border-color: var(--ies-blue);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

/* ---- Tabs ---- */
.hub-tab-bar {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-2) 0;
}

.hub-tab {
  padding: 10px 20px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--ies-gray-200);
  font-family: 'Montserrat', sans-serif;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ies-gray-600);
  background: #fff;
  cursor: pointer;
  transition: all var(--ease-default);
  white-space: nowrap;
}

.hub-tab:hover {
  border-color: var(--ies-blue);
  color: var(--ies-blue);
}

.hub-tab.active {
  background: var(--ies-blue);
  color: #fff;
  border-color: var(--ies-blue);
}

/* ---- KPI Bar (dark gradient) ---- */
.hub-kpi-bar {
  display: flex;
  align-items: center;
  background: linear-gradient(135deg, #0a1628, #0d1f3c, #0a1628);
  border-radius: var(--radius-md);
  padding: var(--sp-4) var(--sp-3);
  gap: 0;
  overflow: hidden; /* no horizontal scroll — items flex-share the width */
  width: 100%;
  /* Container queries: children size themselves against the bar's actual
     inline width so wider viewports keep the hero-scale numbers and narrow
     viewports auto-shrink without clipping or ellipsis. */
  container-type: inline-size;
  container-name: hub-kpi-bar;
}

.hub-kpi-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1 1 0;
  min-width: 0;
  padding: 0 var(--sp-3);
  border-right: 1px solid rgba(255, 255, 255, 0.15);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hub-kpi-item:last-child { border-right: none; }

.hub-kpi-label {
  /* 9px floor → 11px ceiling, scaling at 1.1% of container width */
  font-size: clamp(9px, 1.1cqi, 11px);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: var(--sp-1);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hub-kpi-value {
  /* 13px floor so 7-tile bars stay legible on 1280 screens; scales to 22px at
     full width. cqi = 1% of the bar's inline size. */
  font-size: clamp(13px, 2.1cqi, 22px);
  font-weight: var(--fw-extrabold);
  color: #fff;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.15;
}

.hub-kpi-value.secondary { font-size: clamp(11px, 1.7cqi, 14px); }

/* Fallback for browsers without container-query support — media queries that
   approximate the scaling so text still fits at common sidebar-open widths. */
@supports not (container-type: inline-size) {
  .hub-kpi-value { font-size: var(--fs-page); }
  .hub-kpi-label { font-size: var(--fs-caption); }
  @media (max-width: 1400px) {
    .hub-kpi-value { font-size: 18px; }
  }
  @media (max-width: 1200px) {
    .hub-kpi-value { font-size: 16px; }
  }
  @media (max-width: 1000px) {
    .hub-kpi-value { font-size: 14px; }
    .hub-kpi-label { font-size: 10px; }
  }
}

/* ---- Badges / Pills ---- */
.hub-badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  border-radius: var(--radius-pill);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.hub-badge-blue { background: rgba(0, 71, 171, 0.1); color: var(--ies-blue); }
.hub-badge-green { background: rgba(40, 167, 69, 0.1); color: var(--ies-green); }
.hub-badge-red { background: rgba(220, 53, 69, 0.1); color: var(--ies-red); }
.hub-badge-orange { background: rgba(255, 58, 0, 0.1); color: var(--ies-orange); }
.hub-badge-gray { background: var(--ies-gray-100); color: var(--ies-gray-600); }

/* ---- Tables ---- */
.hub-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);
}

.hub-table th {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--ies-gray-500);
  text-align: left;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 2px solid var(--ies-gray-200);
}

.hub-table td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--ies-gray-100);
  color: var(--ies-navy);
  font-weight: var(--fw-semibold);
}

.hub-table tr:hover td { background: var(--ies-gray-50); }

/* ---- Layout: App Shell ---- */
.hub-app {
  display: flex;
  height: 100vh;
  overflow: hidden;
}

/* Sidebar */
.hub-sidebar {
  width: var(--sidebar-width);
  min-width: var(--sidebar-width);
  background: var(--ies-sidebar-dark);
  display: flex;
  flex-direction: column;
  transition: width var(--ease-slow), min-width var(--ease-slow);
  overflow: hidden;
  z-index: 100;
}

.hub-sidebar.collapsed {
  width: var(--sidebar-collapsed);
  min-width: var(--sidebar-collapsed);
}

.hub-sidebar-header {
  padding: var(--sp-5);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.hub-sidebar-logo {
  width: 32px;
  height: 32px;
  background: var(--ies-orange);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.hub-sidebar-title {
  font-size: var(--fs-subtitle);
  font-weight: var(--fw-bold);
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
}

.hub-sidebar.collapsed .hub-sidebar-title { display: none; }

/* Keep toggle button accessible when collapsed */
.hub-sidebar.collapsed .hub-sidebar-header {
  justify-content: center;
  padding: var(--sp-3);
}
.hub-sidebar.collapsed .hub-sidebar-logo { display: none; }
.hub-sidebar.collapsed .hub-sidebar-toggle {
  margin-left: 0 !important;
}

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

.hub-nav-group {
  padding: var(--sp-2) var(--sp-5);
}

.hub-nav-group-label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.4);
  padding: var(--sp-3) 0 var(--sp-2);
}

.hub-sidebar.collapsed .hub-nav-group-label { display: none; }

.hub-nav-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-sm);
  color: rgba(255, 255, 255, 0.65);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: all var(--ease-default);
  white-space: nowrap;
}

.hub-nav-item:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.hub-nav-item.active {
  background: var(--ies-orange);
  color: #fff;
}

.hub-nav-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hub-nav-icon svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.hub-nav-label { overflow: hidden; }
.hub-sidebar.collapsed .hub-nav-label { display: none; }

/* Main Content Area */
.hub-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--ies-gray-50);
}

.hub-content {
  flex: 1;
  overflow-y: auto;
  padding: var(--sp-6);
}

.hub-content-inner {
  max-width: var(--content-max-width);
  margin: 0 auto;
}

/* ---- Layout Pattern A: Builder ---- */
/* IMPORTANT: `min-height: 0` on the flex container AND its flex children
   is required so the children's intrinsic min-content height cannot push
   `.hub-builder` past its parent (`.hub-content`). Without this, tall
   sidebar/content forces `.hub-content` to scroll its OWN container —
   which then fights with `.hub-builder-content`'s sticky `.cm-header-kpis`
   (sticky binds to its nearest scrolling ancestor, the inner
   `.hub-builder-content`; when the OUTER `.hub-content` also scrolls,
   the sticky bar drifts up with it and content bleeds above/below the
   navy KPI tile). The explicit `max-height: 100%` is belt-and-braces:
   even if a future child sets a min-height, the builder still caps at
   parent. Symptom this fixed: 2026-04-27 morning — KPI bar drifting
   53px and the page-name title (e.g. "Equipment") peeking through. */
.hub-builder {
  display: flex;
  height: 100%;
  max-height: 100%;
  min-height: 0;
  gap: 0;
}

.hub-builder-sidebar {
  width: 220px;
  min-width: 220px;
  min-height: 0;
  background: #fff;
  border-right: 1px solid var(--ies-gray-200);
  overflow-y: auto;
  padding: var(--sp-4) 0;
}

.hub-builder-content {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--sp-6);
}

.hub-builder-form { max-width: var(--form-max-width); }

/* Sections that need the full available width opt out of the 640px cap.
   Triggers: any section containing a .hub-master-detail (Labor today),
   explicitly wrapped in .cm-wide-layout (Pricing Buckets), OR containing
   any wide data table (Equipment, Overhead, VAS, Start-Up, Timeline, the
   Multi-Year P&L / Sensitivity tables on Summary, the Monthly Labor View).
   Without this, `.hub-builder-form` caps the section at 640px and the
   1040px-min-width data tables force a horizontal scroll even when there's
   plenty of empty content area to the right. */
.hub-builder-form:has(.hub-master-detail),
.hub-builder-form:has(.cm-wide-layout),
.hub-builder-form:has(.cm-table-scroll),
.hub-builder-form:has(.cm-timeline-monthly-scroll),
.hub-builder-form:has(.cm-mlv-card),
.hub-builder-form:has(.cm-season-grid),
.hub-builder-form:has(.cm-fin-grid),
.hub-builder-form:has(.cm-summary-row),
.hub-builder-form:has(.cm-linked-grid),
.hub-builder-form:has(.cm-assumptions-grid) {
  max-width: var(--content-max-width);
}

/* ---- Layout Pattern B: Analyzer ---- */
.hub-analyzer {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.hub-analyzer-tabs { padding: var(--sp-4) var(--sp-6) 0; }

.hub-analyzer-content {
  flex: 1;
  overflow-y: auto;
  padding: var(--sp-6);
}

/* ---- Auth Screen ---- */
.hub-auth-overlay {
  position: fixed;
  inset: 0;
  background: linear-gradient(135deg, #0a1628 0%, #0d1f3c 50%, #0a1628 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.hub-auth-card {
  background: #fff;
  border-radius: var(--radius-md);
  padding: var(--sp-8);
  width: 380px;
  max-width: 90vw;
  box-shadow: var(--shadow-lg);
  text-align: center;
}

.hub-auth-logo {
  width: 56px;
  height: 56px;
  background: var(--ies-orange);
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto var(--sp-5);
}

.hub-auth-title {
  font-size: var(--fs-page);
  font-weight: var(--fw-extrabold);
  color: var(--ies-navy);
  margin-bottom: var(--sp-2);
}

.hub-auth-subtitle {
  font-size: var(--fs-body);
  color: var(--ies-gray-500);
  margin-bottom: var(--sp-6);
}

.hub-auth-input {
  width: 100%;
  margin-bottom: var(--sp-4);
}

.hub-auth-error {
  color: var(--ies-red);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  margin-bottom: var(--sp-3);
  display: none;
}

.hub-auth-error.visible { display: block; }

/* Slice 3.2 additions — label, pane switcher, secondary link. */
.hub-auth-label {
  display: block;
  text-align: left;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--ies-gray-600);
  margin-bottom: var(--sp-1);
}

.hub-auth-pane {
  text-align: left;
}

.hub-auth-pane .hub-auth-input {
  margin-bottom: 0; /* spacing is handled by the label margin-top */
  text-align: left;
}

.hub-auth-footer {
  text-align: center;
  font-size: var(--fs-caption);
}

.hub-auth-link {
  color: var(--ies-gray-500);
  font-weight: var(--fw-semibold);
  text-decoration: none;
  border-bottom: 1px dotted var(--ies-gray-300);
  padding-bottom: 1px;
}
.hub-auth-link:hover {
  color: var(--ies-navy);
  border-bottom-color: var(--ies-navy);
}

.hub-auth-pane.hidden { display: none; }

/* Header "sign out" affordance (Slice 3.2). */
.hub-user-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--ies-gray-200);
  background: #fff;
  border-radius: 8px;
  color: var(--ies-gray-700);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  max-width: 220px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hub-user-chip:hover {
  background: var(--ies-gray-50);
  color: var(--ies-navy);
}
.hub-user-chip svg { flex-shrink: 0; }
.hub-user-chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Global Search ---- */
.hub-search-container {
  position: relative;
  margin: 0 var(--sp-5);
  padding: var(--sp-3) 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.hub-search-input {
  width: 100%;
  height: 36px;
  padding: 8px 12px 8px 32px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--radius-sm);
  color: #fff;
  font-family: 'Montserrat', sans-serif;
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  transition: all var(--ease-default);
}

.hub-search-input:focus {
  outline: none;
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--ies-blue);
}

.hub-search-input::placeholder {
  color: rgba(255, 255, 255, 0.4);
}

.hub-search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: rgba(255, 255, 255, 0.4);
}

.hub-search-dropdown {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  max-height: 320px;
  overflow-y: auto;
  z-index: 200;
  display: none;
}

.hub-search-dropdown.visible { display: block; }

.hub-search-result {
  padding: var(--sp-3) var(--sp-4);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  transition: background var(--ease-default);
}

.hub-search-result:hover,
.hub-search-result.focused {
  background: var(--ies-gray-50);
}

.hub-search-result-title {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--ies-navy);
}

.hub-search-result-section {
  font-size: var(--fs-caption);
  color: var(--ies-gray-500);
}

/* ---- Utility Classes ---- */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); }
.gap-4 { gap: var(--sp-4); }
.gap-5 { gap: var(--sp-5); }
.gap-6 { gap: var(--sp-6); }
.w-full { width: 100%; }
.text-center { text-align: center; }
.text-right { text-align: right; }
.text-muted { color: var(--ies-gray-500); }
.text-blue { color: var(--ies-blue); }
.text-green { color: var(--ies-green); }
.text-red { color: var(--ies-red); }
.text-orange { color: var(--ies-orange); }
.mt-2 { margin-top: var(--sp-2); }
.mt-4 { margin-top: var(--sp-4); }
.mt-6 { margin-top: var(--sp-6); }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-4 { margin-bottom: var(--sp-4); }
.mb-6 { margin-bottom: var(--sp-6); }
.hidden { display: none !important; }

/* ============================================================
   TIER 2 — Unified Tool Frame
   Shared shell primitives used across every Design Tool so that
   tool headers, action rails, tab strips, primary actions, and
   input groups render consistently. Domain inputs + visualization
   centers remain tool-specific.
   ============================================================ */

/* Navy page banner — generalized from the Cost Model "page-name lifted into
   navy bar" pattern (commits 384b2a7 + 57aae71 + AM6, 2026-04-27 morning).
   Tools opt-in by passing { description, subtitle } to renderToolHeader.
   When present, this banner replaces the inline `.hub-tool-title` so the
   page name only reads once. Status chips + tab strip + run button still
   render in the strip below the banner. */
.hub-page-banner {
  background: linear-gradient(135deg, #0a1628 0%, #0d1f3c 100%);
  color: #fff;
  padding: 14px 24px;
  margin: 12px 24px 0;
  border-radius: var(--radius-md);
  box-shadow: 0 6px 16px rgba(10, 22, 40, 0.18);
}
.hub-page-banner__title {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-family: Montserrat, sans-serif;
  margin: 0;
}
.hub-page-banner__name {
  font-size: 18px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.1px;
  line-height: 1.2;
}
.hub-page-banner__pill {
  display: inline-block;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.22);
  white-space: nowrap;
}
.hub-page-banner__desc {
  font-size: 12px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.72);
  margin: 6px 0 0;
  line-height: 1.4;
  max-width: 900px;
  white-space: normal;
}
.hub-page-banner__desc strong,
.hub-page-banner__desc code {
  color: #fff;
  font-weight: 600;
}
.hub-page-banner__desc a {
  color: #fff;
  text-decoration: underline;
  text-decoration-color: rgba(255,255,255,0.4);
}
.hub-page-banner__desc a:hover { text-decoration-color: #fff; }
/* When a tool's content is already padded (most are wrapped in
   .hub-content-inner with default padding), the banner sits at the same
   horizontal inset as the tab strip below. Tools that opt out of
   .hub-content-inner padding (analyzer-pattern: padding:0 + flex column)
   need the banner to honor the 24px gutter the tool-header uses. */
.hub-content-inner > .hub-page-banner:first-child { margin-top: 12px; }

/* Header strip: Back link + tool title + status chips + tabs + primary action */
.hub-tool-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 24px 0 24px;
  flex-shrink: 0;
  flex-wrap: wrap;
}
.hub-tool-header .hub-tool-title {
  font-family: Montserrat, sans-serif;
  font-size: var(--fs-page);
  font-weight: var(--fw-extrabold);
  color: var(--ies-navy);
  margin: 0;
  letter-spacing: -0.01em;
}
.hub-tool-header .hub-tool-back {
  font-size: 11px;
  font-weight: var(--fw-semibold);
}

/* Status chip cluster (Linked to CM #7, Saved 2m ago, Draft, etc.) */
.hub-tool-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.hub-status-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  background: var(--ies-gray-100);
  color: var(--ies-gray-600);
  border: 1px solid var(--ies-gray-200);
  white-space: nowrap;
  line-height: 1.4;
}
.hub-status-chip.linked { background: #eff6ff; color: #1d4ed8; border-color: #bfdbfe; }
.hub-status-chip.standalone { background: var(--ies-gray-50); color: var(--ies-gray-500); border-color: var(--ies-gray-200); }
.hub-status-chip.saved { background: #f0fdf4; color: #166534; border-color: #bbf7d0; }
.hub-status-chip.draft { background: #fffbeb; color: #92400e; border-color: #fde68a; }
.hub-status-chip.modified { background: #fef3c7; color: #92400e; border-color: #fcd34d; }
.hub-status-chip.dot::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

/* Tab strip — shared tab-bar alternative used inside tool headers */
.hub-tab-strip {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.hub-tab-strip .hub-tab-btn {
  padding: 6px 14px;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  background: #fff;
  font-family: Montserrat, sans-serif;
  font-size: 13px;
  font-weight: var(--fw-semibold);
  color: var(--ies-gray-600);
  cursor: pointer;
  transition: all var(--ease-default);
  line-height: 1.2;
}
.hub-tab-strip .hub-tab-btn:hover {
  border-color: var(--ies-blue);
  color: var(--ies-blue);
}
.hub-tab-strip .hub-tab-btn.active {
  background: var(--ies-blue);
  color: #fff;
  border-color: var(--ies-blue);
}
.hub-tab-strip .hub-tab-btn:focus-visible {
  outline: 2px solid var(--ies-blue);
  outline-offset: 2px;
}

/* Action rail — the right-aligned bucket of action buttons on a tool header */
.hub-action-rail {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  flex-wrap: wrap;
  row-gap: 6px;
}

/* Primary Run button — orange, owns the Cmd/Ctrl+Enter shortcut */
.hub-run-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 16px;
  background: var(--ies-orange);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  font-family: Montserrat, sans-serif;
  font-size: 13px;
  font-weight: var(--fw-bold);
  cursor: pointer;
  line-height: 1.2;
  transition: background var(--ease-default), transform var(--ease-default);
  box-shadow: 0 1px 2px rgba(255, 58, 0, 0.18);
}
.hub-run-btn:hover { background: #e63300; }
.hub-run-btn:active { transform: translateY(1px); }
.hub-run-btn:focus-visible { outline: 2px solid var(--ies-orange); outline-offset: 2px; }
.hub-run-btn[disabled] { opacity: 0.55; cursor: not-allowed; }
.hub-run-btn .hub-run-icon {
  width: 12px;
  height: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  flex-shrink: 0;
}
.hub-run-btn .hub-run-shortcut {
  font-size: 10px;
  font-weight: var(--fw-bold);
  opacity: 0.7;
  padding: 1px 5px;
  border-radius: 3px;
  background: rgba(255,255,255,0.18);
  margin-left: 4px;
}
/* Flash-success animation when a run completes */
.hub-run-btn.ran { animation: hub-run-flash 0.6s ease; }
@keyframes hub-run-flash {
  0%   { box-shadow: 0 0 0 0 rgba(34,197,94,0.6); }
  50%  { box-shadow: 0 0 0 6px rgba(34,197,94,0); }
  100% { box-shadow: 0 1px 2px rgba(255,58,0,0.18); }
}

/* Run-state: clean (results match current inputs). Soft-filled green variant —
   obviously clickable (not disabled), but visually distinct from the orange
   dirty state so the user knows no recompute is needed. Hover lifts and
   brightens to reinforce "this is a button, click to re-run." */
.hub-run-btn.is-clean {
  background: #dcfce7;
  color: #166534;
  border: 1px solid #86efac;
  box-shadow: 0 1px 2px rgba(22, 163, 74, 0.10);
}
.hub-run-btn.is-clean:hover {
  background: #bbf7d0;
  border-color: #4ade80;
  box-shadow: 0 2px 4px rgba(22, 163, 74, 0.18);
}
.hub-run-btn.is-clean:active {
  transform: translateY(1px);
}
.hub-run-btn.is-clean .hub-run-shortcut {
  background: rgba(22, 163, 74, 0.18);
  color: #15803d;
  opacity: 0.85;
}
.hub-run-btn.is-clean:focus-visible {
  outline-color: #16a34a;
}

/* Input Groups — consistent label/input/help stack used across all tools */
.hub-input-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.hub-input-group > label,
.hub-input-group .hub-input-label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  color: var(--ies-gray-600);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.hub-input-group > .hub-input-help {
  font-size: 11px;
  color: var(--ies-gray-400);
  font-weight: var(--fw-medium);
  line-height: 1.4;
}
.hub-input-group > .hub-input-error {
  font-size: 11px;
  color: var(--ies-red);
  font-weight: var(--fw-semibold);
  line-height: 1.4;
}
.hub-input-group input.hub-input,
.hub-input-group select.hub-input,
.hub-input-group textarea.hub-input,
.hub-input-group > input[type="text"]:not(.hub-input),
.hub-input-group > input[type="number"]:not(.hub-input),
.hub-input-group > input[type="email"]:not(.hub-input),
.hub-input-group > select:not(.hub-input),
.hub-input-group > textarea:not(.hub-input) {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  font-family: Montserrat, sans-serif;
  font-size: 13px;
  font-weight: var(--fw-semibold);
  color: var(--ies-gray-800);
  background: #fff;
  transition: border-color var(--ease-default), box-shadow var(--ease-default);
}
.hub-input-group > input:not([type="checkbox"]):not([type="radio"]):focus,
.hub-input-group > select:focus,
.hub-input-group > textarea:focus,
.hub-input-group input.hub-input:focus,
.hub-input-group select.hub-input:focus,
.hub-input-group textarea.hub-input:focus {
  outline: none;
  border-color: var(--ies-blue);
  box-shadow: 0 0 0 3px rgba(0,71,171,0.12);
}

/* Input Row — horizontal grid of input groups */
.hub-input-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}
.hub-input-row.cols-2 { grid-template-columns: repeat(2, 1fr); }
.hub-input-row.cols-3 { grid-template-columns: repeat(3, 1fr); }
.hub-input-row.cols-4 { grid-template-columns: repeat(4, 1fr); }

/* Results shelf — collapsible/solid KPI strip below canvas */
.hub-results-shelf {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 18px;
  border-top: 1px solid var(--ies-gray-200);
  background: var(--ies-gray-50);
  flex-shrink: 0;
}
.hub-results-shelf .hub-results-header {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  color: var(--ies-gray-600);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.hub-results-shelf .hub-results-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
}
.hub-results-shelf .hub-results-kpi {
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.hub-results-shelf .hub-results-kpi .kpi-label {
  font-size: 10px;
  font-weight: var(--fw-bold);
  color: var(--ies-gray-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.hub-results-shelf .hub-results-kpi .kpi-value {
  font-size: 18px;
  font-weight: var(--fw-extrabold);
  color: var(--ies-navy);
  line-height: 1.2;
}

/* Map toolbar — standardized control strip for Leaflet maps */
.hub-map-toolbar {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: rgba(255,255,255,0.95);
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  font-size: 12px;
  font-weight: var(--fw-semibold);
  color: var(--ies-gray-700);
}
.hub-map-toolbar .hub-map-chip {
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: var(--ies-gray-100);
  color: var(--ies-gray-600);
  cursor: pointer;
  border: 1px solid transparent;
  font-weight: var(--fw-bold);
  line-height: 1.3;
}
.hub-map-toolbar .hub-map-chip:hover { background: var(--ies-gray-200); }
.hub-map-toolbar .hub-map-chip.active {
  background: var(--ies-blue);
  color: #fff;
}

/* Training Wiki — article body normalization */
.hub-wiki-article {
  font-size: 13px;
  line-height: 1.7;
  color: var(--ies-gray-800);
  font-family: Montserrat, sans-serif;
}
.hub-wiki-article p {
  margin: 0 0 14px 0;
  line-height: 1.7;
}
.hub-wiki-article p:last-child { margin-bottom: 0; }
.hub-wiki-article h1,
.hub-wiki-article h2,
.hub-wiki-article h3,
.hub-wiki-article h4 {
  font-weight: var(--fw-extrabold);
  color: var(--ies-navy);
  margin: 24px 0 10px 0;
  line-height: 1.3;
}
.hub-wiki-article h1 { font-size: 22px; }
.hub-wiki-article h2 { font-size: 18px; }
.hub-wiki-article h3 { font-size: 15px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ies-gray-700); }
.hub-wiki-article h4 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ies-gray-600); }
.hub-wiki-article h1:first-child,
.hub-wiki-article h2:first-child,
.hub-wiki-article h3:first-child { margin-top: 0; }
.hub-wiki-article ul,
.hub-wiki-article ol {
  margin: 0 0 14px 0;
  padding-left: 22px;
}
.hub-wiki-article li { margin-bottom: 4px; line-height: 1.6; }
.hub-wiki-article li p { margin: 0 0 6px 0; }
.hub-wiki-article strong, .hub-wiki-article b { font-weight: var(--fw-extrabold); color: var(--ies-navy); }
.hub-wiki-article em, .hub-wiki-article i { font-style: italic; color: var(--ies-gray-700); }
.hub-wiki-article code {
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: 12px;
  background: var(--ies-gray-100);
  padding: 1px 5px;
  border-radius: 3px;
  color: var(--ies-gray-800);
}
.hub-wiki-article pre {
  background: var(--ies-gray-800);
  color: #e8eaed;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  overflow-x: auto;
  margin: 0 0 14px 0;
  font-size: 12px;
  line-height: 1.5;
}
.hub-wiki-article pre code { background: transparent; color: inherit; padding: 0; }
.hub-wiki-article blockquote {
  margin: 0 0 14px 0;
  padding: 8px 14px;
  border-left: 3px solid var(--ies-blue);
  background: #f0f5ff;
  color: var(--ies-gray-700);
  font-style: italic;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.hub-wiki-article table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 16px 0;
  font-size: 12px;
}
.hub-wiki-article th {
  text-align: left;
  padding: 8px 10px;
  background: var(--ies-gray-100);
  color: var(--ies-gray-700);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: 11px;
  border-bottom: 2px solid var(--ies-gray-200);
}
.hub-wiki-article td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--ies-gray-100);
  vertical-align: top;
}
.hub-wiki-article tr:last-child td { border-bottom: none; }
.hub-wiki-article hr {
  border: none;
  border-top: 1px solid var(--ies-gray-200);
  margin: 20px 0;
}
.hub-wiki-article a {
  color: var(--ies-blue);
  text-decoration: none;
  border-bottom: 1px dotted var(--ies-blue);
}
.hub-wiki-article a:hover { border-bottom-style: solid; }

/* v2-ported article helper classes — render consistently in v3 light theme */
.hub-wiki-article .wiki-breadcrumb {
  font-size: 11px;
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ies-gray-500);
  margin-bottom: 16px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--ies-gray-200);
}
.hub-wiki-article .wiki-spec-table {
  width: 100%;
  border-collapse: collapse;
  margin: 12px 0 18px 0;
  font-size: 12px;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.hub-wiki-article .wiki-spec-table th {
  background: var(--ies-gray-100);
  color: var(--ies-gray-700);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 11px;
  text-align: left;
  padding: 8px 12px;
  border-bottom: 2px solid var(--ies-gray-200);
}
.hub-wiki-article .wiki-spec-table td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--ies-gray-100);
  vertical-align: top;
  color: var(--ies-gray-800);
  line-height: 1.5;
}
.hub-wiki-article .wiki-spec-table tr:last-child td { border-bottom: none; }
.hub-wiki-article .wiki-spec-table tr:nth-child(even) td { background: var(--ies-gray-50); }
.hub-wiki-article .wiki-callout {
  margin: 14px 0;
  padding: 12px 16px;
  background: #f0f5ff;
  border-left: 3px solid var(--ies-blue);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.hub-wiki-article .wiki-callout p { margin: 0; line-height: 1.6; color: var(--ies-gray-700); }
.hub-wiki-article .wiki-callout-title {
  font-weight: var(--fw-extrabold);
  color: var(--ies-blue);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 6px;
}
/* Inline-styled feature card grids (porting from v2 dark theme) — neutralize */
.hub-wiki-article .wiki-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
  margin: 14px 0;
}
.hub-wiki-article .wiki-card {
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-left: 3px solid var(--ies-blue);
  border-radius: var(--radius-sm);
  padding: 14px;
  box-shadow: var(--shadow-sm);
}
.hub-wiki-article .wiki-card-title {
  font-size: 13px;
  font-weight: var(--fw-extrabold);
  color: var(--ies-navy);
  margin-bottom: 6px;
}
.hub-wiki-article .wiki-card-body {
  font-size: 12px;
  color: var(--ies-gray-600);
  line-height: 1.55;
}
.hub-wiki-article .wiki-video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 8px;
  margin: 12px 0;
}
.hub-wiki-article .wiki-video-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--ies-gray-50);
  color: var(--ies-gray-800);
  text-decoration: none;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: var(--fw-semibold);
}
.hub-wiki-article .wiki-video-link:hover {
  border-color: var(--ies-blue);
  color: var(--ies-blue);
}
.hub-wiki-article .wiki-video-link::before {
  content: '▶';
  color: var(--ies-red);
  font-size: 14px;
  flex-shrink: 0;
}
.hub-wiki-article .wiki-roi {
  background: var(--ies-gray-50);
  border: 1px solid var(--ies-gray-200);
  border-left: 3px solid var(--ies-teal);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.7;
  margin: 14px 0;
  color: var(--ies-gray-800);
}
.hub-wiki-article .wiki-roi strong { color: var(--ies-navy); }

/* ---- Scrollbar Styling ---- */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--ies-gray-300); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--ies-gray-400); }

/* ---- Responsive ---- */
@media (max-width: 768px) {
  .hub-sidebar {
    position: fixed;
    left: -240px;
    height: 100vh;
    transition: left var(--ease-slow);
  }
  .hub-sidebar.mobile-open { left: 0; }
  .hub-builder-sidebar { display: none; }
}

/* ============================================================
 * DESIGN PRIMITIVES KIT (Cost Model v2 UI redesign, 2026-04-19)
 *
 * Consolidated primitives so new sections stop inventing their own
 * inline font sizes, widths, and spacings. Any new UI that touches
 * the Cost Model tool (and eventually every other tool) should use
 * these classes instead of inline styles.
 * ============================================================ */

/* ---- Field groups (label + input + hint) ---- */
.hub-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.hub-field--row {
  flex-direction: row;
  align-items: center;
  gap: 12px;
}
.hub-field--compact { gap: 2px; }
.hub-field__label {
  font-size: 11px;
  font-weight: 600;
  color: var(--ies-gray-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.25;
}
.hub-field__hint {
  font-size: 11px;
  color: var(--ies-gray-400);
  line-height: 1.3;
}
.hub-field__error {
  font-size: 11px;
  color: #dc2626;
  font-weight: 600;
  line-height: 1.3;
}

/* ---- Numeric affordance (tabular nums + right align) ---- */
.hub-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* ---- Standardized data table ---- */
.hub-datatable {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
  font-family: inherit;
}
.hub-datatable thead th {
  padding: 10px 12px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ies-gray-500);
  border-bottom: 1px solid var(--ies-gray-200);
  text-align: left;
  background: var(--ies-gray-50);
  white-space: nowrap;
}
.hub-datatable thead th.hub-num { text-align: right; }
.hub-datatable tbody td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--ies-gray-100);
  vertical-align: middle;
  color: var(--ies-gray-800);
}
.hub-datatable tbody tr:last-child td { border-bottom: 0; }
.hub-datatable tbody tr:hover { background: var(--ies-gray-50); }
.hub-datatable tbody tr.is-selected,
.hub-datatable tbody tr[data-selected="true"] {
  background: #eff6ff;
}
.hub-datatable tbody tr.is-selected:hover,
.hub-datatable tbody tr[data-selected="true"]:hover {
  background: #dbeafe;
}
.hub-datatable--dense tbody td { padding: 6px 10px; }
.hub-datatable--dense thead th { padding: 8px 10px; }
.hub-datatable .hub-input {
  padding: 6px 8px;
  height: 32px;
  font-size: 13px;
  width: 100%;
  box-sizing: border-box;
}

/* ---- Master-detail layout (used in Labor + future dense sections) ---- */
/* Container queries let child grids adapt to the PANE width, not viewport
   width — critical when an outer chrome (Cowork sidebar, dev-tools, etc.)
   eats into the viewport. */
.hub-master-detail {
  display: grid;
  grid-template-columns: minmax(300px, 360px) minmax(0, 1fr);
  gap: 16px;
  /* align-items: stretch (default) → master pane grows to match detail
     pane height instead of stopping at its natural content height. Paired
     with .hub-master-detail__master { height: 100% } + max-height cap +
     internal overflow-y: auto on __master-body so long lists still scroll. */
  align-items: stretch;
  container-type: inline-size;
  container-name: master-detail;
}
/* Only collapse to single-column on genuinely small screens. No max-width
   cap — let the detail pane use whatever horizontal room it has. */
@media (max-width: 820px) {
  .hub-master-detail { grid-template-columns: 1fr; }
  /* When collapsed, don't force equal height — master naturally shrinks. */
  .hub-master-detail__master { height: auto; }
}
.hub-master-detail__master {
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-md);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* height: 100% fills the grid row that align-items: stretch makes equal
     to the tallest sibling (typically the detail pane). No max-height on
     the outer element here — max-height would win against stretch, which
     was capping master at 483px while detail was 733px (250px gap). The
     __master-body does the overflow scrolling for long item lists. */
  height: 100%;
}
.hub-master-detail__master-header {
  padding: 12px 14px;
  border-bottom: 1px solid var(--ies-gray-100);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ies-gray-700);
  background: var(--ies-gray-50);
  flex-shrink: 0;
}
.hub-master-detail__master-body {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  /* Belt-and-braces safety cap: if a list has hundreds of items, stop it
     from pushing the page height to absurd levels. At typical (5-25 item)
     sizes the grid-row height is the bound; this rarely kicks in. */
  max-height: calc(100vh - 180px);
}
.hub-master-detail__item {
  padding: 12px 14px;
  border-bottom: 1px solid var(--ies-gray-100);
  cursor: pointer;
  transition: background var(--ease-default);
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: relative;
}
.hub-master-detail__item:hover { background: var(--ies-gray-50); }
.hub-master-detail__item.is-selected {
  background: #eff6ff;
  box-shadow: inset 3px 0 0 var(--ies-blue);
}
.hub-master-detail__item.is-selected:hover { background: #dbeafe; }
.hub-master-detail__item-primary {
  font-size: 13px;
  font-weight: 600;
  color: var(--ies-gray-800);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.hub-master-detail__item-secondary {
  font-size: 11px;
  color: var(--ies-gray-500);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.hub-master-detail__item-value {
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ies-gray-700);
}
.hub-master-detail__detail {
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-md);
  padding: 20px 22px;
}
.hub-master-detail__detail-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 12px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--ies-gray-100);
}
.hub-master-detail__detail-title {
  font-size: 16px;
  font-weight: 700;
  color: var(--ies-gray-900);
  margin: 0;
}
.hub-master-detail__empty {
  padding: 60px 24px;
  text-align: center;
  color: var(--ies-gray-400);
  font-size: 13px;
  line-height: 1.6;
}

/* ---- Field group sections inside a detail pane ---- */
.hub-detail-group {
  margin-bottom: 20px;
}
.hub-detail-group:last-child { margin-bottom: 0; }
.hub-detail-group__title {
  font-size: 11px;
  font-weight: 700;
  color: var(--ies-gray-500);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 10px 0;
}
/* Grid variants — explicit column counts, collapse via container query
   based on the PANE width (not viewport). 2-col stays 2-col until the
   pane is actually narrow; 4-col stays 4-col until there's no room. */
.hub-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px 18px;
}
.hub-detail-grid--2col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 18px;
}
.hub-detail-grid--4col {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px 18px;
}
/* Container-query collapse, keyed to the master-detail pane width */
@container master-detail (max-width: 840px) {
  .hub-detail-grid--4col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container master-detail (max-width: 560px) {
  .hub-detail-grid--4col { grid-template-columns: 1fr; }
  .hub-detail-grid--2col { grid-template-columns: 1fr; }
}

/* Make sure reused helpers (MOST picker, Volume Source picker) stretch
   to fill the detail-grid column width instead of their hardcoded px
   widths. Scoped tightly to .hub-detail-grid so v1 renderers aren't
   affected. */
.hub-detail-grid .hub-field input,
.hub-detail-grid .hub-field select {
  max-width: 100%;
  box-sizing: border-box;
}
.hub-detail-grid [data-most-select],
.hub-detail-grid [data-labor-volume-source] {
  width: 100% !important;
  font-size: 13px !important;
  padding: 8px 10px !important;
  height: 40px;
  min-height: 40px;
  border: 1px solid var(--ies-gray-200) !important;
}
.hub-detail-grid [data-most-select] + * { flex-shrink: 0; }

/* Read-only field — no input chrome, looks like output, not a disabled input */
.hub-detail-readonly {
  padding: 10px 0 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--ies-gray-800);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  line-height: 1.2;
  min-height: 40px;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  border-bottom: 1px dotted var(--ies-gray-200);
}
.hub-detail-readonly::after {
  content: " computed";
  margin-left: 6px;
  font-size: 10px;
  font-weight: 700;
  color: var(--ies-gray-400);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.7;
  align-self: center;
}

/* Read-only callout block (big number + helper text). Used at the bottom
   of the Labor detail pane and other output-style summaries. */
.hub-detail-readout {
  border: 1px solid var(--ies-gray-200);
}

/* ---- KPI Strip (4-tile row of headline metrics) ---- */
.hub-kpi-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}
@media (max-width: 800px) {
  .hub-kpi-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.hub-kpi-tile {
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.hub-kpi-tile__label {
  font-size: 11px;
  font-weight: 600;
  color: var(--ies-gray-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  /* Allow 2-line wrap rather than ellipsis — at 4-tile or 5-tile strips
     on narrower containers, labels like "ANNUAL OPERATING" or
     "CONTRIB / ORDER" don't fit in one line. Reserve height for 2 lines
     so the tile values still vertically align across a row. */
  line-height: 1.25;
  min-height: calc(2 * 11px * 1.25);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.hub-kpi-tile__value {
  font-size: 20px;
  font-weight: 800;
  color: var(--ies-navy);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.hub-kpi-tile__value--brand { color: var(--ies-blue); }
.hub-kpi-tile__hint {
  font-size: 11px;
  color: var(--ies-gray-400);
}

/* ---- Chips ---- */
.hub-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
  line-height: 1.4;
}
.hub-chip--neutral { background: var(--ies-gray-100); color: var(--ies-gray-600); }
.hub-chip--success { background: #dcfce7; color: #166534; }
.hub-chip--warn { background: #fef3c7; color: #92400e; }
.hub-chip--danger { background: #fee2e2; color: #991b1b; }
.hub-chip--info { background: #dbeafe; color: #1e40af; }
.hub-chip--brand { background: rgba(0, 71, 171, 0.1); color: var(--ies-blue); }

/* ---- Section-level heading inside a card ---- */
.hub-section-heading {
  font-size: 12px;
  font-weight: 700;
  color: var(--ies-gray-600);
  margin: 0 0 10px 0;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ---- CM Monthly Direct Labor View (Brock 2026-04-20) ----
   Peak / avg / min FTE across the contract with per-type MHE and IT
   fleet counts implied by shift structure. Appended below Indirect
   Labor. Sparkline is a simple flex row of 1-col grid bars — no chart
   dep; peak month highlighted orange.
*/
.cm-mlv-card {
  background: #fff;
}
.cm-mlv-kpi {
  padding: 10px 12px;
  border: 1px solid var(--ies-gray-200, #e5e7eb);
  border-radius: 6px;
  background: #fff;
  min-width: 0;
}
.cm-mlv-kpi-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--ies-gray-500, #6b7280);
  text-transform: uppercase;
  letter-spacing: 0.3px;
  line-height: 1.25;
}
.cm-mlv-kpi-value {
  font-size: 22px;
  font-weight: 700;
  color: var(--ies-gray-900, #111827);
  margin-top: 4px;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.cm-mlv-kpi-sub {
  font-size: 11px;
  color: var(--ies-gray-500, #6b7280);
  margin-top: 3px;
  line-height: 1.2;
}
/* ---- MLV header + year pills (Brock 2026-04-20 redesign) ----
   Per-year scope replaces the flat 0-60 sparkline so intra-year
   seasonality is legible instead of conflated with volume growth. */
.cm-mlv-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 4px;
  flex-wrap: wrap;
}
.cm-mlv-header__title { flex: 1 1 320px; min-width: 280px; }

.cm-mlv-year-pills {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  background: var(--ies-gray-100, #f3f4f6);
  border-radius: 8px;
  align-self: flex-start;
  flex-wrap: wrap;
}
.cm-mlv-year-pill {
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ies-gray-600, #4b5563);
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  min-width: 36px;
  transition: background 0.15s ease, color 0.15s ease;
}
.cm-mlv-year-pill:hover { background: #fff; color: var(--ies-gray-900, #111827); }
.cm-mlv-year-pill.is-active {
  background: #fff;
  color: var(--ies-blue, #0047AB);
  box-shadow: 0 1px 2px rgba(0,0,0,0.06);
}
.cm-mlv-year-pill:focus-visible {
  outline: 2px solid var(--ies-blue, #0047AB);
  outline-offset: 2px;
}

.cm-mlv-kpi-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-top: 16px;
}

/* ---- Stacked-bar chart: baseline (gray) + seasonal wedge (orange) ---- */
.cm-mlv-chart-wrap { margin-top: 16px; }
.cm-mlv-chart-legend {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--ies-gray-500, #6b7280);
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.cm-mlv-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
.cm-mlv-legend-swatch--wedge { background: var(--ies-orange, #d97706); }
.cm-mlv-legend-swatch--base  { background: var(--ies-gray-300, #d1d5db); }

.cm-mlv-chart {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 100px;
  padding: 4px 6px;
  background: var(--ies-gray-50, #f9fafb);
  border: 1px solid var(--ies-gray-100, #f3f4f6);
  border-radius: 4px;
}
.cm-mlv-chart.is-all-years {
  gap: 1px;
  padding: 4px 4px;
}
.cm-mlv-bar-col {
  flex: 1 1 0;
  min-width: 6px;
  height: 100%;
  display: flex;
  flex-direction: column-reverse; /* base at bottom, wedge on top */
  border-radius: 2px 2px 0 0;
  overflow: hidden;
  transition: filter 0.15s ease;
}
.cm-mlv-chart.is-all-years .cm-mlv-bar-col { min-width: 2px; border-radius: 1px 1px 0 0; }
.cm-mlv-bar-col:hover { filter: brightness(1.08); }
.cm-mlv-bar-base {
  width: 100%;
  background: var(--ies-gray-300, #d1d5db);
}
.cm-mlv-bar-wedge {
  width: 100%;
  background: rgba(217, 119, 6, 0.5); /* translucent so peak highlight stands out */
}
.cm-mlv-bar-wedge.is-peak {
  background: var(--ies-orange, #d97706);
}

.cm-mlv-chart-axis {
  display: flex;
  gap: 4px;
  margin-top: 4px;
  padding: 0 6px;
}
.cm-mlv-chart-axis.is-all-years { gap: 1px; padding: 0 4px; }
.cm-mlv-axis-label {
  flex: 1 1 0;
  min-width: 6px;
  text-align: center;
  font-size: 10px;
  color: var(--ies-gray-400, #9ca3af);
  font-variant-numeric: tabular-nums;
}
.cm-mlv-chart-axis.is-all-years .cm-mlv-axis-label { min-width: 2px; text-align: left; }
.cm-mlv-axis-label.is-year-start {
  color: var(--ies-gray-600, #4b5563);
  font-weight: 600;
  border-left: 1px solid var(--ies-gray-200, #e5e7eb);
  padding-left: 2px;
}

/* ---- Inline Sync CTA — directly under the chart it acts on ---- */
.cm-mlv-flex-cta {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 14px;
  padding: 12px 14px;
  background: rgba(217, 119, 6, 0.05);
  border: 1px solid rgba(217, 119, 6, 0.18);
  border-left: 3px solid var(--ies-orange, #d97706);
  border-radius: 4px;
  flex-wrap: wrap;
}
.cm-mlv-flex-cta__text {
  flex: 1 1 320px;
  font-size: 13px;
  color: var(--ies-gray-700, #374151);
  line-height: 1.45;
}
.cm-mlv-flex-cta__text strong { color: var(--ies-gray-900, #111827); }
.cm-mlv-flex-cta__btn { white-space: nowrap; }
.cm-mlv-flex-cta--empty {
  background: var(--ies-gray-50, #f9fafb);
  border: 1px solid var(--ies-gray-200, #e5e7eb);
  border-left: 3px solid var(--ies-gray-300, #d1d5db);
}
.cm-mlv-flex-cta--empty .cm-mlv-flex-cta__text { color: var(--ies-gray-500, #6b7280); }

/* ---- CM What-If Studio live preview (Brock 2026-04-20) ----
   Replaces the prior purple-accented gradient card with a neutral
   hub-card that uses the standard left-accent pattern (info-blue)
   shared with Wayfair banners, Recommended-SF callouts, etc. Each
   KPI tile shows value / delta / baseline in a 3-line stack so the
   user sees impact at a glance without hunting across rows.
*/
/* ---- What-If Studio v2 layout (Brock 2026-04-20 redesign) ----
   Two-column grid with wide right pane (KPI table + trajectory chart +
   driver-impact bars). Replaces the narrow sidebar that wasted the
   right half of the content rail. */
.cm-whatif-layout {
  display: grid;
  grid-template-columns: minmax(360px, 42%) 1fr;
  gap: 16px;
  margin-top: 12px;
  align-items: start;
}
@media (max-width: 1080px) {
  .cm-whatif-layout { grid-template-columns: 1fr; }
}

.cm-whatif-drivers-card { padding: 16px 18px; }
.cm-whatif-drivers-card__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--ies-gray-200, #e5e7eb);
}
.cm-whatif-drivers-card__title {
  font-weight: 700;
  font-size: 14px;
  color: var(--ies-gray-900, #111827);
}
.cm-whatif-drivers-card__count {
  font-size: 11px;
  color: var(--ies-gray-500, #6b7280);
}

.cm-whatif-group { margin-bottom: 14px; }
.cm-whatif-group:last-of-type { margin-bottom: 0; }
.cm-whatif-group__title {
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  color: var(--ies-gray-500, #6b7280);
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}

.cm-whatif-slider-row {
  padding: 7px 0 8px;
  border-bottom: 1px solid var(--ies-gray-100, #f3f4f6);
}
.cm-whatif-slider-row:last-child { border-bottom: 0; }
.cm-whatif-slider-row__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cm-whatif-slider-row__label {
  font-size: 13px;
  font-weight: 500;
  color: var(--ies-gray-900, #111827);
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.cm-whatif-impact-chip {
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  padding: 1px 6px;
  border-radius: 10px;
  background: rgba(0,0,0,0.03);
  white-space: nowrap;
}

.cm-whatif-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 14px;
  border-top: 1px solid var(--ies-gray-200, #e5e7eb);
  padding-top: 14px;
}

.cm-whatif-preview-pane {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.cm-whatif-preview-card {
  border-left: 4px solid var(--ies-blue, #0047AB);
  background: #fff;
  padding: 16px 18px;
}
.cm-whatif-preview-card__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
  gap: 12px;
  flex-wrap: wrap;
}
.cm-whatif-preview-card__title {
  font-weight: 700;
  font-size: 14px;
  color: var(--ies-gray-900, #111827);
}
.cm-whatif-preview-card__sub {
  font-size: 11px;
  color: var(--ies-gray-500, #6b7280);
}

/* 3-col KPI table — Baseline | Scenario | Δ */
.cm-whatif-kpi-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.cm-whatif-kpi-table thead th {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--ies-gray-500, #6b7280);
  padding: 4px 6px;
  border-bottom: 1px solid var(--ies-gray-200, #e5e7eb);
  text-align: right;
}
.cm-whatif-kpi-table thead th:first-child { text-align: left; }
.cm-whatif-kpi-table tbody td {
  padding: 8px 6px;
  border-bottom: 1px solid var(--ies-gray-100, #f3f4f6);
  font-size: 13px;
}
.cm-whatif-kpi-table tbody tr:last-child td { border-bottom: 0; }
.cm-whatif-kpi-table .cm-whatif-kpi-row__label {
  font-weight: 600;
  color: var(--ies-gray-700, #374151);
}
.cm-whatif-kpi-table .cm-whatif-kpi-row__baseline { color: var(--ies-gray-500, #6b7280); }
.cm-whatif-kpi-table .cm-whatif-kpi-row__scenario {
  font-weight: 700;
  color: var(--ies-gray-900, #111827);
}
.cm-whatif-kpi-table .cm-whatif-kpi-row__delta { font-weight: 600; }

/* Multi-year trajectory chart (SVG) */
.cm-whatif-chart { }
.cm-whatif-chart__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}
.cm-whatif-chart__title {
  font-size: 13px;
  color: var(--ies-gray-700, #374151);
}
.cm-whatif-chart__title strong { color: var(--ies-gray-900, #111827); }
.cm-whatif-chart__legend {
  margin-left: 12px;
  font-size: 11px;
  color: var(--ies-gray-500, #6b7280);
}
.cm-whatif-chart__swatch {
  display: inline-block;
  width: 10px;
  height: 3px;
  border-radius: 1px;
  vertical-align: middle;
  margin-right: 4px;
}
.cm-whatif-chart__swatch--base { background: var(--ies-gray-400, #9ca3af); }
.cm-whatif-chart__swatch--sce  { background: var(--ies-blue, #0047AB); }
.cm-whatif-chart__metric-pills {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  background: var(--ies-gray-100, #f3f4f6);
  border-radius: 8px;
}
.cm-whatif-chart__pill {
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 600;
  color: var(--ies-gray-600, #4b5563);
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.cm-whatif-chart__pill:hover { background: #fff; }
.cm-whatif-chart__pill.is-active {
  background: #fff;
  color: var(--ies-blue, #0047AB);
  box-shadow: 0 1px 2px rgba(0,0,0,0.06);
}
/* 2026-04-21 PM (Brock feedback): chart layout restructured so the Y-axis
   has a title + tick labels. Grid columns = [axis title (rotated) | tick
   values | canvas]. The SVG still uses preserveAspectRatio="none" so we
   render all labels as HTML outside the SVG — embedded <text> would stretch.
   2026-04-21 evening (Brock overflow report): explicit grid-template-rows
   + min-height:0 + overflow:hidden cap children at 160px. Without these the
   SVG's 100×100 viewBox was inheriting canvas width (~523px) via aspect-ratio
   preservation on ``<svg>`` intrinsic sizing, which stretched the yaxis-ticks
   border-right all the way down past the Driver Impact panel below. */
.cm-whatif-chart__plot {
  display: grid;
  grid-template-columns: 18px 56px 1fr;
  grid-template-rows: 160px;
  gap: 4px;
  align-items: stretch;
  height: 160px;
  max-height: 160px;
  /* NB: no `overflow: hidden` on the grid container. The tick labels use
     `transform: translateY(-50%)` so the TOP and BOTTOM ticks straddle the
     0% / 100% lines by half their text height — clipping the container
     shaves the ends off those labels. The SVG escape we need to contain
     is on the canvas child (see .cm-whatif-chart__canvas below). */
}
.cm-whatif-chart__yaxis-title {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--ies-gray-600, #4b5563);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  text-align: center;
  align-self: center;
  padding: 4px 0;
  white-space: nowrap;
  min-height: 0;
}
.cm-whatif-chart__yaxis-ticks {
  position: relative;
  height: 160px;
  max-height: 160px;
  min-height: 0;
  border-right: 1px solid var(--ies-gray-200, #e5e7eb);
}
.cm-whatif-chart__ytick {
  position: absolute;
  right: 4px;
  transform: translateY(-50%);
  font-size: 10px;
  color: var(--ies-gray-500, #6b7280);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cm-whatif-chart__canvas {
  height: 160px;
  max-height: 160px;
  min-height: 0;
  overflow: hidden;
  background: var(--ies-gray-50, #f9fafb);
  border: 1px solid var(--ies-gray-100, #f3f4f6);
  border-radius: 4px;
  padding: 4px 8px;
  box-sizing: border-box;
}
.cm-whatif-chart__canvas svg { width: 100%; height: 100%; display: block; max-height: 100%; }
.cm-whatif-chart__xaxis-wrap {
  display: grid;
  grid-template-columns: 18px 56px 1fr;
  gap: 4px;
  margin-top: 4px;
}
.cm-whatif-chart__xaxis-title {
  grid-column: 3;
  text-align: center;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--ies-gray-600, #4b5563);
  margin-top: 2px;
  order: 2;
}
.cm-whatif-chart__xaxis {
  grid-column: 3;
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: var(--ies-gray-400, #9ca3af);
  padding: 0 8px;
  order: 1;
}

/* Driver-impact horizontal bars */
.cm-whatif-drivers__hint {
  font-size: 11px;
  color: var(--ies-gray-500, #6b7280);
  margin-bottom: 10px;
  line-height: 1.4;
}
.cm-whatif-drivers__rows { display: flex; flex-direction: column; gap: 6px; }
.cm-whatif-drivers__row {
  display: grid;
  grid-template-columns: 140px 1fr 90px;
  align-items: center;
  gap: 10px;
}
.cm-whatif-drivers__label {
  font-size: 12px;
  font-weight: 500;
  color: var(--ies-gray-700, #374151);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cm-whatif-drivers__bar-track {
  height: 10px;
  background: var(--ies-gray-100, #f3f4f6);
  border-radius: 2px;
  overflow: hidden;
  position: relative;
}
.cm-whatif-drivers__bar {
  height: 100%;
  border-radius: 2px;
  transition: width 0.2s ease;
}
.cm-whatif-drivers__value {
  font-size: 12px;
  font-weight: 700;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.cm-whatif-drivers-empty {
  font-size: 12px;
  color: var(--ies-gray-500, #6b7280);
  text-align: center;
  padding: 14px;
  border: 1px dashed var(--ies-gray-200, #e5e7eb);
  border-radius: 4px;
}
/* 2026-04-21 PM — muted rows for sliders that don't move the currently-
   selected metric. Reviewer still sees the slider is active + a cross-hint
   telling them which metric DOES move (so they can switch the chart metric). */
.cm-whatif-drivers__row--muted .cm-whatif-drivers__label {
  color: var(--ies-gray-400, #9ca3af);
  font-weight: 400;
}
.cm-whatif-drivers__value--muted {
  color: var(--ies-gray-400, #9ca3af);
  font-weight: 500;
  display: flex;
  gap: 6px;
  align-items: center;
  justify-content: flex-end;
}
.cm-whatif-drivers__crosshint {
  font-size: 10px;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 3px;
  background: var(--ies-gray-100, #f3f4f6);
  color: var(--ies-gray-600, #4b5563);
  white-space: nowrap;
  cursor: help;
}
.cm-whatif-drivers__crosshint--none {
  background: transparent;
  color: var(--ies-gray-400, #9ca3af);
  font-weight: 400;
  font-style: italic;
}

/* Legacy — kept for backward compat where .cm-whatif-kpis is still used */
.cm-whatif-preview-card-legacy {
  border-left: 4px solid var(--ies-blue, #0047AB);
  background: #fff;
}
.cm-whatif-kpis {
  container-type: inline-size;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.cm-whatif-kpi {
  display: flex;
  flex-direction: column;
  padding: 10px 12px;
  border: 1px solid var(--ies-gray-200, #e5e7eb);
  border-radius: 6px;
  background: #fff;
  min-width: 0;
}
.cm-whatif-kpi-label {
  font-size: clamp(10px, 1.1cqw + 9px, 12px);
  color: var(--ies-gray-500, #6b7280);
  font-weight: 600;
  line-height: 1.25;
  white-space: normal;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.cm-whatif-kpi-value {
  font-size: clamp(14px, 1.6cqw + 12px, 18px);
  font-weight: 700;
  color: var(--ies-gray-900, #111827);
  margin-top: 3px;
  line-height: 1.15;
}
.cm-whatif-kpi-delta {
  font-size: 11px;
  font-weight: 600;
  margin-top: 2px;
  line-height: 1.2;
}
.cm-whatif-kpi-baseline {
  font-size: 10px;
  font-weight: 500;
  color: var(--ies-gray-400, #9ca3af);
  margin-top: 1px;
  font-variant-numeric: tabular-nums;
}
@container (max-width: 240px) {
  .cm-whatif-kpis { grid-template-columns: 1fr; }
}
@supports not (container-type: inline-size) {
  .cm-whatif-kpi-label { font-size: 10px; }
  .cm-whatif-kpi-value { font-size: 15px; }
}

/* ---- CM Labor master-item share-of-total bar (Brock new #1) ----
   A thin horizontal bar at the bottom of each direct-labor chip so
   you can visually scan which activities drive the biggest chunk of
   direct labor cost. Pairs with a "% of DL" chip in the secondary row.
*/
.cm-labor-share-bar {
  height: 3px;
  margin-top: 6px;
  background: var(--ies-gray-100, #f3f4f6);
  border-radius: 2px;
  overflow: hidden;
}
.cm-labor-share-bar__fill {
  height: 100%;
  border-radius: 2px;
  transition: width 0.15s ease;
}

/* ---- CM MOST per-row revert button (↺ when UPH is overridden) ---- */
/* Previously inline-styled at 12px font — too small to read next to the 11px
   select. Bumped to 16px with a subtle amber pill affordance so it's clearly
   a clickable control, not decoration. */
.cm-most-revert {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  margin-left: 2px;
  background: #fef3c7;
  color: #b45309;
  border: 1px solid #fcd34d;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  font-weight: 700;
  flex-shrink: 0;
  transition: background 0.1s, color 0.1s, transform 0.1s;
}
.cm-most-revert:hover {
  background: #fde68a;
  color: #92400e;
  transform: rotate(-30deg);
}
.cm-most-revert:active {
  transform: rotate(-60deg);
}
.cm-most-revert:focus-visible {
  outline: 2px solid var(--ies-blue);
  outline-offset: 1px;
}

/* ---- Completion dots (for grouped sidebar nav) ---- */
.hub-completion-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  vertical-align: middle;
  margin-left: 6px;
  flex-shrink: 0;
}
.hub-completion-dot--complete { background: #16a34a; }
.hub-completion-dot--partial  { background: #fbbf24; }
.hub-completion-dot--empty    { background: var(--ies-gray-200); }

/* ---- Sidebar group header (collapsible, used in v2 nav) ---- */
.hub-nav-group {
  margin-bottom: 4px;
}
.hub-nav-group__header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: 10px;
  font-weight: 700;
  color: var(--ies-gray-400);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  cursor: pointer;
  user-select: none;
  border: 0;
  background: transparent;
  width: 100%;
  text-align: left;
}
.hub-nav-group__header:hover { color: var(--ies-gray-600); }
.hub-nav-group__caret {
  font-size: 9px;
  color: var(--ies-gray-400);
  transition: transform var(--ease-default);
}
.hub-nav-group__count {
  font-size: 10px;
  font-weight: 600;
  color: var(--ies-gray-400);
  margin-left: auto;
}
.hub-nav-group__items {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.hub-nav-group.is-collapsed .hub-nav-group__items { display: none; }
.hub-nav-group.is-collapsed .hub-nav-group__caret { transform: rotate(-90deg); }

/* ============================================================
 * CM PHASE 3 — Section-level primitives (Summary / Timeline /
 * Equipment / Overhead / VAS / narrow forms). Replaces inline
 * <style> blocks and inline style="..." attributes that lived
 * inside renderXxx() template literals.
 * ============================================================ */

/* ---- Stacked cost-breakdown bar + legend (Summary, top of page) ---- */
.cm-stacked-bar {
  display: flex;
  height: 32px;
  border-radius: 6px;
  overflow: hidden;
  margin-bottom: 16px;
}
.cm-stacked-legend {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
@media (max-width: 720px) {
  .cm-stacked-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.cm-stacked-legend__item {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.cm-stacked-legend__swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex-shrink: 0;
}

/* ---- Multi-Year P&L row accents (Summary) ---- */
.cm-pnl-row-total td {
  background: var(--ies-gray-50);
  font-weight: 700;
  border-top: 1px solid var(--ies-gray-200);
}
.cm-pnl-row-revenue td { background: rgba(0, 71, 171, 0.04); }
.cm-pnl-row-capex td { border-top: 2px solid var(--ies-gray-200); }

/* ---- Horizontal scroll wrapper for tables (avoids overflow on inputs) ---- */
.cm-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---- CM Summary 2-column row (CM layout pass 2026-04-29) ---- */
/* Pairs Cost Breakdown + Financial Metrics side-by-side now that the new
   chrome reclaimed horizontal space. Cost Breakdown takes ~38% (its content
   is denser per inch); Financial Metrics takes ~62% (cm-metrics-grid has
   4 columns internally and benefits from the wider half). */
.cm-summary-row {
  display: grid;
  grid-template-columns: minmax(0, 38fr) minmax(0, 62fr);
  gap: 16px;
  align-items: start;
}
@media (max-width: 1100px) {
  .cm-summary-row { grid-template-columns: 1fr; gap: 12px; }
}

/* ---- Financial Metrics 4-col grid (Summary) ---- */
.cm-metrics-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}
@media (max-width: 900px) {
  .cm-metrics-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 540px) {
  .cm-metrics-grid { grid-template-columns: 1fr; }
}
/* Metric card: extends hub-kpi-tile with pass/fail/neutral semantics */
.cm-metric-card { text-align: left; }
.cm-metric-card.is-pass {
  border-color: rgba(32, 201, 151, 0.4);
  background: rgba(32, 201, 151, 0.04);
}
.cm-metric-card.is-pass .hub-kpi-tile__value { color: #0d9668; }
.cm-metric-card.is-fail {
  border-color: rgba(220, 53, 69, 0.3);
  background: rgba(220, 53, 69, 0.04);
}
.cm-metric-card.is-fail .hub-kpi-tile__value { color: var(--ies-red); }
/* is-neutral inherits the default hub-kpi-tile styling */

/* ---- Timeline section primitives ---- */
.cm-timeline-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 12px;
}
.cm-timeline-meta__title { margin: 0; font-size: 16px; font-weight: 700; color: var(--ies-gray-900); }
.cm-timeline-meta__hint { font-size: 11px; color: var(--ies-gray-400); }

.cm-timeline-monthly-scroll {
  max-height: 400px;
  overflow-y: auto;
  border-radius: var(--radius-md);
}
.cm-timeline-monthly-scroll thead {
  position: sticky;
  top: 0;
  background: #fff;
  z-index: 1;
  box-shadow: 0 1px 0 var(--ies-gray-200);
}
.cm-timeline-pre-go-live { background: #fef3c7; }
.cm-timeline-pre-go-live-tag {
  color: #92400e;
  font-size: 10px;
  margin-left: 4px;
  font-weight: 600;
  text-transform: uppercase;
}

/* ---- Equipment master-detail (Phase 3) ---- */
.cm-equipment-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--ies-gray-500);
}

/* ---- Generic hub-datatable nest in cm-card (Overhead / VAS) ---- */
.hub-datatable .cm-num,
.hub-datatable td.cm-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.hub-datatable .cm-total-row td,
.hub-datatable tr.cm-total-row td {
  font-weight: 700;
  background: var(--ies-gray-50);
  border-top: 1px solid var(--ies-gray-200);
}

/* M1 (2026-04-21): G&A + Mgmt Fee inline split inputs on Financial section */
.cm-margin-split {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--ies-gray-200);
  border-radius: 6px;
  background: var(--ies-gray-50);
}
.cm-margin-split-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 140px;
}
.cm-margin-split-field .hub-input {
  width: 100%;
  text-align: right;
  font-weight: 600;
}
.cm-margin-split-sublabel {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--ies-gray-600);
}
.cm-margin-split-op {
  font-size: 18px;
  font-weight: 700;
  color: var(--ies-gray-400);
  padding-bottom: 6px;
}
.cm-margin-split-total {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 120px;
  padding: 0 10px;
}
.cm-margin-split-total-value {
  font-size: 22px;
  font-weight: 700;
  color: var(--ies-blue);
  line-height: 1.1;
}
.hub-datatable td.cm-actions { width: 1%; white-space: nowrap; }
.hub-datatable .cm-delete-btn {
  border: 0;
  background: transparent;
  color: var(--ies-gray-400);
  font-size: 11px;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 4px;
}
.hub-datatable .cm-delete-btn:hover { color: var(--ies-red); background: rgba(220, 53, 69, 0.06); }

/* ---- Position-Catalog notes (expandable row) — Brock 2026-04-26 ---- */
/* Replaces the old sliver-width inline notes <input>. Each catalog row has
   a Notes button cell that expands a full-width sub-row with a real textarea. */
.cm-pos-note-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  max-width: 100%;
  text-align: left;
  border: 1px solid var(--ies-gray-200, #e5e7eb);
  background: #fff;
  color: var(--ies-gray-700, #334155);
  font-size: 12px;
  line-height: 1.3;
  padding: 5px 8px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cm-pos-note-btn:hover {
  background: var(--ies-gray-50, #f9fafb);
  border-color: var(--ies-gray-300, #cbd5e1);
}
.cm-pos-note-btn--filled {
  background: #fef3c7;            /* warm amber — matches the legacy-mode banner */
  border-color: #fcd34d;
  color: #92400e;
}
.cm-pos-note-btn--filled:hover {
  background: #fde68a;
  border-color: #f59e0b;
}
.cm-pos-note-btn--empty .cm-pos-note-empty {
  color: var(--ies-gray-400, #94a3b8);
  font-style: italic;
}
.cm-pos-note-btn--open {
  border-color: var(--ies-blue, #3b82f6);
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
}
.cm-pos-note-chev {
  display: inline-block;
  width: 9px;
  font-size: 11px;
  color: var(--ies-gray-400, #94a3b8);
  flex: 0 0 9px;
}
.cm-pos-note-btn--filled .cm-pos-note-chev { color: #b45309; }
.cm-pos-note-btn--open .cm-pos-note-chev { color: var(--ies-blue, #3b82f6); }
.cm-pos-note-preview {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Expanded notes sub-row — full-width textarea on a tinted band */
.cm-pos-notes-row > td { padding: 0 !important; }
.cm-pos-row-expanded > td {
  background: var(--ies-gray-50, #f9fafb);
}
.cm-pos-notes-textarea:focus {
  outline: none;
  border-color: var(--ies-blue, #3b82f6) !important;
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.18) !important;
}

/* ---- CM-INSP-1 hover disclosure popover (Brock 2026-04-26) ---- */
.cm-disclose-popover {
  position: absolute;
  z-index: 99997;
  min-width: 260px;
  max-width: 360px;
  background: #fff;
  color: #0f172a;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  box-shadow: 0 12px 30px rgba(15, 23, 42, 0.15);
  padding: 0;
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.4;
  pointer-events: none; /* hover-only — no interaction needed */
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 0.14s ease, transform 0.14s ease;
}
.cm-disclose-popover--visible {
  opacity: 1;
  transform: translateY(0);
}
.cm-disclose-popover::after {
  content: '';
  position: absolute;
  left: var(--cm-disclose-arrow-x, 50%);
  width: 10px;
  height: 10px;
  background: #fff;
  border-right: 1px solid #e2e8f0;
  border-bottom: 1px solid #e2e8f0;
  transform: translateX(-50%) rotate(45deg);
}
.cm-disclose-popover[data-placement="above"]::after {
  bottom: -6px;
}
.cm-disclose-popover[data-placement="below"]::after {
  top: -6px;
  border-right: none;
  border-bottom: none;
  border-left: 1px solid #e2e8f0;
  border-top: 1px solid #e2e8f0;
}
.cm-disclose-head {
  padding: 10px 14px 8px;
  border-bottom: 1px solid #f1f5f9;
}
.cm-disclose-title {
  font-size: 13px;
  font-weight: 700;
  color: #0f172a;
}
.cm-disclose-formula {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 10.5px;
  color: #64748b;
  margin-top: 3px;
  line-height: 1.35;
  word-break: break-word;
}
.cm-disclose-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 5px 14px;
  font-size: 12.5px;
}
.cm-disclose-row__label {
  color: #475569;
  flex: 1 1 auto;
  min-width: 0;
}
.cm-disclose-row__hint {
  display: block;
  font-size: 10.5px;
  color: #94a3b8;
  margin-top: 1px;
  font-style: italic;
}
.cm-disclose-row__value {
  flex: 0 0 auto;
  color: #0f172a;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cm-disclose-total {
  border-top: 1px solid #e2e8f0;
  background: #f8fafc;
  margin-top: 4px;
  padding: 4px 0;
}
.cm-disclose-total .cm-disclose-row__label {
  font-weight: 700;
  color: #0f172a;
}
.cm-disclose-total .cm-disclose-row__value {
  font-size: 13.5px;
  color: var(--ies-blue, #3b82f6);
}
.cm-disclose-foot {
  padding: 8px 14px 10px;
  border-top: 1px dashed #e2e8f0;
  font-size: 11px;
  color: #64748b;
  line-height: 1.45;
  background: #fafafa;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}
.cm-disclose-foot strong { color: #334155; font-weight: 600; }
/* Cursor cue on the disclose-tagged tiles */
[data-cm-disclose] {
  cursor: help;
  position: relative;
}
[data-cm-disclose]::before {
  content: 'i';
  position: absolute;
  top: 6px; right: 8px;
  width: 14px; height: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'Times New Roman', serif;
  font-style: italic;
  font-size: 10px;
  font-weight: 600;
  color: #94a3b8;
  background: #f1f5f9;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s ease;
}
[data-cm-disclose]:hover::before {
  opacity: 1;
}

/* ---- Auto-Generate / Catalog button row (Equipment, Overhead) ---- */
.cm-section-toolbar {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.cm-section-toolbar__hint {
  font-size: 11px;
  color: var(--ies-gray-400);
  flex: 1;
  min-width: 200px;
}

/* ---- Narrow-form primitives (Setup / Facility / Shifts / Financial / Startup / OrderProfile)
   ---- 2026-04-29 layout pass: was capped at max-width 720px (legacy chrome
   constraint). New chrome reclaimed ~12% horizontal — switching to
   auto-fit so columns flow with viewport: 4-col on wide screens, 3-col
   on standard laptops, 2-col on small windows, 1-col on phones. ---- */
.cm-narrow-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px 18px;
}
/* Tools that pass an explicit grid-template-columns inline (e.g. repeat(3, ..)
   or repeat(4, ..)) override the auto-fit default — kept working unchanged. */
@media (max-width: 640px) {
  .cm-narrow-form { grid-template-columns: 1fr; }
}
.cm-narrow-form .hub-field--full { grid-column: 1 / -1; }
.cm-narrow-form .hub-input,
.cm-narrow-form select.hub-input {
  width: 100%;
  box-sizing: border-box;
}

/* ---- Linked Designs grid (2026-04-29 layout pass)
   4 design-tool cards stack vertically by default; on wider canvas they
   pack tighter as 2x2 (or 4-col on very wide screens). ---- */
.cm-linked-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  gap: 12px;
  margin-top: 12px;
}
/* The .hub-card.mt-4 inline marg fights the grid-gap on the first card.
   Inside cm-linked-grid we drop the margin-top — the grid handles spacing. */
.cm-linked-grid > .hub-card { margin-top: 0; }

/* ---- Assumptions categories grid (2026-04-29 layout pass)
   Each category card hosts a small table (5 cols, ~5-15 rows). With the
   wider canvas they fit 2-up or 3-up nicely instead of stacking. ---- */
.cm-assumptions-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(520px, 1fr));
  gap: 16px;
  align-items: start;
}
.cm-assumptions-grid > .cm-card { margin-top: 0; }

/* ---- Financial Assumptions sub-cards (CM-ASM-1, 2026-04-26)
   2026-04-29 layout pass: dropped max-width 1040px cap. ---- */
.cm-fin-grid {
  display: grid;
  gap: 18px;
}
.cm-fin-section {
  background: #fff;
  border: 1px solid var(--ies-gray-100, #f0f1f3);
  border-radius: var(--radius-md, 12px);
  padding: 20px 22px;
  box-shadow: 0 1px 2px rgba(15, 27, 46, 0.03);
}
.cm-fin-section__header {
  margin: 0 0 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--ies-gray-100, #f0f1f3);
}
.cm-fin-section__header h3 {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--ies-navy, #0a2540);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.cm-fin-section__header p {
  margin: 4px 0 0;
  font-size: 12px;
  color: var(--ies-gray-500, #6b7280);
  line-height: 1.45;
}
.cm-fin-row {
  display: grid;
  gap: 14px 18px;
  grid-template-columns: 1fr;
}
.cm-fin-row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cm-fin-row--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cm-fin-row + .cm-fin-row { margin-top: 14px; }
@media (max-width: 720px) {
  .cm-fin-row--2,
  .cm-fin-row--3 { grid-template-columns: 1fr; }
}

/* ---- Seasonality grid breathing room (CM-SEAS-1, 2026-04-26) ---- */
/* Tighter input padding so 12 month cells render in full now that the
   parent form expanded to wide-layout. */
.cm-season-grid {
  grid-template-columns: repeat(12, minmax(54px, 1fr)) !important;
  gap: 6px !important;
}
.cm-season-cell input.hub-input {
  padding: 8px 4px;
  height: 36px;
  font-size: 12px;
}


/* ---- Generic mt-2 utility (one-shot, used by Sensitivity hint) ---- */
.mt-2 { margin-top: 8px; }

/* ---- Shifts — Annual operating hours hero card ---- */
.cm-opshours-card {
  background: linear-gradient(135deg, #0a1628, #0d1f3c);
  color: #fff;
  text-align: center;
  padding: 20px;
  border-radius: var(--radius-md);
  max-width: 720px;
}
.cm-opshours-card__label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: 4px;
}
.cm-opshours-card__value {
  font-size: var(--fs-hero);
  font-weight: var(--fw-extrabold);
  font-variant-numeric: tabular-nums;
}
.cm-opshours-card__formula {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.55);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* ---- Currency-input cell (Brock 2026-04-21 pm) ----
   Wraps a $ prefix alongside a number input in a table cell so
   wages/salaries display as currency without losing numeric editing. */
.cm-currency-cell {
  position: relative;
  padding: 4px 6px;
}
.cm-currency-prefix {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12px;
  color: var(--ies-gray-500);
  pointer-events: none;
  font-weight: 500;
}
.cm-currency-input {
  padding-left: 16px !important;
}
.cm-currency-input:disabled + .cm-currency-prefix,
.cm-currency-cell:has(.cm-currency-input:disabled) .cm-currency-prefix {
  color: var(--ies-gray-300);
}

/* ---- CM Phase 3 follow-up — table min-widths so columns don't cram ---- */
/* Dense hub-datatables inside .cm-table-scroll need room to breathe.
   Without a min-width, narrow containers (or CM's 5-column Equipment table
   with 10 cols + actions) squeeze inputs to 30-40px and truncate text.
   min-width forces horizontal scroll below threshold — readable over
   compact-but-broken. */
.cm-table-scroll > .hub-datatable { min-width: 680px; }
/* Equipment has 12 columns post-Phase-2a (added Line Type enum). Bumped
   960 → 1100px to fit the enum dropdowns' longest options ("Owned Facility",
   "IT Equipment") without truncation. Horizontal scroll kicks in below
   ~1100px viewport which is a narrower laptop than the CM panel supports
   anyway. */
.cm-table-scroll > .hub-datatable.cm-table-equipment { min-width: 1100px; }
/* Overhead + VAS + Startup: 5-6 columns, moderate min */
.cm-table-scroll > .hub-datatable.cm-table-overhead { min-width: 780px; }
.cm-table-scroll > .hub-datatable.cm-table-vas      { min-width: 640px; }
.cm-table-scroll > .hub-datatable.cm-table-startup  { min-width: 680px; }

/* Timeline monthly: 8 columns (Month / Rev / Opex / EBITDA / NI / CapEx / FCF / CumFCF) */
.cm-timeline-monthly-scroll > .hub-datatable { min-width: 780px; }

/* Ensure input elements inside data-table cells don't add extra horizontal
   padding that pushes columns wider than declared. Reset the 32px+ input
   height to fit inside 26-28px rows. */
.hub-datatable--dense .hub-input {
  height: 28px;
  padding: 4px 8px;
  font-size: 13px;
}

/* Slight negative margin on cm-delete-btn so the action col doesn't demand
   excessive width. */
.hub-datatable .cm-actions .cm-delete-btn {
  font-size: 14px;
  line-height: 1;
  padding: 2px 6px;
  min-width: 22px;
  font-weight: 700;
}

/* Enforce explicit column widths on the Equipment table to prevent cells
   from auto-growing past their declared sizes. Without fixed layout,
   one long input value (e.g. "Sit-down Counterbalance Forklift") can
   expand the Equipment column and collapse adjacent columns. */
.cm-table-equipment { table-layout: fixed; }

/* Hide browser number input spinner arrows inside dense tables — they eat
   10-16px of visible width from already-tight columns and read as noise. */
.hub-datatable input[type="number"]::-webkit-outer-spin-button,
.hub-datatable input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.hub-datatable input[type="number"] { -moz-appearance: textfield; }

/* ============================================================
 * Shared cost-model grid table -- extracted from tools/cost-model/ui.js
 * so MOST + WSC + admin tables get correct column spacing without
 * needing CM to be opened first. (MOS-D1)
 * ============================================================ */
.cm-grid-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.cm-grid-table th {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--ies-gray-500);
  text-align: left;
  padding: 8px 10px;
  border-bottom: 2px solid var(--ies-gray-200);
  white-space: nowrap;
}
.cm-grid-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--ies-gray-100);
  vertical-align: middle;
}
.cm-grid-table input,
.cm-grid-table select {
  padding: 6px 8px;
  border: 1px solid var(--ies-gray-200);
  border-radius: 4px;
  font-family: Montserrat, sans-serif;
  font-size: 13px;
  font-weight: 600;
}
.cm-grid-table input:focus,
.cm-grid-table select:focus {
  outline: none;
  border-color: var(--ies-blue);
  box-shadow: 0 0 0 2px rgba(0,71,171,0.1);
}
.cm-num { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.cm-total-row td { font-weight: 700; border-top: 2px solid var(--ies-gray-300); background: var(--ies-gray-50); }
.cm-add-row-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 8px;
  padding: 6px 12px;
  background: none;
  border: 1px dashed var(--ies-gray-300);
  border-radius: 6px;
  color: var(--ies-blue);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  font-family: Montserrat, sans-serif;
}
.cm-add-row-btn:hover { border-color: var(--ies-blue); background: rgba(0,71,171,0.04); }
.cm-delete-btn {
  background: none;
  border: none;
  color: var(--ies-red);
  cursor: pointer;
  font-size: 11px;
  font-weight: 600;
  padding: 4px 8px;
  border-radius: 4px;
  font-family: Montserrat, sans-serif;
}
.cm-delete-btn:hover { background: rgba(220,53,69,0.08); }

/* ============================================================
   Cost-Model — Assumptions & Planning Ratios surface
   Added 2026-04-26 for CM-AES-1: page was held together by
   inline styles only. These classes give the surface a
   coherent rhythm — section header → grouped cards → tables.
   ============================================================ */

.cm-section-header {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 0 0 14px;
  border-bottom: 1px solid var(--ies-gray-100);
  margin-bottom: 16px;
}
.cm-section-header h2 {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  color: var(--ies-navy);
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.cm-section-header__intro {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
}
.cm-section-header__intro > .cm-subtle { flex: 1; min-width: 240px; }
.cm-section-header__actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  flex-shrink: 0;
}

.cm-subtle {
  margin: 0;
  color: var(--ies-gray-600);
  font-size: 13px;
  line-height: 1.45;
  max-width: 760px;
}

.cm-card {
  background: #fff;
  border: 1px solid var(--ies-gray-200);
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}
.cm-card + .cm-card { margin-top: 12px; }
/* 2026-04-27 AM9 — negate the vertical-stacking margin when .cm-card pairs
   sit side-by-side inside a grid row. The +adjacent-sibling rule above is
   meant for vertically-stacked cards on the same page; in a 2-column grid
   it adds a 12px push to the SECOND card that ends up shrinking its
   effective height (cards stretch to row height; the margin eats from
   that envelope), producing visibly mismatched card heights. Brock spotted
   this on Implementation's Volume Ramp + Headcount Ramp pair (12px gap). */
[style*="grid-template-columns:1fr 1fr"] > .cm-card + .cm-card,
[style*="grid-template-columns: 1fr 1fr"] > .cm-card + .cm-card,
[style*="grid-template-columns:repeat(2"] > .cm-card + .cm-card,
[style*="grid-template-columns: repeat(2"] > .cm-card + .cm-card {
  margin-top: 0;
}
.cm-card > h3:first-child {
  margin: 0 0 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ies-gray-700);
  display: flex;
  align-items: center;
  gap: 8px;
}
.cm-card--collapsible { padding: 0; overflow: hidden; }

.cm-card-toggle {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border: 0;
  background: #fff;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: var(--ies-navy);
  transition: background 0.12s ease;
}
.cm-card-toggle:hover { background: var(--ies-gray-50); }
.cm-card-toggle__title { font-size: 14px; font-weight: 700; flex: 1; color: var(--ies-navy); }
.cm-card-toggle__count { font-size: 11px; color: var(--ies-gray-500); }
.cm-card-toggle__caret { font-size: 12px; color: var(--ies-gray-400); width: 14px; text-align: center; }
.cm-card[data-open="true"] > .cm-card-toggle { border-bottom: 1px solid var(--ies-gray-100); }
.cm-card[data-open="true"] > .cm-card-toggle__caret { color: var(--ies-blue); }
.cm-card-body { padding: 12px 16px 16px; }
.cm-card-body__hint { font-size: 12px; color: var(--ies-gray-500); margin: 0 0 8px; }

.cm-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.cm-table thead th {
  text-align: left;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ies-gray-500);
  background: var(--ies-gray-50);
  padding: 10px;
  border-bottom: 1px solid var(--ies-gray-200);
  white-space: nowrap;
}
.cm-table thead th.cm-th-num { text-align: right; }
.cm-table thead th.cm-th-center { text-align: center; }
.cm-table tbody td {
  padding: 10px;
  border-bottom: 1px solid var(--ies-gray-100);
  vertical-align: top;
}
.cm-table tbody tr:last-child td { border-bottom: 0; }
.cm-table tbody tr:hover td { background: var(--ies-gray-50); }
.cm-table tbody tr.cm-row--override td { background: #fffbeb; }
.cm-table tbody tr.cm-row--override:hover td { background: #fef3c7; }

.cm-cell-title { font-weight: 600; color: var(--ies-navy); font-size: 13px; line-height: 1.3; }
.cm-cell-meta {
  font-size: 11px;
  color: var(--ies-gray-500);
  margin-top: 2px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  word-break: break-all;
}
.cm-cell-filters {
  font-size: 10px;
  color: var(--ies-gray-400);
  margin-top: 4px;
  letter-spacing: 0.02em;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.cm-cell-filters span {
  background: var(--ies-gray-100);
  padding: 1px 6px;
  border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.cm-cell-notes { font-size: 12px; color: var(--ies-gray-600); line-height: 1.4; }
.cm-cell-source { font-size: 11px; color: var(--ies-gray-500); line-height: 1.35; }
.cm-cell-source__detail { font-size: 10px; color: var(--ies-gray-400); margin-top: 1px; }

.cm-row-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  justify-content: center;
}

.cm-empty-state {
  text-align: center;
  padding: 40px 16px;
  color: var(--ies-gray-500);
  font-size: 13px;
  background: var(--ies-gray-50);
  border: 1px dashed var(--ies-gray-200);
  border-radius: 8px;
}

.cm-audit-banner {
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-left: 4px solid #f59e0b;
  border-radius: 6px;
  padding: 12px 14px;
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.cm-audit-banner-label {
  flex: 1;
  font-size: 13px;
  color: #78350f;
  line-height: 1.4;
  min-width: 220px;
}
.cm-audit-banner-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

/* Status chip color variants — layered on .hub-status-chip */
.hub-status-chip.cm-chip-warn    { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.hub-status-chip.cm-chip-info    { background: var(--ies-gray-100); color: var(--ies-gray-600); border-color: var(--ies-gray-200); }
.hub-status-chip.cm-chip-stale   { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.hub-status-chip.cm-chip-success { background: #d1fae5; color: #065f46; border-color: #a7f3d0; }
.hub-status-chip.cm-chip-xs      { font-size: 9px; padding: 1px 6px; }

/* Sub-section divider — Planning Ratios sits below Heuristics */
.cm-section-divider {
  height: 1px;
  background: var(--ies-gray-100);
  margin: 28px 0 20px;
}

/* ============================================================
   CM-IMPL-1 — Implementation Timeline (2026-04-26)
   ============================================================ */
.cm-impl-gantt {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--ies-gray-50);
  padding: 12px;
  border-radius: 6px;
  border: 1px solid var(--ies-gray-200);
}
.cm-impl-gantt__ruler {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 8px;
  align-items: center;
  margin-bottom: 6px;
}
.cm-impl-gantt__row {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 8px;
  align-items: center;
}
.cm-impl-gantt__row + .cm-impl-gantt__row {
  border-top: 1px dashed var(--ies-gray-200);
}
.cm-impl-gantt__ruler-label {
  font-size: 11px;
  color: var(--ies-gray-700);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 8px;
}
.cm-impl-gantt__ruler-track {
  background: rgba(255,255,255,0.5);
  border-radius: 3px;
}
.cm-impl-gantt__bar {
  cursor: default;
  box-shadow: 0 1px 2px rgba(15,23,42,0.08);
  transition: filter 0.15s ease;
}
.cm-impl-gantt__bar:hover {
  filter: brightness(1.08);
}

/* ============================================================
   EVE8 — Cost Model sticky KPI strip + sidebar polish
   ============================================================
   1) Pin a 5-tile KPI bar (`.hub-kpi-bar` borrowed from NetOpt) to the top
      of the CM content scroll container. Stays visible while the user
      moves between the 12 sections so the headline cost/unit, margin,
      FTE, and NPV numbers always read where the eye expects them.
   2) Tighten the existing 12-section sidebar to NetOpt's visual hierarchy:
      sharper active-state pill, gradient accent, monospace dot scale,
      crisper group dividers. NO IA changes — same sections, same nesting.
   3) Tri-state save chip: layer dot color on `.hub-status-chip.draft|.modified|.saved`
      so the leading dot adopts the same hue as the chip text. */

.cm-header-kpis {
  position: sticky;
  /* `top: -24px` (negative offset = sticks ABOVE the content edge, into
     `.hub-builder-content`'s padding-top zone) so the white backdrop
     fully covers content scrolling under it. Without the negative top,
     the wrapper sticks at the content edge and there's a 24px padding
     band ABOVE the wrapper through which content visibly bleeds —
     which is exactly the symptom Brock reported 2026-04-27 morning
     ("text going behind and above the blue KPI tile when scrolling").
     The 48px padding-top + the wrapper margin pulls the navy bar BACK
     to the same visual position as before so the design doesn't shift. */
  top: calc(var(--sp-6) * -1);
  z-index: 5;
  /* Backdrop spans the full .hub-builder-content (clawing back its
     var(--sp-6) padding on top + sides) so the white surface covers
     scrolled content above + at the edges. The navy bar inside is
     re-inset via padding so it lines up with section content below. */
  margin: calc(var(--sp-6) * -1) calc(var(--sp-6) * -1) var(--sp-6);
  padding: calc(var(--sp-6) * 2) var(--sp-6) 0;
  background: #fff;
}
.cm-header-kpis:empty {
  display: none;
  margin: 0;
  padding: 0;
  background: transparent;
}
/* The navy bar caps at the wide content max so it has a CONSISTENT
   width across every section — it reads as a page-header dashboard,
   not as a sub-element of the form. Forms below it can be narrower
   (Setup/Facility/Shifts cap at var(--form-max-width); the form's
   right edge being inside the bar's right edge is the standard
   dashboard pattern and reads as deliberate hierarchy, not misalignment.
   What matters — and what this enforces — is that the LEFT EDGE of the
   bar always aligns with the section header + form fields below. */
.cm-header-kpis .hub-kpi-bar {
  max-width: var(--content-max-width);
  /* Left-align (no auto margin) so the bar starts at the gutter,
     matching where section content + headers begin. */
}
.cm-header-kpis .hub-kpi-bar {
  /* More vertical breathing room — labels/values had nowhere to sit
     before. 16/12 vertical padding gives a strip ~58px tall with the
     trimmed type below, vs. the prior ~50px which felt cramped. */
  padding: 16px var(--sp-4);
  border-radius: var(--radius-md);
  /* Stronger shadow so the bar reads as a lifted card sitting above
     the section content column rather than a flat dark slab. */
  box-shadow: 0 6px 16px rgba(10, 22, 40, 0.18);
}
.cm-header-kpis .hub-kpi-item {
  /* Crisper tile divider on dark navy. */
  border-right-color: rgba(255,255,255,0.18);
  padding: 0 var(--sp-3);
  gap: 4px;
}
/* Cap value type so $17.0M / 149.2 / 17.9% feel proportionate to strip
   height. Base .hub-kpi-value clamps to 22px at full width, which reads
   oversized inside CM's narrower content column. */
.cm-header-kpis .hub-kpi-value {
  font-size: clamp(13px, 1.6cqi, 17px);
  line-height: 1.15;
  margin-top: 2px;
}
.cm-header-kpis .hub-kpi-label {
  font-size: clamp(9px, 1cqi, 10px);
  letter-spacing: 0.6px;
  margin-bottom: 2px;
}
/* Subtle "I'm recalculating" pulse — host element gets `.is-ready`
   after the first successful compute. */
.cm-header-kpis:not(.is-ready) .hub-kpi-bar {
  opacity: 0.85;
}

/* ---- 2026-04-27 — page-name + description LIVE INSIDE the navy bar ----
   Lifted out of the orphaned `.cm-section-header` so each section reads
   as a unified "tab identity" header. Title + description sit in a
   top row, with the 5 KPI items in a bottom row, separated by a hairline
   white-on-navy rule. Source titles still live in each section's
   render fn — `refreshHeaderKpis()` reads them out and reflects them
   here, then `.cm-section-header` is hidden via CSS below to avoid
   duplication. Fallback: if read fails, the bar renders without the
   title block (KPIs only) — same as the pre-2026-04-27 layout. */
.cm-header-kpis .hub-kpi-bar {
  /* The bar is now a vertical stack: title block on top, KPIs below.
     `flex-direction: column` overrides the default row layout from
     `.hub-kpi-bar` itself. */
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 14px var(--sp-4);
}
.cm-header-kpis .hub-kpi-bar__id {
  padding: 0 4px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  margin-bottom: 12px;
}
.cm-header-kpis .hub-kpi-bar__title {
  font-size: 18px;
  font-weight: 700;
  color: #fff;
  letter-spacing: 0.1px;
  line-height: 1.2;
}
/* Inline chips inside the title (e.g. Pricing Schedule contract-type chip)
   inherit the navy background so they read on the dark bar — the public
   `.cm-contract-type-chip` styles assume a light surface. */
.cm-header-kpis .hub-kpi-bar__title .cm-contract-type-chip {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.22);
}
.cm-header-kpis .hub-kpi-bar__desc {
  font-size: 12px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.72);
  margin-top: 4px;
  line-height: 1.4;
  /* Wrap gracefully on narrower viewports — descriptions can be long
     (Labor Factors, Pricing Buckets, Financial Assumptions). */
  white-space: normal;
}
.cm-header-kpis .hub-kpi-bar__desc strong,
.cm-header-kpis .hub-kpi-bar__desc code {
  color: #fff;
  font-weight: 600;
}
.cm-header-kpis .hub-kpi-bar__metrics {
  display: flex;
  align-items: stretch;
  width: 100%;
}
/* The hub-kpi-item is already styled — just ensure it grows evenly across
   the metrics row now that it's inside an inner flex container. */
.cm-header-kpis .hub-kpi-bar__metrics .hub-kpi-item {
  flex: 1 1 0;
  min-width: 0;
}

/* The original `.cm-section-header` (page name + description text inside
   the form) is the SOURCE OF TRUTH for the title/desc text — `refreshHeaderKpis`
   reads it and re-renders it inside the navy bar.
   
   2026-04-27 AM6 fix: hide ONLY the title + description elements, NOT the
   entire `.cm-section-header` — six sections (Facility, Pricing Schedule,
   Summary, Linked Designs, Assumptions, Planning Ratios) embed action
   buttons ("Size with Calculator →", scenario compare, export, refresh,
   reset, etc.) directly inside the header element. Hiding the whole
   thing nukes those buttons. Brock walkthrough caught the WSC link
   regression on Facility — same class of bug as the AM3 selector
   over-broadening.
   
   Strategy: hide title-bearing nodes (title, desc, intro wrappers, raw
   h1/h2/h3, .cm-subtle) and strip the chrome from the host header so it
   reads as a clean actions strip. If no buttons remain, the empty header
   collapses via the :has() guard at the bottom. */
#cm-section-content .cm-section-header .cm-section-title,
#cm-section-content .cm-section-header .cm-section-desc,
#cm-section-content .cm-section-header > h1,
#cm-section-content .cm-section-header > h2,
#cm-section-content .cm-section-header > h3,
#cm-section-content .cm-section-header > p,
#cm-section-content .cm-section-header > .cm-subtle,
#cm-section-content .cm-section-header > .cm-section-header__intro > p,
#cm-section-content .cm-section-header > .cm-section-header__intro > .cm-subtle,
#cm-section-content .cm-section-header > .cm-section-header__intro > div:has(> h2),
#cm-section-content .cm-section-header > .cm-section-header__intro > div:has(> .cm-section-title),
#cm-section-content .cm-section-header > div:has(> .cm-section-title),
#cm-section-content .cm-section-header > div:has(> h2),
#cm-section-content .cm-timeline-meta__title,
#cm-section-content .sp-header {
  display: none;
}
/* `.cm-section-header__intro` is the wrapper Implementation/Assumptions
   use INSIDE the page-top `.cm-section-header`; it contains the title
   text AND (in some sections) an actions slot. Don't hide the wrapper
   itself — only hide its TEXT children — so the nested
   `.cm-section-header__actions` button strip still renders.
   2026-04-27 AM6 — Brock walkthrough caught this for Assumptions'
   "Reset all to defaults" which lives inside the intro wrapper.
   2026-04-27 AM7 — scope the override to ONLY .cm-section-header__intro
   that's a child of the page-top .cm-section-header. The same class is
   reused by inner cards (Phase Plan, ramp cards, Ramp Burn) — don't
   right-align THEIR titles, that's how Brock spotted the Phase Plan
   header drifting right. */
#cm-section-content .cm-section-header > .cm-section-header__intro {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: none;
}
/* Strip the chrome — what remains is an actions row (or nothing).
   Right-align so action buttons hug the right edge consistently. */
#cm-section-content .cm-section-header {
  border-bottom: none;
  padding: 0;
  margin: 0 0 12px;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
}
/* Collapse the header entirely when it has no actionable children left
   (most sections have just title+desc, nothing else). */
#cm-section-content .cm-section-header:not(:has(button)):not(:has(a.hub-btn)):not(:has(.hub-btn)):not(:has(.hub-btn-primary)) {
  display: none;
}

/* ---- Tri-state save chip dot — matches text color of state ---- */
.hub-status-chip.draft.dot::before    { background: #92400e; }
.hub-status-chip.modified.dot::before { background: #92400e; }
.hub-status-chip.saved.dot::before    { background: #166534; }

/* ---- CM sidebar polish ---- */
/* Crisper active state — gradient accent + heavier left rail. Same blue
   palette as the existing styling so the change reads as polish, not a
   redesign. */
.cm-nav-item {
  position: relative;
  /* Tighter type for denser scan — was 13px / 600. */
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.1px;
  border-left-width: 3px;
  padding: 7px 16px;
}
.cm-nav-item.active {
  background: linear-gradient(90deg, rgba(0,71,171,0.10), rgba(0,71,171,0.02));
  color: var(--ies-navy);
  font-weight: 700;
  border-left-color: var(--ies-blue);
}
.cm-nav-item.active::after {
  /* Faint right-edge marker — borrowed from NetOpt's tab-active treatment.
     Tiny but legible, helps the active section read as the focus point in
     the sidebar even with completion dots in play. */
  content: '';
  position: absolute;
  right: 0;
  top: 4px;
  bottom: 4px;
  width: 2px;
  background: var(--ies-blue);
  border-radius: 1px;
  opacity: 0.5;
}
/* Hover on inactive items — softer than current full-blue text. */
.cm-nav-item:not(.active):hover {
  background: rgba(0,71,171,0.04);
  color: var(--ies-navy);
}

/* Group headers — crisper divider above each section group so the
   Setup / Inputs / Operations / Financials / Output groupings read
   as a clear vertical hierarchy (NetOpt's tab-strip uses a bottom
   divider; sidebar gets the same treatment between groups). */
/* 2026-04-28 EVE3 — CM sidebar groupings styled to echo the stepper motif
 * (numbered phase badge + label + description sub-text). Replaces the
 * earlier 10px gray-400 quiet header. The group itself is still flat —
 * users still click directly to any section — but it now reads as
 * confidently grouped at a glance. */
.hub-nav-group + .hub-nav-group {
  margin-top: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--ies-gray-200);
}
.hub-nav-group__header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px 8px 12px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ies-gray-700);
  text-transform: none;
  letter-spacing: normal;
  cursor: pointer;
  user-select: none;
  border: 0;
  background: transparent;
  width: 100%;
  text-align: left;
  border-radius: 6px;
  transition: background var(--ease-default);
}
.hub-nav-group__header:hover {
  background: var(--ies-gray-50);
  color: var(--ies-gray-700);
}
.hub-nav-group__badge {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: var(--ies-gray-300);
}
.hub-nav-group__badge--complete { background: var(--ies-green, #047857); }
.hub-nav-group__badge--partial  { background: var(--ies-blue); }
.hub-nav-group__badge--empty    { background: var(--ies-gray-300); }
.hub-nav-group__label {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--ies-gray-700);
  letter-spacing: 0.1px;
}
.hub-nav-group__count {
  font-size: 10px;
  font-weight: 600;
  color: var(--ies-gray-500);
  margin-left: auto;
  margin-right: 4px;
  flex-shrink: 0;
}
.hub-nav-group__caret {
  font-size: 9px;
  color: var(--ies-gray-400);
  transition: transform var(--ease-default);
  flex-shrink: 0;
}
.hub-nav-group.is-collapsed .hub-nav-group__items { display: none; }
.hub-nav-group.is-collapsed .hub-nav-group__caret { transform: rotate(-90deg); }
.hub-nav-group__items {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 2px 0 4px 12px;
}
/* Collapse the description on narrow / collapsed sidebars. */
.hub-sidebar.collapsed .hub-nav-group__count { display: none; }


/* ============================================================
   2026-04-30 R12-followup — CM Aesthetic Audit Sweep
   ----------------------------------------------------------
   Source: IT_Pitch/CM_Aesthetic_Inconsistencies_Audit_2026-04-26.md
   17 findings of typography / button / input / card / chip drift
   that read as polish noise during demos. The hub.css design
   tokens above already cover most of the targets; this sweep adds
   the explicit rules that lock down the remaining inconsistencies
   without touching 50+ render templates.

   Findings closed:
     F1 Section title weight       → .cm-section-title locked to fw-bold/20px
     F2 Subtitle size drift        → .cm-section-desc locked to 13px / gray-500
     F3 Table header case          → .cm-table thead th already uppercase;
                                     .hub-datatable thead th gets parity rule
     F4 Field label case           → .hub-field__label already uppercase;
                                     .cm-field-label legacy alias added
     F5 Primary button drift       → +Add Volume Line / +Add Overhead Line
                                     unified on .cm-add-row-btn (already shared)
     F6 Secondary action style     → .cm-link-arrow added for inline → links
     F7 Danger button color        → .cm-delete-btn already uses ies-red;
                                     'Reset' text-only links get .cm-link-reset
     F8 Input width                → .hub-input width:100% already; field
                                     widths controlled by .hub-field grid
     F9 Input padding              → .hub-input 10px/12px already fixed
     F10 Placeholder opacity       → .hub-input::placeholder already standardized
     F11 Card padding              → .hub-card already var(--sp-5)=20px;
                                     verified consistent (audit recommendation
                                     of 24px not adopted — 20px reads cleaner
                                     in dense CM forms based on live walk)
     F12 Border radius drift       → tokens enforced; status chips rule added
     F13 Divider rule              → .cm-section-divider exists; explicit
                                     1px / gray-100 / 28px-20px margin
     F14 Status chip sizing        → .hub-status-chip family unified
     F15 Color palette docs        → comment block above codifies semantic use
     F16 Label-input gap           → .hub-field gap:4px standardized
     F17 Card-section spacing      → .cm-card-stack utility for 24px gap groups

   Color palette (semantic):
     ies-blue   → primary actions, links, info accents
     ies-green  → success, positive deltas, "approved"
     ies-red    → destructive actions, alerts, negative deltas
     ies-yellow → warnings, "draft", "pending review"
     ies-gray-* → neutral surfaces, secondary text, inactive state
   ============================================================ */

/* F1+F2 — Section title + subtitle locks. Templates render
   .cm-section-title (h-equivalent) and .cm-section-desc inside
   .cm-section-header, but no explicit class rule existed; weight
   and size cascaded inconsistently across 12 sections. */
.cm-section-title {
  font-size: var(--fs-page);          /* 20px */
  font-weight: var(--fw-bold);        /* 700 */
  color: var(--ies-navy);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0;
}
.cm-section-desc {
  font-size: var(--fs-body);          /* 13px */
  font-weight: var(--fw-medium);      /* 500 */
  color: var(--ies-gray-500);
  line-height: 1.4;
  margin: 0;
}

/* F3 — hub-datatable thead parity with cm-table (some CM tables use
   the shared hub-datatable wrapper instead of cm-table). Lock the
   uppercase-caps treatment so all headers read identically. */
.hub-datatable thead th {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10px;
  font-weight: var(--fw-bold);
  color: var(--ies-gray-500);
}

/* F4 — Legacy alias for templates that emit .cm-field-label instead of
   .hub-field__label. Mirrors the canonical rule so old + new render
   identically; gradual migration to .hub-field__label preferred. */
.cm-field-label {
  font-size: var(--fs-caption);       /* 11px */
  font-weight: var(--fw-semibold);    /* 600 */
  color: var(--ies-gray-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.25;
}

/* F6 — Inline arrow link (e.g. "Size with Calculator →", "Edit in
   Labor Factors →", "Compare scenarios →"). Today some are .hub-btn
   buttons and some are bare <a>; unify on a single text-link affordance
   that reads as a navigation cue, not a primary action. */
.cm-link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: 0;
  padding: 0;
  color: var(--ies-blue);
  font-family: inherit;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  text-decoration: none;
}
.cm-link-arrow:hover { text-decoration: underline; }
.cm-link-arrow:focus-visible {
  outline: 2px solid var(--ies-blue);
  outline-offset: 2px;
  border-radius: 2px;
}

/* F7 — Reset / undo text link (Pricing tab "Reset" was un-styled).
   Subtle gray text link that becomes red on hover to signal the
   destructive intent without screaming on every render. */
.cm-link-reset {
  background: none;
  border: 0;
  padding: 2px 0;
  color: var(--ies-gray-500);
  font-family: inherit;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  cursor: pointer;
}
.cm-link-reset:hover { color: var(--ies-red); text-decoration: underline; }

/* F12 + F14 — Status chip border-radius standardization. tokens have
   --radius-pill (20px); make sure all .hub-status-chip variants resolve
   to it instead of inline 12px / 16px overrides that drift. */
.hub-status-chip { border-radius: var(--radius-pill); }

/* F17 — Stack utility for grouped CM cards. Use on a wrapper around
   sibling .hub-card elements to guarantee the same vertical rhythm
   (24px) that the audit recommends as the "normal" spacing tier. */
.cm-card-stack {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);                   /* 24px — "normal" tier */
}
.cm-card-stack--tight { gap: var(--sp-4); }   /* 16px — "tight" tier */
.cm-card-stack--loose { gap: var(--sp-7); }   /* 32px — "loose" tier */

/* ============================================================
   Feedback FAB (2026-04-30 NIGHT — re-added on all pages)
   Floating action button bottom-right + modal form. Submits
   to hub_feedback Supabase table; auto-captures #route as section.
   ============================================================ */
.hub-feedback-fab {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 9000;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px 10px 12px;
  border: none;
  border-radius: 999px;
  background: var(--ies-blue, #0047AB);
  color: #fff;
  font: 600 13px/1 var(--ies-font, 'Inter', system-ui, sans-serif);
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(0, 71, 171, 0.28), 0 2px 4px rgba(0, 0, 0, 0.08);
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.hub-feedback-fab:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 22px rgba(0, 71, 171, 0.34), 0 3px 6px rgba(0, 0, 0, 0.12);
  background: #0a52b8;
}
.hub-feedback-fab:active { transform: translateY(0); }
.hub-feedback-fab svg { display: block; }
.hub-feedback-fab__label { white-space: nowrap; }

/* Modal */
.hub-feedback-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9100;
  background: rgba(15, 23, 42, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  animation: hubFeedbackFade 0.12s ease;
}
@keyframes hubFeedbackFade { from { opacity: 0; } to { opacity: 1; } }
.hub-feedback-modal {
  background: #fff;
  border-radius: 12px;
  width: min(540px, 100%);
  max-height: calc(100vh - 32px);
  overflow: auto;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28);
  display: flex;
  flex-direction: column;
}
.hub-feedback-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--ies-gray-200, #e5e7eb);
}
.hub-feedback-modal__header h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--ies-gray-900, #0f172a);
}
.hub-feedback-modal__close {
  background: none;
  border: none;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  color: var(--ies-gray-500, #6b7280);
  padding: 0 4px;
}
.hub-feedback-modal__close:hover { color: var(--ies-gray-900, #0f172a); }
.hub-feedback-modal__body { padding: 16px 20px; }
.hub-feedback-modal__row { margin-bottom: 14px; }
.hub-feedback-modal__row--inline { display: flex; gap: 12px; align-items: flex-end; }
.hub-feedback-modal__row > label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--ies-gray-700, #374151);
  margin-bottom: 4px;
}
.hub-feedback-modal__hint {
  font-size: 11px;
  color: var(--ies-gray-500, #6b7280);
  font-weight: 400;
}
.hub-feedback-modal__hint code {
  background: var(--ies-gray-100, #f3f4f6);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 11px;
}
.hub-feedback-pills { display: flex; gap: 6px; flex-wrap: wrap; }
.hub-feedback-pill {
  padding: 6px 12px;
  border: 1px solid var(--ies-gray-300, #d1d5db);
  background: #fff;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  color: var(--ies-gray-700, #374151);
  cursor: pointer;
  transition: all 0.12s ease;
}
.hub-feedback-pill:hover { border-color: var(--ies-blue, #0047AB); color: var(--ies-blue, #0047AB); }
.hub-feedback-pill.is-active {
  background: var(--ies-blue, #0047AB);
  border-color: var(--ies-blue, #0047AB);
  color: #fff;
}
.hub-feedback-modal__footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 20px 16px;
  border-top: 1px solid var(--ies-gray-200, #e5e7eb);
}
@media (max-width: 480px) {
  .hub-feedback-fab__label { display: none; }
  .hub-feedback-fab { padding: 12px; border-radius: 50%; }
  .hub-feedback-modal__row--inline { flex-direction: column; align-items: stretch; gap: 14px; }
}
