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

/* Visually hidden but still readable by screen readers — used for
   aria-live announcements that have no visual presence of their own. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

html,
body,
#root {
  width: 100%;
  min-height: 100vh;
  /* Layout containers below (KPI rows, tab strips, tables, etc.) own their
     own horizontal scroll via overflow-x: auto — the page body itself must
     never scroll horizontally, at any viewport width. */
  overflow-x: hidden;
}

body {
  font-family: 'Inter', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  background: var(--color-bg-gradient);
}

/* ── Global scrollbar ─────────────────────────────────── */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-scrollbar-thumb) var(--color-scrollbar-track);
}

*::-webkit-scrollbar {
  width: 0.5rem;
  height: 0.5rem;
}

*::-webkit-scrollbar-track {
  background-color: var(--color-scrollbar-track);
  border-radius: 6.25rem;
}

*::-webkit-scrollbar-thumb {
  border: 0.03125rem solid var(--color-scrollbar-thumb-border);
  border-radius: 6.25rem;
  background: var(--color-scrollbar-thumb);
}

*::-webkit-scrollbar-button {
  display: none;
  width: 0;
  height: 0;
}

*::-webkit-scrollbar-corner {
  background: transparent;
}
/* Remove arrow buttons completely (all states) */
*::-webkit-scrollbar-button:single-button {
  display: none;
  width: 0;
  height: 0;
}

/* Also target directional buttons explicitly */
*::-webkit-scrollbar-button:vertical:start:decrement,
*::-webkit-scrollbar-button:vertical:end:increment,
*::-webkit-scrollbar-button:horizontal:start:decrement,
*::-webkit-scrollbar-button:horizontal:end:increment {
  display: none;
}

/* Optional: force no extra spacing */
*::-webkit-scrollbar-track-piece {
  margin: 0;
}

/* ── New-optimiser screens: low-chrome scrollbar ──────────────────────────
   The global bar above paints a permanently visible grey track, which reads as
   an OS artifact parked inside these layouts. Here the track is transparent, so
   nothing shows until there is something to scroll, and the thumb is the brand
   navy at low alpha — receding at rest, firming up on hover.

   `background-clip: content-box` with a transparent border is what floats the
   thumb inside its gutter; without it the pill touches both edges and reads as
   the same chunky bar in a different colour. The border must be transparent
   rather than a background-coloured stroke, otherwise it fringes wherever the
   scroll container sits on a tinted surface instead of white.

   Scoped to the new-optimiser page roots, plus the scope dropdowns' portaled
   list (`.sfs-select` rides along via SelectDropdown's className pass-through)
   since that renders under <body>, outside those roots. Everything else keeps
   the scrollbar it was designed against. The `*` above sets these properties on
   every element, so inheritance alone would not reach descendants here — hence
   the explicit descendant selectors. */
:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select),
:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select) * {
  scrollbar-width: thin;
  scrollbar-color: var(--color-scrollbar-thumb-soft) transparent;
}

:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select)::-webkit-scrollbar,
:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select) *::-webkit-scrollbar {
  width: 0.66667rem;
  height: 0.66667rem;
}

:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select)::-webkit-scrollbar-track,
:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select) *::-webkit-scrollbar-track {
  background: transparent;
  border: 0;
}

:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select)::-webkit-scrollbar-thumb,
:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select) *::-webkit-scrollbar-thumb {
  background-color: var(--color-scrollbar-thumb-soft);
  background-clip: content-box;
  border: 0.16667rem solid transparent;
  border-radius: var(--radius-pill);
  transition: background-color var(--motion-duration-normal) var(--motion-easing-standard);
}

:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select)::-webkit-scrollbar-thumb:hover,
:is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select) *::-webkit-scrollbar-thumb:hover {
  background-color: var(--color-scrollbar-thumb-soft-hover);
}

@media (prefers-reduced-motion: reduce) {
  :is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select)::-webkit-scrollbar-thumb,
  :is(.ss-page, .sc-page, .or-page, .oh-page, .cmp-page, .sfs-select) *::-webkit-scrollbar-thumb {
    transition: none;
  }
}

/* ── New-optimiser screens: keep the page scroller clear of the app chrome ──
   Every other screen scrolls inside its OWN container mounted below the header
   (see PerformanceOverview's `<CustomScrollbar height="100%">`), so its track
   starts under the chrome and the thumb is visible end to end. These five
   pages scroll with the app-level `<CustomScrollbar height="100vh">` in
   main.tsx, whose track spans the whole viewport — the top of the thumb ran
   underneath the fixed Navbar + AppTabs (and, on the three screens that have
   one, the sticky scope strip) and simply could not be seen. Insetting the
   track's top is the same result without giving these pages a second scroll
   container.

   `:has()` is what scopes it: the track is a SIBLING of the scrolled content,
   so which page is mounted can only be read from the shared root above both. */
:root {
  /* The one-line scope strip on Set Constraints / Results / Compare. The
     strips pin their own `min-height` to this same token, so the inset below
     and the thing it clears can't drift apart. */
  --app-scope-strip-h: 2.44444rem; /* 44px */
}

.csb-root:has(> .csb-content > :is(.oh-page, .ss-page)) .csb-track--v {
  top: var(--app-header-stack-h);
}

.csb-root:has(> .csb-content > :is(.sc-page, .or-page, .cmp-page)) .csb-track--v {
  top: calc(var(--app-header-stack-h) + var(--app-scope-strip-h));
}
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--space-10);
  background-color: var(--color-navbar);
  box-shadow: none;
  z-index: 1000;
}

.navbar-toolbar {
  height: 100%;
  padding: 0 var(--space-lg) 0 var(--space-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.navbar-brand-group {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.navbar-rapidroi-icon {
  display: flex;
  align-items: center;
}

.navbar-rapidroi-icon svg {
  /* Logo viewBox is tight (37 tall). Height drives the on-screen size;
     width scales automatically (~8:1 aspect). */
  height: 1.15rem;
  width: auto;
}

.navbar-separator {
  color: var(--color-white);
  font-size: var(--font-size-5xl);
  font-weight: var(--font-weight-light);
  opacity: 0.5;
  line-height: var(--line-height-none);
}

.navbar-unilever-icon {
  display: flex;
  align-items: center;
}

.navbar-unilever-icon svg {
  height: var(--space-12-4);
  width: auto;
}

.navbar-dots-icon,
.navbar-logout-icon {
  display: block;
  width: var(--space-lg);
  height: var(--space-lg);
  flex-shrink: 0;
}

.navbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.navbar-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-px);
}

.navbar-last-updated {
  font-size: var(--font-size-sm);
  color: var(--color-white);
  opacity: 1;
  font-family: var(--font-family-base);
  white-space: nowrap;
}

.navbar-data-source {
  font-size: var(--font-size-xs);
  color: var(--color-white);
  opacity: 1;
  text-decoration: underline;
  font-family: var(--font-family-base);
  white-space: nowrap;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.navbar-data-source:hover {
  opacity: 1;
}

.navbar-icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-white);
  opacity: 1;
  display: flex;
  align-items: center;
  padding: var(--space-0-8);
  border-radius: var(--radius-sm);
  transition: opacity var(--motion-duration-fast) ease;
}

.navbar-icon-btn:hover {
  opacity: 1;
}

.navbar-dots-wrap {
  position: relative;
  flex-shrink: 0;
}

.navbar-dots-dropdown {
  position: absolute;
  top: calc(100% + var(--space-sm));
  right: 0;
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: 0 var(--space-xs) var(--space-xl) var(--color-shadow-dropdown);
  min-width: var(--space-44);
  z-index: 2000;
  overflow: hidden;
  padding: var(--space-xs) 0;
}

.navbar-dots-item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--motion-duration-fast) ease;
}

.navbar-dots-item:hover {
  background: var(--color-bg-hover-light);
  color: var(--color-primary);
}

.navbar-dots-item-icon {
  width: var(--space-lg);
  height: var(--space-lg);
  flex-shrink: 0;
  color: var(--color-text-muted);
}

.navbar-dots-item:hover .navbar-dots-item-icon {
  color: var(--color-primary);
}

.navbar-dots-empty {
  display: block;
  padding: var(--space-sm) var(--space-md);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
}

.navbar-avatar-wrap {
  position: relative;
  flex-shrink: 0;
}

.navbar-avatar {
  width: var(--space-xxl);
  height: var(--space-xxl);
  border-radius: var(--radius-full);
  background: var(--color-white);
  color: var(--color-primary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  user-select: none;
  border: none;
  padding: 0;
  outline-offset: 2px;
}

.navbar-dropdown {
  position: absolute;
  top: calc(100% + var(--space-sm));
  right: 0;
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: 0 var(--space-xs) var(--space-xl) var(--color-shadow-dropdown);
  min-width: var(--space-52);
  z-index: 2000;
  overflow: hidden;
  padding: var(--space-xs) 0;
}

.navbar-dropdown-user {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
}

.navbar-dropdown-avatar {
  width: var(--space-xxl);
  height: var(--space-xxl);
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-white);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.navbar-dropdown-name {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  font-family: var(--font-family-display);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.navbar-dropdown-divider {
  height: var(--space-px);
  background: var(--color-border);
  margin: var(--space-xs) 0;
}

.navbar-dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  padding: var(--space-sm) var(--space-md);
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
  text-align: left;
  transition: background var(--motion-duration-fast) ease;
}

.navbar-dropdown-item:hover {
  background: var(--color-bg-hover-light);
  color: var(--color-error);
}

.ds-modal-backdrop {
  position: fixed;
  inset: 0;
  background: var(--color-backdrop-overlay);
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ds-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: 0 var(--space-xs) var(--space-xl) var(--color-shadow-dropdown);
  width: var(--space-28);
  max-width: 90vw;
}

.ds-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
}

.ds-modal-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  font-family: var(--font-family-display);
}

.ds-modal-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-body);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xs);
  border-radius: var(--radius-sm);
  transition: background var(--motion-duration-fast) ease;
}

.ds-modal-close svg {
  width: var(--space-lg);
  height: var(--space-lg);
  display: block;
}

.ds-modal-close:hover {
  background: var(--color-bg-hover-light);
}

.ds-modal-body {
  padding: var(--space-lg);
}

.ds-modal-body ul {
  margin: 0;
  padding-left: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.ds-modal-body li {
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-family: var(--font-family-base);
}

/* ── Responsive ───────────────────────────────────────────
   The toolbar is a single non-wrapping flex row (brand group +
   meta/actions). Below ~768px there isn't always room for the full
   "Last Updated: <date>" string alongside "Data Source" and the other
   actions. Rather than hiding "Last Updated" outright (it's useful,
   user-facing information, not purely decorative), let it shrink and
   truncate with an ellipsis instead — it stays visible at every width,
   just shorter when space is tight. The full text is still available via
   the element's aria-label for assistive tech.
   min-width: 0 is what actually lets this shrink: flex items default to
   min-width: auto (their content size), which would otherwise stop each
   container in the chain — .navbar-right, then .navbar-meta, then
   .navbar-last-updated itself — from ever shrinking below "Last Updated:
   <date>"'s full width, no matter how little room is left. It has to be
   set at every level of that chain, not just the innermost one: .navbar-
   right is .navbar-toolbar's own flex item, so if *it* doesn't shrink,
   .navbar-meta inside it never even gets asked to. The sibling icons/
   avatar (flex-shrink: 0 already) keep their size, so the flex algorithm
   gives .navbar-meta exactly whatever room remains, guaranteeing no
   overflow at any width. */
@media (max-width: 768px) {
  .navbar-toolbar {
    padding: 0 var(--space-md) 0 var(--space-sm);
  }

  .navbar-right {
    min-width: 0;
  }

  .navbar-meta {
    min-width: 0;
  }

  .navbar-last-updated {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

@media (max-width: 480px) {
  .navbar-data-source {
    display: none;
  }

  .navbar-right {
    gap: var(--space-sm);
  }
}
.primary-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  height: var(--space-xxl); /* 2rem */
  padding: 0 var(--space-lg);
  letter-spacing: var(--letter-spacing-wider);
  cursor: pointer;
  transition: background-color var(--motion-duration-normal) ease;
}

.primary-btn--full {
  width: 100%;
}

.primary-btn:hover:not(:disabled) {
  background-color: var(--color-primary-hover);
}

.primary-btn:disabled {
  background-color: var(--color-btn-disabled-bg);
  color: var(--color-btn-disabled-text);
  cursor: not-allowed;
}
.input-wrapper {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.input-field-inner {
  position: relative;
  display: flex;
  align-items: center;
}

.input-field {
  width: 100%;
  height: var(--space-12); /* 3rem */
  padding: var(--space-lg) var(--space-md) var(--space-xs);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-input);
  background-color: var(--color-input-bg);
  font-size: var(--font-size-base);
  color: var(--color-text-heading);
  outline: none;
  transition: border-color var(--motion-duration-normal) ease;
}

/* floating label */
.input-label {
  position: absolute;
  left: var(--space-md);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--font-size-base);
  color: var(--color-input-label);
  pointer-events: none;
  transition:
    top var(--motion-duration-fast) ease,
    font-size var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
}

.input-field:focus ~ .input-label,
.input-field.has-value ~ .input-label {
  top: calc(var(--space-px) * -8);
  transform: none;
  font-size: var(--font-size-2xs);
  color: var(--color-black);
  background: var(--color-input-bg);
  padding: 0 var(--space-xs);
  line-height: var(--line-height-none);
  z-index: 1;
  margin-left: calc(var(--space-xs) * -1);
}

.input-field:focus {
  border-color: var(--color-input-border-focus);
}

/* error state */
.input-wrapper--error .input-field {
  border-color: var(--color-error);
}
.input-wrapper--error .input-label {
  color: var(--color-error);
}

.input-helper {
  font-size: var(--font-size-sm);
  color: var(--color-error);
  padding-left: var(--space-md);
}

/* password toggle */
.visibility-btn {
  position: absolute;
  right: var(--space-sm);
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--space-xs);
  color: var(--color-visibility-icon);
  display: flex;
  align-items: center;
}

.visibility-btn svg {
  width: var(--space-lg); /* 1.5rem — close to original 1.1rem icon size */
  height: var(--space-lg);
}

/* autofill override — also fires animationstart so JS can detect the fill */
@keyframes onAutofillStart { from { } }

.input-field:-webkit-autofill,
.input-field:-webkit-autofill:hover,
.input-field:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--color-text-heading);
  box-shadow: 0 0 0 62.5rem var(--color-input-bg) inset;
  transition: background-color 5000s ease-in-out 0s;
  animation-name: onAutofillStart;
  animation-duration: 1ms;
}

/* float the label when the browser has autofilled the field */
.input-field:-webkit-autofill ~ .input-label {
  top: calc(var(--space-px) * -6);
  transform: none;
  font-size: var(--font-size-2xs);
  color: var(--color-black);
  background: var(--color-input-bg);
  padding: 0 var(--space-xs);
  line-height: var(--line-height-none);
  z-index: 1;
  margin-left: calc(var(--space-xs) * -1);
}
.speed-lines {
  display: block;
  overflow: visible; /* streaks + smoke fly past the viewBox edges */
}

/* Colours (var() isn't valid in SVG presentation attributes). */
.sl-grad-start {
  stop-color: var(--color-logo-bar-start);
}
.sl-grad-end {
  stop-color: var(--color-logo-bar-end);
}
.sl-track rect {
  fill: var(--color-logo-bar-start);
  opacity: 0.14;
}
.sl-smoke {
  fill: var(--color-loader-smoke);
}

/* ── Speed streaks: grow from the left, hold, whoosh off right + fade ──── */
.sl-bar {
  transform-box: fill-box;
  transform-origin: left center;
  filter: drop-shadow(0 0 1.5px var(--color-logo-bar-start));
  will-change: transform, opacity;
  animation: sl-streak 0.9s cubic-bezier(0.4, 0, 0.15, 1) infinite;
}
.sl-bar--1 {
  animation-delay: 0s;
}
.sl-bar--2 {
  animation-delay: 0.13s;
}
.sl-bar--3 {
  animation-delay: 0.26s;
}

@keyframes sl-streak {
  0% {
    transform: translateX(0) scaleX(0.05);
    opacity: 0;
  }
  22% {
    transform: translateX(0) scaleX(1);
    opacity: 1;
  }
  48% {
    transform: translateX(0) scaleX(1);
    opacity: 1;
  }
  100% {
    transform: translateX(18px) scaleX(0.12);
    opacity: 0;
  }
}

/* ── Exhaust smoke: slower, out of sync, so it lingers. ────────────────── */
.sl-smoke {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  will-change: transform, opacity;
  animation: sl-smoke 1.7s ease-out infinite;
}
.sl-smoke--1 {
  animation-delay: 0.15s;
}
.sl-smoke--2 {
  animation-delay: 0.7s;
}
.sl-smoke--3 {
  animation-delay: 1.15s;
}

@keyframes sl-smoke {
  0% {
    transform: translate(0, 0) scale(0.4);
    opacity: 0;
  }
  25% {
    opacity: 0.4;
  }
  100% {
    transform: translate(-9px, -6px) scale(1.7);
    opacity: 0;
  }
}

/* Reduced-motion: hold the mark fully drawn, drop the smoke. */
@media (prefers-reduced-motion: reduce) {
  .sl-bar {
    animation: none;
    transform: none;
    opacity: 1;
  }
  .sl-smoke-group {
    display: none;
  }
}
.auth-loader-container {
  position: fixed;
  inset: 0;
  /* Match the login screen (tokens: --color-hero-gradient / --color-bg-cream). */
  background: var(--color-hero-gradient), var(--color-bg-cream);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

/* Wordmark + animated bars, laid out as the RAPID ROI lockup. */
.auth-loader-lockup {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.auth-loader-word {
  font-family: "Manrope", var(--font-family-base);
  font-size: 2.5rem; /* ~40px */
  font-weight: 400;
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--color-text-heading);
  white-space: nowrap;
}

.auth-loader-mark {
  width: 5rem; /* bars sized to sit beside the ~40px wordmark */
  height: auto;
}

@media (max-width: 480px) {
  .auth-loader-word {
    font-size: 1.9rem;
  }
  .auth-loader-mark {
    width: 4rem;
  }
}
.toast-container {
  position: fixed;
  top: var(--space-lg);
  right: var(--space-lg);
  z-index: 10000;
  pointer-events: none;
}

.toast {
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-md) var(--space-lg);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  display: flex;
  /* flex-start, not center: a multi-line message (e.g. one line per saved
     combination) would otherwise center the icon against the whole block's
     height, floating it away from the title/first line. Identical to
     `center` for the common single-line case, so nothing else changes. */
  align-items: flex-start;
  gap: var(--space-md);
  min-width: 320px;
  max-width: 500px;
  pointer-events: all;
  animation: toast-slide-in var(--motion-duration-normal) ease-out;
}

.toast--icon-centered {
  align-items: center;
}

.toast--success {
  background: var(--color-success, #2E7D32);
}

.toast--error {
  background: var(--color-error-msg-bg, #9C2121);
}

.toast--warning {
  background: var(--color-warning, #ED6C02);
}

.toast--info {
  background: var(--color-info, #1565C0);
}

@keyframes toast-slide-in {
  from {
    transform: translateY(-100%);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.toast-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-xl);
  height: var(--space-xl);
  background: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  flex-shrink: 0;
  color: white;
}

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

/* Matches `.toast-message`'s color/size so the title reads as the same
   banner, not a differently-styled heading — bumped to semibold (instead of
   message's medium) is enough on its own to read as the title. Never had a
   rule of its own before, so it fell through to the browser's default block
   text (dark, and larger than the message beneath it). */
.toast-title {
  font-size: var(--font-size-sm);
  color: white;
  line-height: var(--line-height-normal);
  font-weight: var(--font-weight-semibold);
}

.toast-message {
  font-size: var(--font-size-sm);
  color: white;
  line-height: var(--line-height-normal);
  font-weight: var(--font-weight-medium);
  /* Honors literal "\n"s as line breaks (e.g. one line per saved
     combination) while still collapsing runs of spaces/tabs like normal
     text — a plain single-line message renders exactly as before. */
  white-space: pre-line;
  display: block;
}

.toast-close {
  background: none;
  border: none;
  color: white;
  cursor: pointer;
  padding: 0;
  width: var(--space-5);
  height: var(--space-5);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background 0.15s;
  flex-shrink: 0;
  opacity: 0.8;
}

.toast-close:hover {
  background: rgba(255, 255, 255, 0.15);
  opacity: 1;
}
.login-page {
  min-height: 100vh;
  /* Figma 1284-39670: a subtle teal→white→purple→pink gradient over the cream
     base (tokens: --color-hero-gradient / --color-bg-cream). */
  background: var(--color-hero-gradient), var(--color-bg-cream);
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}

/* session-expired notice bar — sits below the fixed navbar, above the
   decorative background images, with a compact centered message + button. */
.login-auth-expired-banner {
  position: relative;
  z-index: 3;
  margin-top: var(--space-10);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-lg);
  background: var(--color-warning-bg);
  border-bottom: var(--space-px) solid var(--color-warning-border);
}

.login-auth-expired-banner p {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-family: var(--font-family-base);
}

/* background SVG overlay */
.login-bg-svg {
  position: absolute;
  /* inset:0 (not top + height:100%) so it fills reliably in Safari/WebKit,
     which resolves percentage heights against a min-height container
     differently than Chrome. */
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  opacity: 0.45;
  z-index: 0;
}

/* UlLS decorative image — left side */
.login-ulls-img {
  position: absolute;
  left: 0;
  top: 54%;
  transform: translateY(-50%);
  height: var(--space-70);
  max-width: var(--space-52);
  object-fit: contain;
  pointer-events: none;
  opacity: 0.5;
  z-index: 1;
}

/* main content area — vertically centered below navbar */
.login-content {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 1;
}

/* card — matches expected width */
.login-card {
  width: 100%;
  max-width: var(--space-25);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0;
}

/* "Welcome to" */
.welcome-text {
  font-size: var(--font-size-5xl);
  color: var(--color-text-heading);
  font-weight: var(--font-weight-semilight);
  font-family: var(--font-family-base);
  text-align: center;
  margin: 0 0 var(--space-0-4);
}

/* "RapidROI" */
.rapid-logo {
  width: 100%;
  max-width: var(--space-25); /* fill the 400px login card */
  height: auto;
  display: block;
  margin: var(--space-sm) auto;
  opacity: 1;
}

/* "Unified hub for spend optimization" */
.brand-subtitle {
  font-size: var(--font-size-3xl);
  color: var(--color-text-subtitle);
  text-align: center;
  margin: var(--space-xs) 0 var(--space-15);
  font-family: var(--font-family-base);
}

/* SSO button wrapper */
.sso-wrapper {
  width: 100%;
  margin-bottom: var(--space-5);
}

/* Or divider — wider than card to match expected */
.or-divider {
  display: flex;
  align-items: center;
  width: 115%;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

.divider-line {
  flex: 1;
  height: var(--space-px);
  background-color: var(--color-divider);
  display: block;
}

.or-text {
  color: var(--color-divider-text);
  font-size: var(--font-size-base);
  white-space: nowrap;
  line-height: var(--line-height-none);
}

/* form fields */
.login-form {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-3-5);
}

/* transparent inputs on login page */
.login-form .input-field {
  background-color: transparent;
  border-color: var(--color-primary);
}

/* label background on login must blend with gradient — no color change */
.login-form .input-field:focus ~ .input-label,
.login-form .input-field.has-value ~ .input-label,
.login-form .input-field:-webkit-autofill ~ .input-label {
  background: var(--color-login-input-bg);
  color: var(--color-input-label);
}

.login-form .input-field:-webkit-autofill,
.login-form .input-field:-webkit-autofill:hover,
.login-form .input-field:-webkit-autofill:focus {
  box-shadow: 0 0 0 62.5rem transparent inset;
  -webkit-text-fill-color: var(--color-text-heading);
}

/* forgot password */
.forgot-password {
  width: 100%;
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-1-5);
}

.forgot-link {
  font-size: var(--font-size-sm);
  color: var(--color-text-link);
  cursor: pointer;
  text-decoration: none;
}

.forgot-link:hover {
  opacity: 0.75;
}

.error-text {
  font-size: var(--font-size-sm);
  color: var(--color-error);
  text-align: center;
  margin: calc(var(--space-0-4) * -1) 0 0;
}

/* ── Forgot Password button ─────────────────────────── */
.forgot-password .forgot-link {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

/* ── Reset Password Modal ────────────────────────────── */
.fp-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.fp-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: 0 var(--space-sm) var(--space-xxl) rgba(0, 0, 0, 0.2);
  width: min(var(--space-26), 92vw);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.fp-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-lg) var(--space-xl);
  border-bottom: var(--space-px) solid var(--color-border);
}

.fp-modal-title {
  font-size: var(--font-size-lg);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  margin: 0;
}

.fp-modal-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--font-size-base);
  padding: var(--space-xs);
  border-radius: var(--radius-sm);
  line-height: 1;
}

.fp-modal-close:hover {
  color: var(--color-text-body);
}

.fp-modal-body {
  padding: var(--space-xl);
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.fp-modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-lg) var(--space-xl);
  border-top: var(--space-px) solid var(--color-border);
}

.fp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-semibold);
  padding: var(--space-xs) var(--space-xl);
  cursor: pointer;
  border: var(--space-px) solid transparent;
  transition: opacity var(--motion-duration-fast) ease;
}

.fp-btn--outline {
  background: var(--color-white);
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.fp-btn--outline:hover {
  background: var(--color-bg-card-alt);
}

.fp-btn--primary {
  background: var(--color-primary);
  color: var(--color-white);
  border-color: var(--color-primary);
}

.fp-btn--primary:hover {
  opacity: 0.88;
}

.fp-btn--primary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.no-access-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background-color: #f0f2f5;
}

.no-access-content {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.no-access-card {
  background: #ffffff;
  border-radius: 12px;
  padding: 3rem 4rem;
  max-width: 600px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}

.no-access-icon {
  width: 56px;
  height: 56px;
}

.no-access-icon svg {
  width: 100%;
  height: 100%;
}

.no-access-message {
  color: #1a237e;
  font-size: 1rem;
  line-height: 1.6;
  text-align: center;
  margin: 0;
}

.no-access-link {
  color: #1a237e;
  font-weight: 600;
  text-decoration: none;
}

.no-access-link:hover {
  text-decoration: underline;
}

.no-access-btn {
  margin-top: 0.25rem;
  padding: 0.55rem 1.5rem;
  background: #1a237e;
  color: #ffffff;
  border: none;
  border-radius: 6px;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}

.no-access-btn:hover {
  background: #283593;
}
.fb-wrapper {
  position: sticky;
  top: var(--space-10);
  /* 2.75rem — below fixed navbar */
  z-index: 100;
  background: var(--color-bg-card);
  border-bottom: var(--space-px) solid var(--color-border);
}

/* ── Strip ──────────────────────────────────────────────── */
.fb-strip {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-1-5) var(--space-7);
  min-height: var(--space-10);
}

/* ── Filters button ─────────────────────────────────────── */
.fb-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-xs) var(--space-md);
  border: var(--space-px) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-bg-card);
  color: var(--color-black);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  white-space: nowrap;
  font-family: var(--font-family-display);
  transition:
    background var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
}

.fb-btn svg path {
  fill: var(--color-primary);
  fill-opacity: 1;
}

.fb-filter-icon {
  width: var(--space-3-5);
  height: var(--space-3-5);
  object-fit: contain;
}

/* ── No-filters error state ──────────────────────────────── */
.fb-no-filters {
  padding: var(--space-4);
  color: var(--color-error);
}

/* ── Inline filter-load-error message in strip ───────────── */
.fb-unavailable-msg {
  font-size: var(--font-size-sm);
  font-style: italic;
  color: var(--color-text-muted);
}

/* ── Calendar popup (position driven by JS via CSS custom props) */
.fb-monthrange-popup {
  position: fixed;
  top: var(--fb-cal-top, 0px);
  left: var(--fb-cal-left, 0px);
  z-index: 9999;
}

.fb-btn--active,
.fb-btn:hover {
  background: var(--color-grey);
  color: var(--color-black);
}

.fb-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

.fb-btn--active svg path,
.fb-btn:hover svg path {
  fill: var(--color-white);
}

/* ── Chips ──────────────────────────────────────────────── */
.fb-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
}

.fb-chips--loading {
  opacity: 0.7;
  pointer-events: none;
}

.fb-chip {
  position: relative;
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-weight: var(--font-weight-regular);
  font-family: var(--font-family-base);
  cursor: pointer;
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-xs);
  transition: background var(--motion-duration-fast) ease;
}

.fb-chip:hover {
  background: var(--color-bg-hover-light);
}

.fb-chip-extra {
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
}

.fb-chip-tooltip {
  display: none;
  position: absolute;
  top: calc(100% + var(--space-1-5));
  left: 0;
  z-index: 300;
  background: #2d1b6b;
  color: #fff;
  border-radius: var(--radius-sm);
  padding: var(--space-sm) var(--space-md);
  min-width: var(--space-40);
  flex-direction: column;
  gap: var(--space-xs);
  white-space: nowrap;
  box-shadow: 0 var(--space-xs) var(--space-md) rgba(0, 0, 0, 0.28);
  pointer-events: none;
}

.fb-chip:hover .fb-chip-tooltip {
  display: flex;
}

.fb-chip-tooltip-item {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-normal);
  color: #fff;
}

.fb-chip-value {
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  display: inline-block;
  max-width: var(--space-40);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

.fb-chip-value--none {
  color: var(--color-text-muted, #94a3b8);
  font-weight: var(--font-weight-regular);
  font-style: italic;
}

.fb-chip-sep {
  font-size: var(--font-size-sm);
  color: var(--color-filter-pipe);
  padding: 0 var(--space-xs);
  user-select: none;
}

/* ── Backdrop ───────────────────────────────────────────── */
.fb-backdrop {
  position: fixed;
  inset: 0;
  z-index: 99;
}

/* ── Panel ──────────────────────────────────────────────── */
.fb-panel {
  --fb-panel-left-w: var(--space-31); /* 18rem — left column width */
  position: absolute;
  top: 100%;
  left: var(--space-5);
  z-index: 200;
  background: var(--color-bg-card);
  box-shadow: 0 var(--space-sm) var(--space-xxl) var(--color-shadow-panel);
  width: auto;
  display: grid;
  grid-template-columns: var(--fb-panel-left-w) var(--space-22);
  grid-template-rows: 1fr auto;
  height: var(--space-22);
  overflow: hidden;
  border-top: var(--space-px) solid var(--color-border);
}

.fb-panel--collapsed {
  width: var(--fb-panel-left-w);
  grid-template-columns: 1fr;
}

/* ── Left column ────────────────────────────────────────── */
.fb-panel-left {
  grid-row: 1;
  grid-column: 1;
  border-right: var(--space-px) solid var(--color-border);
  overflow: hidden;
  min-height: 0;
  height: 100%;
}

.fb-panel-left-content {
  padding: var(--space-xs) var(--space-md);
}

.fb-group-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-3-5) var(--space-5);
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--font-size-base);
  color: var(--color-primary);
  text-align: left;
  width: 100%;
  font-family: var(--font-family-display);
  border-radius: var(--radius-sm);
  margin-block: var(--space-xs);
  transition: background var(--motion-duration-fast) ease;
}

.fb-group-item:hover {
  background: var(--color-bg-hover-light);
  border-radius: var(--radius-sm);
  margin-block: var(--space-xs);
  font-weight: var(--font-weight-semibold);
}

.fb-group-item--active {
  background: var(--color-bg-hover-light);
  border-radius: var(--radius-sm);
  font-weight: var(--font-weight-semibold);
  margin-block: var(--space-xs);
}

.fb-group-divider {
  height: var(--space-px);
  background: var(--color-filter-border);
  margin: 0;
}

/* ── Right column ───────────────────────────────────────── */
.fb-panel-right {
  grid-row: 1;
  grid-column: 2;
  overflow: hidden;
  min-height: 0;
  height: 100%;
}

.fb-panel-right-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-lg) var(--space-5);
}

/* ── Search ─────────────────────────────────────────────── */
.fb-search-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-md);
  background: var(--color-bg-card);
  transition: border-color var(--motion-duration-fast) ease;
  max-width: var(--space-60);
}

.fb-search-wrap:focus-within {
  border-color: var(--color-primary);
}

.fb-search {
  border: none;
  outline: none;
  font-size: var(--font-size-base);
  color: var(--color-primary);
  width: 100%;
  background: transparent;
  font-family: var(--font-family-base);
}

/* ── Options list ───────────────────────────────────────── */
.fb-options {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.fb-options-divider {
  height: var(--space-px);
  background: var(--color-border);
  margin: var(--space-px) 0;
}

.fb-option {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  font-size: var(--font-size-base);
  color: var(--color-primary);
  cursor: pointer;
  font-family: var(--font-family-display);
}

.fb-option:hover,
.fb-option:has(input:checked) {
  font-weight: var(--font-weight-semibold);
}

.fb-option input[type="radio"],
.fb-option input[type="checkbox"] {
  accent-color: var(--color-primary);
  width: var(--space-md);
  height: var(--space-md);
  cursor: pointer;
  flex-shrink: 0;
}

.fb-no-results {
  font-size: var(--font-size-sm);
  color: var(--color-text-placeholder);
  margin: 0;
}

.fb-option-highlight {
  background: color-mix(in srgb, var(--color-primary) 15%, transparent);
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--space-0-5);
}

/* ── Date range ─────────────────────────────────────────── */
.fb-daterange {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.fb-date-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.fb-date-label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary);
}

.fb-date-input {
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-md);
  font-size: var(--font-size-base);
  color: var(--color-primary);
  background: var(--color-bg-card);
  outline: none;
  cursor: pointer;
  width: 100%;
  font-family: var(--font-family-base);
  transition: border-color var(--motion-duration-fast) ease;
}

.fb-date-input:focus {
  border-color: var(--color-border-strong);
}

.fb-date-summary {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  margin: 0;
  padding-top: var(--space-sm);
  border-top: var(--space-px) solid var(--color-border);
}

/* ── Month range trigger & popup ────────────────────────── */
.fb-monthrange-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.fb-monthrange-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2-5);
  padding: var(--space-1-5) var(--space-lg);
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-sm);
  background: var(--color-bg-card);
  color: var(--color-primary);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: background var(--motion-duration-fast) ease;
}

.fb-monthrange-trigger:hover {
  background: var(--color-bg-hover-light);
}

.fb-monthrange-popup {
  position: fixed;
  z-index: 9999;
  transform: translateX(-50%);
}

/* ── Footer ─────────────────────────────────────────────── */
.fb-panel-footer {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-3-5);
  position: relative;
}

.fb-panel-footer::before,
.fb-panel-footer::after {
  content: "";
  position: absolute;
  top: 0;
  height: var(--space-px);
  background: var(--color-filter-border);
}

/* line under the left column */
.fb-panel-footer::before {
  left: var(--space-md);
  width: calc(var(--fb-panel-left-w) - (var(--space-md) * 2));
}

/* line under the right column */
.fb-panel-footer::after {
  left: calc(var(--fb-panel-left-w) + var(--space-md));
  right: var(--space-md);
}

.fb-reset-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  background: none;
  border: var(--space-px) solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-primary);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  padding: var(--space-1-5) var(--space-md);
  font-family: var(--font-family-display);
  transition: border-color var(--motion-duration-fast) ease;
}

.fb-reset-btn:hover:not(:disabled) {
  border-color: var(--color-border);
}

.fb-reset-btn:disabled {
  color: var(--color-text-placeholder);
  cursor: not-allowed;
  opacity: 0.6;
}

.fb-cancel-btn {
  background: none;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-base);
  color: var(--color-primary);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: border-color var(--motion-duration-fast) ease;
}

.fb-cancel-btn:hover:not(:disabled) {
  border-color: var(--color-border-strong);
}

.fb-cancel-btn:disabled {
  color: var(--color-text-placeholder);
  cursor: not-allowed;
  opacity: 0.6;
}

.fb-apply-btn {
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-xl);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: background var(--motion-duration-fast) ease;
}

.fb-apply-btn:hover:not(:disabled) {
  background: var(--color-primary-hover);
}

.fb-apply-btn:disabled {
  background: var(--color-border);
  color: var(--color-text-placeholder);
  cursor: not-allowed;
  opacity: 0.6;
}

/* ── Options loading overlay ────────────────────────────── */
.fb-options-loading {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  padding: var(--space-md) 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.fb-options-spinner {
  display: inline-block;
  width: var(--space-3-5);
  height: var(--space-3-5);
  border: var(--space-0-5) solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: fb-spin var(--motion-duration-spin-fast) linear infinite;
  flex-shrink: 0;
}

/* ── Sidebar group spinner (dependent filters updating) ─── */
.fb-group-spinner {
  display: inline-block;
  width: var(--space-md);
  height: var(--space-md);
  border: var(--space-0-5) solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: fb-spin var(--motion-duration-spin-fast) linear infinite;
  flex-shrink: 0;
}

.fb-group-item--updating,
.fb-group-item--disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.fb-group-item--disabled:hover {
  background: none;
  font-weight: var(--font-weight-regular);
}

/* ── Apply button spinner ───────────────────────────────── */
.fb-apply-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
}

.fb-apply-spinner {
  display: inline-block;
  width: var(--space-md);
  height: var(--space-md);
  border: var(--space-0-5) solid var(--color-overlay-white-faint);
  border-top-color: var(--color-white);
  border-radius: 50%;
  animation: fb-spin var(--motion-duration-spin-fast) linear infinite;
  flex-shrink: 0;
}

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

/* ── Options fade while updating ───────────────────────── */
.fb-panel-right .fb-options,
.fb-panel-right .fb-search-wrap,
.fb-panel-right .fb-daterange {
  transition: opacity var(--motion-duration-fade) ease;
}

.fb-panel-right:has(.fb-options-loading) .fb-options,
.fb-panel-right:has(.fb-options-loading) .fb-search-wrap {
  opacity: 0.35;
  pointer-events: none;
}

/* ── Error chip value ────────────────────────────────────── */
.fb-chip-value--error {
  color: var(--color-error);
  font-weight: var(--font-weight-semibold);
}

/* ── Group item icons wrapper ────────────────────────────── */
.fb-group-item-icons {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  flex-shrink: 0;
}

/* ── Error icon in left sidebar ──────────────────────────── */
.fb-group-error-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-md);
  height: var(--space-md);
  border-radius: 50%;
  border: var(--space-px) solid var(--color-error);
  color: var(--color-error);
  font-size: 10px;
  font-weight: var(--font-weight-bold);
  line-height: 1;
  flex-shrink: 0;
  cursor: default;
}

/* ── Error banner in right panel ─────────────────────────── */
.fb-error-banner {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  border: var(--space-px) solid var(--color-error);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--color-error) 8%, transparent);
  color: var(--color-error);
  font-size: var(--font-size-sm);
  line-height: 1.4;
}

.fb-error-banner-icon {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
}

/* ── Imported icon sizes ─────────────────────────────────── */
.fb-chevron-right-icon {
  display: block;
  width: var(--space-lg);
  height: var(--space-lg);
  flex-shrink: 0;
}

.fb-calendar-icon {
  display: block;
  width: var(--space-3-5);
  height: var(--space-3-5);
  flex-shrink: 0;
}

/* ── Responsive ───────────────────────────────────────────
   The filter panel's two columns (group list + options) use fixed rem
   widths sized for desktop and together exceed a mobile viewport. Stack
   them into a single scrollable column instead, capped to the viewport
   so the panel never pushes the page into horizontal scroll. */
@media (max-width: 768px) {
  .fb-panel {
    grid-template-columns: 1fr;
    /* minmax(0, 1fr) — not a fixed max-height per row — is required here:
       CSS Grid sizes `auto` tracks (the footer) from their own content
       FIRST, then splits whatever's left between `1fr` tracks. A previous
       version instead gave .fb-panel-left/.fb-panel-right an independent
       `max-height: 40vh` each (80vh combined) with `grid-template-rows:
       auto auto auto` — exactly matching this panel's own 80vh cap, so
       once either list had enough options to actually reach 40vh, there
       was zero room left for the footer row, which .fb-panel's own
       `overflow: hidden` (below) then silently clipped — the Apply/Cancel
       buttons weren't just hard to reach, they were never rendered
       on-screen at all. */
    grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) auto;
    width: min(var(--fb-panel-left-w), 92vw);
    max-width: 92vw;
    height: auto;
    max-height: 80vh;
  }

  .fb-panel--collapsed {
    width: min(var(--fb-panel-left-w), 92vw);
  }

  .fb-panel-left {
    grid-row: 1;
    grid-column: 1;
    border-right: none;
    border-bottom: var(--space-px) solid var(--color-border);
    /* min-height: 0 overrides the grid-item default of min-height: auto
       (which otherwise refuses to shrink below content size, defeating
       the minmax(0, 1fr) row above) so this pane actually shrinks to its
       allotted share of space and scrolls internally instead. */
    min-height: 0;
    overflow-y: auto;
  }

  .fb-panel-right {
    grid-row: 2;
    grid-column: 1;
    min-height: 0;
    overflow-y: auto;
  }

  .fb-panel-footer {
    grid-row: 3;
    grid-column: 1;
  }

  .fb-panel-footer::before,
  .fb-panel-footer::after {
    display: none;
  }
}

.fb-reset-icon {
  display: inline-block;
  width: var(--space-md);
  height: var(--space-md);
  vertical-align: middle;
}
.mrcp {
  --mrcp-width: var(--space-34);        /* 20rem = 320px */
  --mrcp-month-size: var(--space-15);   /* 3.75rem = 60px — month circle button */
  background: var(--color-bg-card);
  border-radius: var(--radius-lg);
  padding: var(--space-md) var(--space-5) var(--space-sm);
  width: var(--mrcp-width);
  max-width: calc(100vw - var(--space-md) * 2);
  /* Belt-and-suspenders for a viewport shorter than the popup itself (rare,
     but FilterBar's flip-above-or-below positioning can't place 100% of a
     too-tall popup on-screen either way): let the month grid scroll
     internally instead, keeping Done always reachable rather than clipped
     off with no way back to it — background scroll is locked while the
     filter panel is open, so there'd otherwise be no way to reach it. */
  max-height: calc(100vh - var(--space-md) * 2);
  box-shadow: 0 var(--space-xs) var(--space-5) var(--color-shadow-popover);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* ── Year navigation ──────────────────────────────────── */
.mrcp__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

.mrcp__nav {
  width: var(--space-7); /* 28px */
  height: var(--space-7);
  border: none;
  background: none;
  color: var(--color-primary);
  font-size: var(--font-size-3xl); /* closest token: 1.2rem ≈ nav arrow size */
  line-height: var(--line-height-none);
  cursor: pointer;
  border-radius: var(--radius-input); /* 6px */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background var(--motion-duration-fast);
}

.mrcp__nav:hover {
  background: var(--color-bg-hover-light);
}

.mrcp__year {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-input);
  padding: var(--space-xs) var(--space-5);
  min-width: var(--space-20);
  width: var(--space-20);
  text-align: center;
  font-family: var(--font-family-display);
  background: var(--color-bg-card);
  outline: none;
  cursor: text;
}

/* hide browser number spinners */
.mrcp__year::-webkit-inner-spin-button,
.mrcp__year::-webkit-outer-spin-button {
  appearance: none;
  margin: 0;
}

.mrcp__year[type="number"] {
  appearance: textfield;
  -moz-appearance: textfield;
}

.mrcp__year:focus {
  border-color: var(--color-primary);
}

/* ── Month grid ───────────────────────────────────────── */
.mrcp__month-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-sm);
  justify-items: center;
  /* Shrinks and scrolls internally, rather than being clipped, once .mrcp's
     max-height clamp kicks in — min-height: 0 overrides the flex-item
     default (min-height: auto), which otherwise refuses to shrink below
     content size and defeats overflow-y here. */
  overflow-y: auto;
  min-height: 0;
}

.mrcp__month {
  /* min(…, 100%) instead of a fixed size — lets the circle shrink with its
     grid cell when .mrcp's viewport max-width clamp kicks in on a narrow
     screen, instead of overflowing it. aspect-ratio keeps it circular at
     any resulting width. */
  width: min(var(--mrcp-month-size), 100%);
  aspect-ratio: 1;
  border-radius: var(--radius-full); /* 50% circle */
  border: none;
  background: var(--color-white); /* #e8eaf6 — lavender default */
  color: var(--color-primary);
  font-size: var(--font-size-base); /* ~13px */
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  transition:
    background var(--motion-duration-fast),
    color var(--motion-duration-fast);
  font-family: var(--font-family-display);
}

.mrcp__month:hover:not(:disabled) {
  background: var(--color-primary); /* #c5cae9 */
  color: var(--color-white);
}

.mrcp__month--selected {
  background: var(--color-primary);
  color: var(--color-white);
}

.mrcp__month--between {
  background: var(--color-circleblue); /* #c5cae9 */
  color: var(--color-primary);
}

.mrcp__month--disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* ── Footer ───────────────────────────────────────────── */
.mrcp__footer {
  display: flex;
  justify-content: flex-end;
  border-top: var(--space-px) solid var(--color-border);
  padding-top: var(--space-sm);
}

.mrcp__done {
  background: none;
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-input);
  padding: var(--space-1-5) var(--space-5); /* 6px 20px */
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: background var(--motion-duration-fast);
}

.mrcp__done:hover:not(:disabled) {
  background: var(--color-bg-hover-light);
}

.mrcp__done:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  border-color: var(--color-border);
  color: var(--color-text-placeholder);
}
.csb-root {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 100%;
}

/* ── Inner scrollable content — native bar hidden ────────── */
.csb-content {
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.csb-content::-webkit-scrollbar {
  display: none;
}

/* ── Vertical + capped (maxHeight set) — DataTable use case ─ */
/* Only applied when maxHeight prop is provided; does not affect  */
/* the page-level <CustomScrollbar height="100vh"> usage.        */
.csb-root--capped {
  height: auto; /* grow to content; inline max-height caps it */
}

.csb-root--capped .csb-content {
  height: auto;
  /* max-height is set via inline style in TSX — CSS inheritance is unreliable */
  overflow-x: hidden;
  overflow-y: auto;
}

/* ── Vertical track ──────────────────────────────────────── */
.csb-track--v {
  position: absolute;
  top: var(--space-xs);
  bottom: var(--space-xs);
  right: var(--space-0-8);
  width: var(--space-1-5);
  cursor: pointer;
  z-index: 10; /* above sticky thead (z-index: 2) */
}

/* ── Horizontal track ────────────────────────────────────── */
.csb-track--h {
  position: absolute;
  left: var(--space-xs);
  right: var(--space-xs);
  bottom: var(--space-0-8);
  height: var(--space-1-5);
  cursor: pointer;
}

/* Track stays mounted (so trackRef is measurable on first layout) but is
   visually hidden + non-interactive when content doesn't overflow. */
.csb-track--hidden {
  opacity: 0;
  pointer-events: none;
}

/* ── Horizontal root variant ─────────────────────────────── */
.csb-root--h {
  overflow: hidden; /* allow thumb to sit below content */
}

.csb-root--h .csb-content {
  overflow-x: auto;
  overflow-y: hidden;
  height: auto;
  max-height: none;
}

/* ── Thumb — pill: white fill + primary border ───────────── */
.csb-thumb {
  position: absolute;
  background: var(--color-white);
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-md);
  cursor: grab;
  transition: background var(--motion-duration-fast) ease;
  z-index: 100;
}

.csb-thumb:hover,
.csb-thumb:active {
  background: var(--color-scrollbar-thumb-hover);
  cursor: grabbing;
}
@keyframes skeleton-shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

.skeleton-block {
  display: inline-block;
  background: linear-gradient(
    90deg,
    var(--color-lightgrey, #e5e7eb) 25%,
    #f3f4f6 50%,
    var(--color-lightgrey, #e5e7eb) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-sm, 0.25rem);
  flex-shrink: 0;
}

/* ── Filter strip variant ───────────────────────────────── */
.skeleton-filter-strip {
  display: flex;
  align-items: center;
  gap: 0;
}

.skeleton-chip-item {
  display: flex;
  align-items: center;
  padding: var(--space-xs);
}

.skeleton-chip-sep {
  font-size: var(--font-size-sm);
  color: var(--color-divider);
  padding: 0 var(--space-xs);
  user-select: none;
}
/* ── Full-page error container ───────────────────────────── */
.page-error-container {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 85vh;
  width: 100%;
  background: var(--color-lightgrey);
}

/* ── Inline / widget-level variant ──────────────────────── */
.page-error-container--inline {
  min-height: 240px;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-lightgrey);
  border-radius: var(--radius-sm);
}

/* ── Variant that keeps the widget's title/description visible ─
   The grey error background applies only to the chart area below
   the header, not the title/description, which sit on the card. ── */
.page-error-container--inline.page-error-container--with-header {
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  background: transparent;
  border-radius: 0;
}

.page-error-body {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  background: var(--color-lightgrey);
  border-radius: var(--radius-sm);
}

.page-error-widget-header {
  padding: 0;
}

.page-error-widget-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
}

.page-error-widget-subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  margin: var(--space-px) 0 0;
  font-family: var(--font-family-base);
}

.page-error-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  max-width: var(--space-105);
  text-align: center;
  padding: var(--space-xxl) var(--space-xl);
}

.page-error-icon {
  margin-bottom: var(--space-0-4);
}

/* SVG color inheritance via currentColor */
.page-error-svg--error {
  color: var(--color-error);
}

.page-error-svg--primary {
  color: var(--color-primary);
}

/* ── Title ───────────────────────────────────────────────── */
.page-error-title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  font-family: var(--font-family-display);
  margin: 0;
  color: var(--color-primary);
}

.page-error-title--red {
  color: var(--color-error);
  letter-spacing: var(--letter-spacing-wider);
}

/* ── Message ─────────────────────────────────────────────── */
.page-error-message {
  font-size: var(--font-size-lg);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  margin: 0;
  line-height: var(--line-height-loose);
}

/* ── Button ──────────────────────────────────────────────── */
.page-error-button {
  margin-top: var(--space-sm);
  padding: var(--space-2-5) var(--space-xxl);
  background-color: var(--color-error);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-input);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  cursor: pointer;
  transition: background-color var(--motion-duration-normal)
    var(--motion-easing-standard);
}

.page-error-button:hover {
  background-color: var(--color-danger);
}

.page-error-button:active {
  transform: scale(0.98);
}

/* ── Filter-error variant — same as full-page, no box/border ─ */
.page-error-container--filter {
  min-height: unset;
  height: 100%;
  background: var(--color-lightgrey);
}

/* ── Chart-level no-data variant ─────────────────────────── */
.page-error-container--chart {
  min-height: unset;
  flex: 1;
  background: var(--color-lightgrey);
  border-radius: var(--radius-sm);
}

.page-error-container--chart .page-error-content {
  gap: var(--space-sm);
  padding: var(--space-lg) var(--space-lg);
}

.page-error-container--chart .page-error-icon {
  margin-bottom: var(--space-0-4);
}

.page-error-container--chart .page-error-title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-error);
  letter-spacing: var(--letter-spacing-wider);
}

.page-error-container--chart .page-error-message {
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  text-align: center;
  line-height: var(--line-height-loose);
}
.chart-loader {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  min-height: var(--space-40); /* 10rem = 160px */
}

.chart-loader-spinner {
  width: var(--space-10);   /* 2.5rem = 40px */
  height: var(--space-10);
  border: var(--space-0-8) solid var(--color-border); /* ~3px */
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: chart-loader-spin var(--motion-duration-spin) linear infinite;
}

@keyframes chart-loader-spin {
  to {
    transform: rotate(360deg);
  }
}
/* ══════════════════════════════════════════════════════════
   HOME PAGE
══════════════════════════════════════════════════════════ */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.home-page {
  --font-family-base: 'Inter', system-ui, sans-serif;
  --font-family-display: 'Inter', system-ui, sans-serif;
  /* The whole page sits on the cream base; cards/sections layer on top. */
  background: var(--color-bg-cream);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  height: 100vh;
  /* Without this, the FilterBar's dropdown panel (position: absolute, up
     to --space-22 tall) can extend past this page's own 100vh box — since
     nothing here clips it, the browser adds a genuine page-level scrollbar
     to reveal the overflow the moment the panel opens. .um-page already
     has this; the other pages using FilterBar were missing it. */
  overflow: hidden;
}

.home-filters-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 100vh minus navbar (--space-10) minus filter strip (--space-10) */
  height: calc(100vh - var(--space-10) - var(--space-10));
}

.home-body {
  flex: 1;
  padding: var(--space-md) var(--space-5) var(--space-2-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  overflow-y: auto;
  min-height: 0;
}

.home-body--hidden {
  display: none;
}

/* ══════════════════════════════════════════════════════════
   HEADER CARD
══════════════════════════════════════════════════════════ */
.home-header-card {
  /* Same lockup as login/loading (tokens: --color-hero-gradient / --color-bg-cream). */
  background: var(--color-hero-gradient), var(--color-bg-cream);
  border-radius: var(--radius-md);
  padding: var(--space-lg) var(--space-5);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  min-height: var(--space-30);
  box-shadow: 0 var(--space-xs) var(--space-5) var(--color-shadow-card-lg);
  overflow: hidden;
  font-family: var(--font-family-display);
  position: relative;
}

.home-header-card:focus-visible {
  outline: var(--space-0-5) solid var(--color-accent);
  outline-offset: var(--space-0-6);
}

.home-header-text {
  display: flex;
  flex-direction: column;
  z-index: 1;
  flex: 1;
  min-width: 0;
}

.home-hi {
  font-size: var(--font-size-md);
  line-height: var(--line-height-relaxed);
  color: var(--color-black);
  margin: 0;
  font-weight: var(--font-weight-regular);
  display: flex;
  align-items: center;
}

.home-username {
  font-weight: var(--font-weight-extrabold);
  color: var(--color-accent);
  margin-left: var(--space-0-5);
}

.home-welcome {
  font-weight: var(--font-weight-regular);
  font-size: var(--font-size-xl);
  line-height: var(--line-height-relaxed);
  color: var(--color-black);
  margin: 0;
}

.home-product {
  font-family: "Manrope", var(--font-family-base);
  font-weight: var(--font-weight-medium);
  font-size: var(--font-size-5xl);
  line-height: var(--line-height-snug);
  color: var(--color-accent);
  margin-top: var(--space-2-5);
}

.home-description {
  font-size: var(--font-size-xs);
  line-height: var(--line-height-relaxed);
  color: var(--color-black);
  font-style: italic;
  margin-top: var(--space-2-5);
}

/* decorative image — right side, absolute */
.home-header-img-wrapper {
  position: absolute;
  right: var(--space-10);
  top: 0;
  bottom: 0;
  width: 25%;
  opacity: 0.35;
  display: flex;
  align-items: stretch;
  pointer-events: none;
}

.home-header-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: left center;
  display: block;
}

/* ══════════════════════════════════════════════════════════
   INSIGHTS SECTION — no card wrapper
══════════════════════════════════════════════════════════ */
.home-section-insights {
  padding: var(--space-xs) 0 0;
}

/* Error state: constrained to the same height as the metric card row */
.home-insights-error {
  height: var(--space-9);
  display: flex;
  align-items: stretch;
}

.home-insights-error .page-error-container {
  min-height: unset;
  height: 100%;
  width: 100%;
  background: var(--color-lightgrey);
  border-radius: var(--radius-md);
}

.home-insights-error .page-error-content {
  padding: var(--space-md) var(--space-xl);
  gap: var(--space-sm);
}

.home-insights-error .page-error-icon svg {
  width: var(--space-xxl);
  height: var(--space-xxl);
}

.home-insights-error .page-error-title {
  font-size: var(--font-size-base);
}

.home-insights-error .page-error-message {
  font-size: var(--font-size-xs);
}

.home-insights-error .page-error-button {
  padding: var(--space-0-8) var(--space-lg);
  font-size: var(--font-size-sm);
  margin-top: var(--space-0-4);
}

/* ══════════════════════════════════════════════════════════
   EXPLORE SECTION — white card wrapper
══════════════════════════════════════════════════════════ */
.home-section-explore {
  background: var(--color-bg-card);
  border-radius: var(--radius-md);
  padding: var(--space-2-5) var(--space-lg) var(--space-2-5);
  box-shadow: 0 var(--space-xs) var(--space-5) var(--color-shadow-card-md);
}

/* ══════════════════════════════════════════════════════════
   INSIGHTS HEADING
══════════════════════════════════════════════════════════ */

.pulse-title {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-regular);
  font-size: var(--font-size-2xl);
  color: var(--color-black);
  text-align: center;
  line-height: var(--line-height-normal);
  border-radius: var(--radius-sm);
  outline: none;
}

.pulse-title:focus-visible {
  outline: var(--space-0-5) solid var(--color-accent);
  outline-offset: var(--space-0-6);
}

.pulse-highlight {
  color: var(--color-accent);
  font-weight: var(--font-weight-bold);
}

/* ══════════════════════════════════════════════════════════
   CAROUSEL
══════════════════════════════════════════════════════════ */
.carousel-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.carousel-track--fit {
  overflow-x: hidden;
  scroll-snap-type: none;
}

.carousel-track::-webkit-scrollbar {
  display: none;
}

.carousel-page {
  min-width: 100%;
  flex-shrink: 0;
  scroll-snap-align: start;
  display: flex;
  gap: 0;
}

.carousel-item {
  flex: 0 0 calc(100% / 6);
  min-width: calc(100% / 6);
  padding: var(--space-1-5);
  box-sizing: border-box;
}

/* metric carousel item — equal flex share */
.carousel-item--metric {
  flex: 1 1 0;
  min-width: var(--space-9-375);
}

/* explore carousel item — fixed card width driven by JS via CSS custom prop */
.carousel-item--explore {
  flex: 0 0 var(--explore-card-w, var(--space-56));
  min-width: var(--explore-card-w, var(--space-56));
}

/* ══════════════════════════════════════════════════════════
   METRIC CARD — blue tinted bg
══════════════════════════════════════════════════════════ */
.metric-card {
  background: var(--color-bg-card);
  border-radius: var(--radius-md);
  padding: var(--space-2-5) var(--space-md);
  border: var(--space-px) solid var(--color-metric-card-border);
  /* Subtle shadow matching the Explore card below (was a large, offset one). */
  box-shadow: 0 var(--space-xs) var(--space-2-5) var(--color-shadow-card);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  height: 100%;
  min-height: var(--space-30);
  font-family: var(--font-family-display);
  overflow: hidden;
}

.metric-card:focus-visible {
  outline: var(--space-0-5) solid var(--color-accent);
  outline-offset: var(--space-0-6);
}

.metric-title {
  font-size: var(--font-size-sm);
  color: var(--color-accent);
  font-weight: var(--font-weight-semibold);
  margin: 0 0 var(--space-xs);
  line-height: var(--line-height-normal);
}

.metric-value-row {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  margin-bottom: var(--space-xs);
  flex-wrap: wrap;
}

.metric-value {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-accent);
  line-height: var(--line-height-relaxed);
  font-family: var(--font-family-display);
}

.metric-change {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  display: flex;
  align-items: center;
  gap: var(--space-0-8);
  font-family: var(--font-family-display);
}

/* Delta tokens, not success/error-alt — matches KpiCard's trend colours
   (.kpi-change--up/--down) used on every other screen. */
.trend-up {
  color: var(--color-delta-positive);
}

.trend-down {
  color: var(--color-delta-negative);
}

/* details row */
.metric-details {
  display: flex;
  align-items: stretch;
  padding-top: var(--space-sm);
}

.metric-details--single {
  justify-content: flex-start;
}

.metric-details--multi {
  justify-content: space-between;
  width: 100%;
}

.metric-detail {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-0-5);
  font-size: var(--font-size-3xs);
  color: var(--color-black);
  font-family: var(--font-family-display);
}

.metric-detail--single {
  flex: none;
  align-items: flex-start;
}

.metric-detail--right {
  align-items: center;
}

.metric-detail-icon {
  color: var(--color-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-0-5);
}

.metric-detail-text {
  font-size: var(--font-size-3xs);
  font-weight: var(--font-weight-medium);
  text-align: center;
  line-height: var(--line-height-normal);
}

.metric-detail-value {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-black);
  text-align: center;
}

.metric-detail-divider {
  width: var(--space-px);
  background: var(--color-metric-card-border);
  margin: 0 var(--space-2-5);
  align-self: stretch;
}

/* ══════════════════════════════════════════════════════════
   PAGINATION
══════════════════════════════════════════════════════════ */
.carousel-pagination {
  display: flex;
  justify-content: center;
  margin-top: var(--space-md);
}

.carousel-pagination-track {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.dot {
  display: inline-block;
  width: var(--space-sm);
  height: var(--space-sm);
  border-radius: 50%;
  background: var(--color-grey);
  border: var(--space-px) solid var(--color-grey);
  cursor: pointer;
  transition: all var(--motion-duration-slow) ease;
  flex-shrink: 0;
  padding: 0;
  appearance: none;
}

.dot:focus-visible {
  outline: 0.125rem solid var(--color-accent);
  outline-offset: 0.1875rem;
}

.dot--active {
  background: var(--color-pagination-dot-active);
  width: var(--space-5);
  border-radius: var(--space-md);
  border-color: var(--color-pagination-dot-active);
}

/* ══════════════════════════════════════════════════════════
   EXPLORE SECTION
══════════════════════════════════════════════════════════ */
/* each explore card is its own snap target */
.explore-snap-item {
  scroll-snap-align: start;
}

.explore-title {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-base);
  color: var(--color-text-black);
  margin: 0 0 var(--space-sm);
}

.explore-card {
  flex: 1;
  background: var(--color-bg-card);
  border-radius: var(--radius-md);
  padding: var(--space-sm);
  border: var(--space-px) solid var(--color-explore-card-border);
  box-shadow: 0 var(--space-xs) var(--space-2-5) var(--color-shadow-card);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;
  min-height: 0;
  font-family: var(--font-family-display);
}

.explore-card-top {
  flex: 1;
}

.explore-card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.explore-more-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-placeholder);
  font-size: var(--font-size-xl);
  line-height: var(--line-height-none);
  padding: 0;
}

.explore-card-title {
  font-weight: var(--font-weight-bold);
  font-size: var(--font-size-base);
  color: var(--color-accent);
  margin: 0 0 var(--space-xs);
  line-height: var(--line-height-normal);
}

.explore-card-desc {
  font-size: var(--font-size-2xs);
  color: var(--color-black);
  line-height: var(--line-height-relaxed);
  margin: var(--space-xs) 0 var(--space-md);
}

.explore-go-btn {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  background: var(--color-accent);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-md);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  font-family: 'Inter', system-ui, sans-serif;
  transition: background var(--motion-duration-normal) ease;
  letter-spacing: var(--space-px);
}

.explore-go-btn:hover {
  background: var(--color-accent-hover);
}

/* ── No custom scrollbar on home page ────────────────────── */
.home-page,
.home-page * {
  scrollbar-width: none;
}

.home-page::-webkit-scrollbar,
.home-page *::-webkit-scrollbar {
  display: none;
}

/* ── Responsive ───────────────────────────────────────────
   .home-header-img is a wide (512×230) pattern. The base rule keeps it on
   the side (like the 100%-width desktop layout) but pins its box to
   top: 0; bottom: 0 — full card height, width a fixed 25% of the (now
   narrowing) card. As the card narrows, that box gets taller and narrower
   relative to the image's own shape, so object-fit: cover has to crop most
   of the pattern away to fill it. Keep the image on the side at every
   width (never stack it below the text) — just stop pinning the box to
   the card's full height and instead size the box itself down via
   aspect-ratio, using a height that scales with the viewport, so the box
   stays the image's own shape (no crop) and visibly shrinks as the window
   narrows, exactly like scaling down a smaller version of the 100% view. */
@media (max-width: 640px) {
  .home-header-card {
    /* .home-header-card has overflow: hidden, which per the flexbox spec
       gives it an automatic minimum main-size of 0 as a flex item of
       .home-body (min-height: var(--space-30) still applies as an explicit
       floor, but that's shorter than the card's actual content) — so on a
       short browser window, .home-body's flex layout can shrink the card
       below its content height, and the card's own overflow: hidden then
       clips that content. This is a latent issue at every width (also
       reproducible at desktop with a short enough window), but only
       addressed here to stay within the mobile-only scope of this fix.
       flex-shrink: 0 keeps the card at its full content height, so any
       shortfall in vertical space is handled by .home-body's
       overflow-y: auto scrolling the page, not by cropping the card. */
    flex-shrink: 0;
  }

  .home-header-img-wrapper {
    position: static;
    align-self: center;
    width: auto;
    height: clamp(3rem, 16vw, 5.5rem);
    aspect-ratio: 512 / 230;
  }

  .home-header-img {
    object-position: center;
  }
}

/* ── Font overrides within home page ─────────────────────── */

/* Navbar → Inter (reset Poppins override so Last Updated / Data Source use Inter) */
.home-page .navbar {
  --font-family-base: 'Inter', system-ui, sans-serif;
  --font-family-display: 'Inter', system-ui, sans-serif;
}

/* FilterBar → Inter (override Poppins CSS vars so all var() references inside resolve correctly) */
.home-page .fb-wrapper {
  --font-family-base: 'Inter', system-ui, sans-serif;
  --font-family-display: 'Inter', system-ui, sans-serif;
  font-family: 'Inter', system-ui, sans-serif;
  /* Every other page cancels FilterBar's default `position: sticky; top:
     var(--space-10)` the same way — Home was the one page missing it.
     That default sticky top-offset is computed relative to the nearest
     ancestor that establishes a scroll container, which includes
     `overflow: hidden` (added to .home-page above to fix the FilterBar
     panel's page-level-scrollbar bug) — not just `overflow: auto/scroll`.
     Before that fix .home-page had `overflow: visible` (no scroll
     container), so the sticky offset was measured from the real
     viewport and FilterBar landed right under the fixed Navbar by
     coincidence; once .home-page became a scroll container, the same
     `top` offset started being measured from .home-page's own box
     instead, pushing the bar down by roughly another navbar-height.
     Matching every other page's override removes the dependency on
     which ancestor happens to be a scroll container entirely. */
  position: relative;
  top: 0;
}

/* Insights KPI detail text + value below icon → Inter */
.metric-detail-text,
.metric-detail-value {
  font-family: 'Inter', system-ui, sans-serif;
}

/* Explore card title ("Performance Overview") → Inter */
.explore-card-title {
  font-family: 'Inter', system-ui, sans-serif;
}

/* Explore card description → Inter */
.explore-card-desc {
  font-family: 'Inter', system-ui, sans-serif;
}
:root {
  --app-tabs-h: calc(var(--space-xxl) + var(--space-0-5));
  /* Height of the whole fixed chrome above a page: the fixed Navbar (whose
     height is also this wrapper's own sticky offset, --space-10) + these tabs.
     Published here, next to the numbers it is made of, so page-level sticky
     bars can park directly beneath the tabs without re-deriving the
     arithmetic.

     --app-tabs-h is a border-box min-height, so the hairline border is already
     inside it — adding it again left a sub-pixel GAP between the tabs and the
     bar below, and scrolling content flickered through that seam. The extra
     --space-px SUBTRACTED here biases the other way on purpose: a bar parked
     here tucks ~1px under the (opaque) tabs instead, which no rounding can
     turn back into a gap. */
  --app-header-stack-h: calc(var(--space-10) + var(--app-tabs-h) - var(--space-px));
}

.app-tabs-wrapper {
  background: var(--color-lightgrey);
  border-bottom: var(--space-px) solid var(--color-border);
  position: sticky;
  top: var(--space-10);
  z-index: 101;
  min-height: var(--app-tabs-h);
  display: flex;
  align-items: stretch;
}

.app-tabs {
  flex: 1;
  min-width: 0;
  display: flex;
  padding: 0 var(--space-lg);
  gap: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.app-tabs::-webkit-scrollbar {
  display: none;
}

.app-tab {
  scroll-snap-align: start;
  padding: var(--space-2-5) var(--space-md);
  background: none;
  border: none;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  cursor: pointer;
  white-space: nowrap;
  font-family: var(--font-family-display);
  transition:
    color var(--motion-duration-fast) ease,
    border-color var(--motion-duration-fast) ease;
}

.app-tab:hover {
  color: var(--color-primary);
}

.app-tab--active {
  color: var(--color-primary);
  border-bottom-color: transparent;
  font-weight: var(--font-weight-semibold);
  position: relative;
}

.app-tab--active::after {
  content: "";
  position: absolute;
  inset: var(--space-xs) var(--space-xs);
  background: var(--color-lightblue);
  border-radius: 0;
  z-index: -1;
}

/* ── Scroll arrows ───────────────────────────────────────── */
.app-tabs-arrow {
  flex-shrink: 0;
  width: var(--space-7);
  border: none;
  background: var(--color-lightgrey);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-primary);
}

.app-tabs-arrow-icon {
  width: var(--space-3-5);
  height: var(--space-3-5);
  display: block;
  flex-shrink: 0;
}

.app-tabs-arrow-icon--left {
  transform: rotate(180deg);
}

/* Dropdown wrapper */
.app-tab-dropdown-wrapper {
  position: relative;
}

.app-tab--has-chevron {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}

.app-tab-chevron {
  display: inline-flex;
  align-items: center;
  transition: transform var(--motion-duration-fast) ease;
}

.app-tab-chevron--open {
  transform: rotate(180deg);
}

.app-tab-chevron-icon {
  display: block;
  width: var(--space-2-5);
  height: var(--space-2-5);
  flex-shrink: 0;
}

/* Dropdown menu — top/left/minWidth set as direct inline styles in AppTabs.tsx */
.app-tab-dropdown {
  position: fixed;
  background: var(--color-bg-card);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-dropdown);
  z-index: 1100;
  max-height: 50vh;
  overflow-x: hidden;
  overflow-y: auto;
  padding: var(--space-sm) 0 var(--space-sm) var(--space-sm);
}

.app-tab-dropdown::-webkit-scrollbar {
  width: 4px;
}
.app-tab-dropdown::-webkit-scrollbar-track {
  background: transparent;
}
.app-tab-dropdown::-webkit-scrollbar-thumb {
  background: var(--color-border);
  border-radius: var(--radius-pill);
}
.app-tab-dropdown::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-muted);
}
.app-tab-dropdown {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}

.app-tab-dropdown-item {
  position: relative;
  display: block;
  width: 100%;
  padding: var(--space-sm) var(--space-xs) var(--space-sm) calc(var(--space-xs) + 4px);
  background: none;
  border: none;
  border-left: 1.5px solid var(--color-kpigrey);
  text-align: left;
  font-size: var(--font-size-xs);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--motion-duration-fast) ease, color var(--motion-duration-fast) ease;
}

.app-tab-dropdown-item:hover {
  background: var(--color-bg-hover-light);
  color: var(--color-primary);
}

.app-tab-dropdown-item--active {
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  background: var(--color-bg-hover-light);
  border-left-color: var(--color-primary);
}
.ib-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  color: var(--color-text-placeholder);
  display: flex;
  align-items: center;
  flex-shrink: 0;
  line-height: var(--line-height-none);
  transition: color var(--motion-duration-fast) ease;
}

.ib-btn:hover {
  color: var(--color-primary);
}

.ib-icon {
  display: block;
  width: var(--space-3-5);   /* 0.875rem = 14px */
  height: var(--space-3-5);
  flex-shrink: 0;
}

/* Rendered via React portal at document.body */
.ib-tooltip {
  position: fixed;
  display: block;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  z-index: 9999;
  pointer-events: none;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  max-width: var(--space-31);   /* 18rem = 288px */
  white-space: normal;
  /* A long unbroken value (a campaign name, a joined scope string) has to break rather
     than push the chip past its own max-width and back out of the viewport — this shape
     is now shared by every hover tooltip in the app via `HoverTooltip`, not just the
     short explanatory copy InfoButton was written for. */
  overflow-wrap: anywhere;
  text-align: left;
  line-height: 1.5;
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
}

/* Upward-pointing triangle above the tooltip */
.ib-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5));   /* -0.375rem */
  left: var(--space-2-5);             /* 0.625rem */
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* When tooltip is right-aligned, flip the triangle to the right */
.ib-tooltip--right::before {
  left: auto;
  right: var(--space-2-5);
}

/* When tooltip is centered on the button, triangle tracks the button center */
.ib-tooltip--centered::before {
  left: var(--ib-triangle-left, 50%);
  transform: translateX(-50%);
}

/* Anchored ABOVE the trigger (`placement="top"`): the triangle moves to the bottom edge
   and points down. Only the vertical half flips — the left/right/centred rules above
   still position it horizontally. */
.ib-tooltip--top::before {
  top: auto;
  bottom: calc(-1 * var(--space-1-5));
  border-bottom: none;
  border-top: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* `placement="top"`'s SIDE-FLYOUT fallback (see `InfoButton.tsx`'s `calcPos`): the
   tooltip's own TOP edge is pinned level with the trigger's, so the triangle sits near the
   tooltip's top-left corner — same `space-2-5` inset the default top-left triangle uses,
   just rotated 90° to point left toward the trigger instead of up. */
.ib-tooltip--side::before {
  top: var(--space-2-5);
  left: calc(-1 * var(--space-1-5));
  border-left: none;
  border-right: var(--space-1-5) solid var(--color-tooltip-bg);
  border-top: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid transparent;
}
/* Flipped to the trigger's LEFT (no room on the right) — triangle follows to the
   tooltip's right edge, pointing right. */
.ib-tooltip--side-flip::before {
  left: auto;
  right: calc(-1 * var(--space-1-5));
  border-right: none;
  border-left: var(--space-1-5) solid var(--color-tooltip-bg);
}
.kpi-card {
  flex: 1;
  background: var(--color-lightgrey);
  border-radius: var(--radius-md);
  padding: var(--space-md) var(--space-lg);
  border: var(--space-px) solid var(--color-border);
  box-shadow: 0 var(--space-0-5) var(--space-sm) var(--color-shadow-card);
  min-width: 0;
  font-family: var(--font-family-display);
  position: relative;
  z-index: 0;
}

/* Value/label/trend summary — kept as an accessibility sibling of the info
   button rather than its wrapper; see the comment in KpiCard.tsx. */
.kpi-card-summary {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--space-sm);
  min-width: 0;
  height: 100%;
  outline: none;
}

.kpi-card-summary:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -3px;
  position: relative;
  z-index: 10;
}

.kpi-card-info-btn {
  position: absolute;
  top: var(--space-md);
  right: var(--space-lg);
}


/* ── Top row ────────────────────────────────────────────── */
.kpi-card-header {
  display: flex;
  align-items: flex-start;
  /* Only the label lives here now — the info button is a positioned
     sibling of kpi-card-summary, not a flex item in this row. Reserve
     room roughly matching the icon's own footprint so a long, truncated
     label doesn't render underneath it. */
  padding-right: var(--space-5);
  gap: var(--space-sm);
  min-width: 0;
}

.kpi-label {
  display: block;
  font-size: var(--font-size-sm);
  color: var(--color-kpi-title);
  font-weight: var(--font-weight-regular);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}


/* ── Bottom row ─────────────────────────────────────────── */
.kpi-value-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-xs);
}

.kpi-value {
  margin-top: var(--space-1-5);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-black);
  line-height: var(--line-height-tight);
  cursor: default;
}

.kpi-value-tooltip {
  position: fixed;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  white-space: nowrap;
  pointer-events: none;
  z-index: 9999;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  line-height: 1.5;
}

.kpi-value-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5));
  left: 50%;
  transform: translateX(-50%);
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* Tooltip sits above its anchor (KPI title) instead of below it — flip the
   arrow to point down at the anchor instead of up. */
.kpi-value-tooltip--above::before {
  top: auto;
  bottom: calc(-1 * var(--space-1-5));
  border-bottom: none;
  border-top: var(--space-1-5) solid var(--color-tooltip-bg);
}

.kpi-change {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding-bottom: var(--space-px);
}

.kpi-change--up {
  color: var(--color-delta-positive);
}
.kpi-change--down {
  color: var(--color-delta-negative);
}
.kpi-change--neutral {
  color: var(--color-text-muted);
}

.kpi-trend-icon {
  display: block;
  width: var(--space-2-75);
  height: var(--space-2-75);
  flex-shrink: 0;
}

/* ── Empty / no-data state in KPI row ───────────────────── */
.kpi-card--no-data {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  color: var(--color-text-muted);
}

.kpi-card--no-data-label {
  font-size: var(--font-size-lg);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
}
.plotly-chart-wrapper {
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* ── Accessible focus ring around the chart ─────────────── */
.plotly-chart-focus {
  outline: none;
  position: relative;
}

.plotly-chart-focus:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* ── Visually hidden data summary for screen readers ─────── */
.pc-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.plotly-chart-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.plotly-chart-titles {
  display: flex;
  flex-direction: column;
  gap: var(--space-px);
}

.plotly-chart-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.plotly-chart-subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  margin: 0;
  font-family: var(--font-family-base);
}

/* ⓘ info button — same style as KpiCard */
.plotly-info-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  color: var(--color-text-placeholder);
  display: flex;
  align-items: center;
  flex-shrink: 0;
  line-height: 1;
  transition: color var(--motion-duration-fast) ease;
  position: relative;
}

.plotly-info-btn:hover {
  color: var(--color-primary);
}

/* header right side — actions + download */
.plotly-chart-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-shrink: 0;
}

.plotly-download-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  padding: var(--space-0-8);
  display: flex;
  align-items: center;
  border-radius: var(--radius-sm);
  transition:
    color var(--motion-duration-fast) ease,
    background var(--motion-duration-fast) ease;
}

.plotly-download-btn:hover {
  color: var(--color-primary);
  background: var(--color-bg-hover-light);
}

.plotly-chart-container {
  width: 100%;
  overflow: visible;
}

/* Allow Plotly hover labels to extend beyond the SVG boundary
   so tooltips near right/top edges flip inward instead of clipping */
.plotly-chart-container svg.main-svg {
  overflow: visible;
}

/* ── Info tooltip — same style as KpiCard ───────────────── */
.plotly-info-tooltip {
  display: none;
  position: absolute;
  top: calc(100% + var(--space-1-5));
  left: 0;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  padding: var(--space-sm) var(--space-2-5);
  border-radius: var(--radius-sm);
  z-index: 50;
  pointer-events: none;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  max-width: var(--space-31);
  white-space: normal;
  text-align: left;
  line-height: var(--line-height-relaxed);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
}

.plotly-info-btn:hover .plotly-info-tooltip {
  display: block;
}

.plotly-icon {
  display: block;
  width: var(--space-3-5);
  height: var(--space-3-5);
  flex-shrink: 0;
}
.mt-trigger {
  display: inline-flex;
  align-items: center;
  cursor: help;
}

/* Rendered via React portal at document.body */
.mt-tooltip {
  position: fixed;
  display: block;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  z-index: 9999;
  pointer-events: none;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  max-width: var(--space-31); /* 18rem = 288px */
  white-space: normal;
  text-align: left;
  line-height: 1.5;
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
}

/* Upward-pointing triangle above the tooltip */
.mt-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5)); /* -0.375rem */
  left: var(--space-2-5); /* 0.625rem */
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* When tooltip is right-aligned, flip the triangle to the right */
.mt-tooltip--right::before {
  left: auto;
  right: var(--space-2-5);
}

/* When tooltip is centered on the trigger, triangle tracks the trigger center */
.mt-tooltip--centered::before {
  left: var(--mt-triangle-left, 50%);
  transform: translateX(-50%);
}
.dt-wrapper {
  display: flex;
  flex-direction: column;
  font-family: var(--font-family-display);
  min-width: 0;
  position: relative;
}

/* ── Table container ─────────────────────────────────────── */
.dt-body {
  border: var(--space-px) solid var(--color-border);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}

/* ── Vertical scroll (default) ───────────────────────────── */
.dt-vscroll {
  width: 100%;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* ── Scroll area wrapper (relative for vertical thumb) ───── */
.dt-inner-wrap {
  position: relative;
  overflow: hidden;
}

/* ── Horizontal + vertical scroll inner (native bars hidden) */
.dt-inner-h {
  overflow-x: auto;
  overflow-y: auto;
  max-height: var(--dt-max-h, var(--space-22));
  /* auto (not contain): once this table's own scroll hits its top/bottom
     edge, let the wheel/touch input chain through to the page scroll
     instead of dead-ending here. */
  overscroll-behavior: auto;
  /* Horizontally there is no page scroll to hand off to — an overscroll there only
     rubber-bands the table sideways (a blank strip beside the first column) or fires the
     browser's swipe-back gesture. */
  overscroll-behavior-x: none;
  scrollbar-width: none;
  outline: none;
}
.dt-inner-h::-webkit-scrollbar {
  display: none;
}
.dt-inner-h:focus-visible {
  outline: var(--space-0-5) solid var(--color-primary);
  outline-offset: calc(-1 * var(--space-0-5));
}

/* ── Custom vertical track ───────────────────────────────── */
.dt-vtrack {
  position: absolute;
  top: var(--dt-vtrack-top, var(--space-xs));
  bottom: var(--space-xs);
  right: var(--space-0-8);
  width: var(--space-1-5);
  cursor: pointer;
  z-index: 10;
}

/* Track stays mounted (so it's measurable on first layout) but is
   visually hidden + non-interactive when content doesn't overflow. */
.dt-vtrack--hidden {
  opacity: 0;
  pointer-events: none;
}

/* Reserve a gutter for the vertical thumb while it's visible so it never
   overlays the last column's values. */
.dt-inner-wrap--vscroll .dt-inner-h {
  margin-right: var(--space-2-5);
}

/* Paint the gutter's header-height strip to match the thead (incl. its
   bottom divider) so the header bar reads as one continuous band. */
.dt-inner-wrap--vscroll::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: var(--space-2-5);
  height: var(--dt-vtrack-top, 0px);
  box-sizing: border-box;
  background: var(--color-lightgrey);
  border-bottom: var(--space-px) solid var(--color-border);
}

.dt-vthumb {
  position: absolute;
  left: 0;
  right: 0;
  height: var(--dt-vthumb-size, 0px);
  top: var(--dt-vthumb-offset, 0px);
  background: var(--color-white);
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-md);
  cursor: grab;
  transition: background var(--motion-duration-fast) ease;
}

.dt-vthumb:hover,
.dt-vthumb:active {
  background: var(--color-scrollbar-thumb-hover);
  cursor: grabbing;
}

/* ── Custom horizontal track ─────────────────────────────── */
.dt-htrack {
  position: relative;
  height: var(--space-2-5);
  cursor: pointer;
  margin: var(--space-xs) 0 0;
}

.dt-hthumb {
  position: absolute;
  height: var(--space-1-5);
  top: var(--space-0-8);
  width: var(--dt-hthumb-size, 0px);
  left: var(--dt-hthumb-offset, 0px);
  background: var(--color-white);
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-md);
  cursor: grab;
  transition: background var(--motion-duration-fast) ease;
  z-index: 1;
}

.dt-hthumb:hover,
.dt-hthumb:active {
  background: var(--color-scrollbar-thumb-hover);
  cursor: grabbing;
}

/* ── Clickable row ───────────────────────────────────────── */
.dt-row--clickable {
  cursor: pointer;
}

/* ── Table base ─────────────────────────────────────────── */
.dt-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
  table-layout: auto;
}

/* ── Table layout variant ────────────────────────────────── */
/* Must be declared AFTER `.dt-table` above: both are single-class selectors
   of equal specificity, so with `.dt-table` first, `tableLayout="fixed"`
   silently never took effect — `.dt-table`'s own `table-layout: auto` always
   won the cascade regardless of source order in the component's className
   string. */
.dt-table--fixed {
  table-layout: fixed;
}

/* -- Header ---------------------------------------------- */
.dt-table thead tr {
  background: var(--color-lightgrey);
}

/* Sticky header: applied via stickyHeader prop */
.dt-sticky-header thead th {
  position: sticky;
  top: 0;
  z-index: 2;
}

.dt-table th {
  padding: var(--space-md) var(--space-lg);
  text-align: center;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
  white-space: nowrap;
  word-break: normal;
  background: var(--color-lightgrey);
  vertical-align: middle;
}

.dt-th-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  white-space: nowrap;
}

.dt-th-label {
  min-width: 0;
  white-space: nowrap;
  line-height: var(--line-height-normal);
}

/* Header labels that carry a definition tooltip: the only affordance is the
   help cursor (inherited from .mt-trigger) — no icon is added to the header. */
.dt-th-tip:focus-visible {
  outline: var(--space-0-5) solid var(--color-primary);
  outline-offset: var(--space-0-4);
  border-radius: var(--radius-sm);
}

.dt-th-actions {
  display: flex;
  align-items: center;
  gap: var(--space-0-8);
  flex-shrink: 0;
}

.dt-th-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--space-0-6);
  display: flex;
  align-items: center;
  border-radius: var(--radius-sm);
  transition: background var(--motion-duration-fast) ease;
}

.dt-th-btn:hover {
  background: var(--color-bg-hover-light);
}

/* -- Column filter dropdown ------------------------------ */
.dt-filter-wrap {
  position: relative;
}

.dt-filter-dropdown {
  z-index: 99;
  background: var(--color-white);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-popover);
  padding: var(--space-sm);
  min-width: var(--space-40);
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
}

.dt-filter-input {
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-2) var(--space-sm);
  font-size: var(--font-size-xs);
  color: var(--color-primary);
  outline: none;
  width: 100%;
  font-family: var(--font-family-base);
}

.dt-filter-input:focus {
  border-color: var(--color-border-strong);
}

.dt-filter-actions {
  display: flex;
  gap: var(--space-1-5);
  justify-content: flex-end;
}

.dt-filter-clear {
  background: none;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-base);
  color: var(--color-primary);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: border-color var(--motion-duration-fast) ease;
}

.dt-filter-clear:hover {
  border-color: var(--color-border-strong);
}

.dt-filter-apply {
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-xl);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: background var(--motion-duration-fast) ease;
}

.dt-filter-apply:hover:not(:disabled) {
  background: var(--color-primary-hover);
}

.dt-filter-apply:disabled {
  background: var(--color-border);
  color: var(--color-text-placeholder);
  cursor: not-allowed;
  opacity: 0.6;
}

.dt-filter-error {
  margin: 0 var(--space-md) var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--color-error);
  text-align: right;
}

/* -- Body rows ------------------------------------------- */
.dt-table td {
  padding: var(--space-md) var(--space-lg);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
  white-space: normal;
  word-break: break-word;
  overflow: visible;
  font-size: var(--font-size-sm);
  vertical-align: middle;
  background: var(--color-white);
  text-align: center;
}

.dt-table tbody tr:nth-child(even) td {
  background: var(--color-white);
}

.dt-table tbody tr:hover td {
  background: var(--color-bg-hover-light);
}

/* A `mergeColumns` cell spans several rows; hovering one of the rows it covers
   must not repaint only its top slice, so it keeps its own background. */
.dt-table tbody tr:hover td.dt-td--merged {
  background: var(--color-white);
}

.dt-empty {
  text-align: center;
  color: var(--color-text-muted);
  padding: var(--space-xxl);
  font-size: var(--font-size-sm);
}

/* -- Row states ------------------------------------------ */
.dt-row-selected td {
  background: var(--color-rowSelectedBg) !important;
}

.dt-row-selected:hover td {
  background: var(--color-rowSelectedHoverBg) !important;
}

/* ── Pagination ─────────────────────────────────────────── */
.dt-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-lg);
  border: var(--space-px) solid var(--color-border);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  background: var(--color-white);
  font-size: var(--font-size-sm);
  color: var(--color-table-pagination-muted);
}

.dt-rows-label {
  white-space: nowrap;
}

.dt-rpp-wrap {
  position: relative;
}

.dt-rpp-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-0-6);
  border: 1px solid var(--color-table-pagination-border);
  border-radius: 0.33333rem;
  padding: 0.22222rem 0.55556rem;
  background: var(--color-white);
  font-size: 0.69444rem;
  font-family: var(--font-family-base);
  color: var(--color-table-pagination-ink);
  cursor: pointer;
  min-width: 2.77778rem;
}

.dt-rpp-chevron {
  display: block;
  width: 0.55556rem;
  height: 0.55556rem;
  flex-shrink: 0;
  color: var(--color-table-pagination-axis);
  transition: transform var(--motion-duration-fast) ease;
}

.dt-rpp-chevron--open {
  transform: rotate(180deg);
}

.dt-rpp-dropdown {
  position: absolute;
  bottom: calc(100% + var(--space-xs));
  left: 0;
  right: 0;
  background: var(--color-white);
  border: 1px solid var(--color-table-pagination-border);
  border-radius: 0.33333rem;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-popover);
  overflow: hidden;
  z-index: 10;
}

.dt-rpp-option {
  display: block;
  width: 100%;
  padding: 0.33333rem;
  background: none;
  border: none;
  font-size: 0.69444rem;
  font-family: var(--font-family-base);
  color: var(--color-table-pagination-ink);
  cursor: pointer;
  text-align: center;
}

.dt-rpp-option:hover {
  background: var(--color-table-pagination-hover-bg);
}

.dt-rpp-option--selected {
  background: var(--color-table-pagination-selected-bg);
  font-weight: 700;
}

.dt-page-info {
  white-space: nowrap;
  min-width: calc(var(--space-xxl) * 2); /* 2rem × 2 = 4rem */
  text-align: center;
}

.dt-nav-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-table-pagination-ink);
  line-height: 1;
  padding: 0 0.22222rem;
  display: flex;
  align-items: center;
  transition: color var(--motion-duration-fast) ease;
}

.dt-nav-btn:disabled {
  color: var(--color-table-pagination-faint);
  cursor: not-allowed;
}

.dt-nav-icon {
  width: 0.83333rem;
  height: 0.83333rem;
  flex-shrink: 0;
}

.dt-nav-icon--prev {
  transform: rotate(90deg);
}

.dt-nav-icon--next {
  transform: rotate(-90deg);
}

/* -- Multi-select filter dropdown ------------------------ */
.dt-filter-multi {
  min-width: var(--space-56);
  padding: var(--space-sm) 0;
  overflow: hidden;
}

.dt-multi-list {
  padding-bottom: var(--space-md);
}

/* Prevent flex from compressing the scroll area — csb-content height must match csb-root */
.dt-filter-multi .csb-root {
  flex-shrink: 0;
}

/* Push native scrollbar outside csb-root's overflow:hidden clip — cross-browser */
.dt-filter-multi .csb-content {
  width: calc(100% + 20px);
  padding-right: 20px;
  box-sizing: content-box;
}

.dt-multi-count {
  margin-left: auto;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  white-space: nowrap;
}

.dt-filter-multi .dt-filter-actions {
  padding: var(--space-sm) var(--space-sm) 0;
  border-top: var(--space-px) solid var(--color-border);
  margin-top: var(--space-1-5);
}

.dt-filter-multi .dt-filter-input {
  margin: 0 var(--space-sm) var(--space-1-5);
  width: calc(100% - var(--space-lg));
}

.dt-highlight {
  background: var(--color-subtleblue);
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--space-0-5);
  padding: 0 var(--space-px);
}

.dt-multi-option {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-1-4) var(--space-md);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dt-multi-option:hover {
  background: var(--color-bg-hover-light);
}

.dt-multi-option input[type="checkbox"] {
  accent-color: var(--color-primary);
  width: var(--space-3-5);
  height: var(--space-3-5);
  flex-shrink: 0;
  cursor: pointer;
}

.dt-multi-select-all {
  border-bottom: var(--space-px) solid var(--color-border);
  margin-bottom: var(--space-xs);
  padding-bottom: var(--space-sm);
}

.dt-multi-select-all em {
  font-style: normal;
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
}

.dt-multi-no-results {
  padding: var(--space-xs) var(--space-md);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-align: center;
}

.dt-empty-val {
  color: var(--color-text-placeholder);
  font-style: italic;
}
/* Native scroll only — no custom thumb/JS wheel handling. Scoped narrowly to
   dropdown option lists, deliberately separate from CustomScrollbar. */
.dsl-list {
  overflow-y: auto;
  overflow-x: hidden;
  /* Stop wheel scroll from chaining to the page once the list hits its top/
     bottom edge. Safe here specifically because this class is only ever
     used for a small floating option list, never a page-level or nested
     scroll container — so there's no ancestor scroller this could conflict
     with the way it did on CustomScrollbar's shared class. */
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--color-scrollbar-thumb) transparent;
}

.dsl-list::-webkit-scrollbar {
  width: var(--space-1-5);
}

.dsl-list::-webkit-scrollbar-track {
  background: transparent;
}

.dsl-list::-webkit-scrollbar-thumb {
  background: var(--color-scrollbar-thumb);
  border-radius: var(--radius-md);
}

.dsl-list::-webkit-scrollbar-thumb:hover {
  background: var(--color-scrollbar-thumb-hover);
}
.sd-wrap {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-input);
  width: fit-content;
}

.sd-label {
  position: absolute;
  top: calc(var(--space-px) * -6);
  left: var(--space-sm);
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  background: var(--color-white);
  padding: 0 var(--space-0-8);
  white-space: nowrap;
  pointer-events: none;
}

/* ── Trigger button ──────────────────────────────────────── */
.sd-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  background: transparent;
  border: none;
  cursor: pointer;
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  color: var(--color-black);
  min-width: var(--space-8);
  /* Padding must eat into the trigger's own box, not add to it — otherwise
     the chevron can get pushed past the wrap's right edge. */
  box-sizing: border-box;
  text-align: left;
}

.sd-trigger:disabled {
  cursor: not-allowed;
}

.sd-value {
  flex: 1;
  /* Guards the chevron: a long value truncates instead of growing the
     trigger and shoving the fixed-size chevron box out of view. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Prompt text shown while nothing is picked — muted, so the field reads as
   empty rather than as holding a selected value (same token the app's inputs
   use for their native ::placeholder). */
.sd-value--placeholder {
  color: var(--color-text-placeholder);
}

/* Fixed-size box (not just the icon) is what actually guarantees
   containment — even if the icon's own intrinsic size were somehow wrong,
   this box clips it via overflow:hidden. */
.sd-chevron {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-lg); /* 16px */
  height: var(--space-lg); /* 16px */
  color: var(--color-dropdown-chevron);
  opacity: 0.6;
  transition: transform var(--motion-duration-fast) ease;
  flex-shrink: 0;
  overflow: hidden;
}

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

/* ── Dropdown list ───────────────────────────────────────── */
/* Rendered through a portal to document.body (see useDropdownPosition) so it
   can't be visually clipped by an ancestor with overflow:hidden (e.g. a
   chart card) — position/top/bottom/left/width are all set inline per
   instance from the hook's fixed-viewport-coordinate calculation. */
.sd-list {
  background: var(--color-white);
  border: var(--space-px) solid var(--color-dropdown-panel-border);
  border-radius: var(--radius-md); /* 8px — crisp menu corner */
  list-style: none;
  z-index: 9999;
  overflow: hidden;
  /* Soft, elevated "popover" shadow so it reads as floating above the page. */
  box-shadow: 0 var(--space-sm) var(--space-xl) var(--color-shadow-popover);
  padding: var(--space-xs); /* 4px inset so rows nearly fill the panel */
}

/* Compact, rounded menu rows (Linear/Notion-style): a ~32px row separated by
   hover/selected highlight, not dividers. font-family falls back to the app's
   base font where "Manrope" isn't loaded (self-hosted only on the optimizer
   pages), same pattern as --ohf-body. */
.sd-option {
  display: flex;
  align-items: center;
  justify-content: space-between; /* label left, selected-check right */
  gap: var(--space-sm);
  min-height: 2rem; /* 32px */
  padding: var(--space-0-6) var(--space-sm); /* ~2.4px / 8px */
  border-radius: var(--radius-input); /* 6px */
  font-family: "Manrope", var(--font-family-base);
  font-weight: var(--font-weight-medium);
  font-size: var(--font-size-base); /* ~13px */
  line-height: var(--line-height-snug);
  color: var(--color-dropdown-option-text);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.sd-option:hover {
  background: var(--color-dropdown-hover);
}

.sd-option--active {
  background: var(--color-dropdown-active-bg);
  color: var(--color-checkbox-navy);
  font-weight: var(--font-weight-semibold);
}

/* Label truncates; the trailing check is pushed to the right edge by the row's
   space-between. */
.sd-option-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Crisp trailing check marks the selected row — a real SVG glyph so it sits
   optically centred in the row (the old CSS border-tick needed a nudge and
   drifted). */
.sd-check {
  width: 0.83333rem; /* ~15px */
  height: 0.83333rem;
  color: var(--color-checkbox-navy);
  flex-shrink: 0;
}

/* ── Search box (searchable lists) ────────────────────────────
   Pinned above the options (outside DropdownScrollList) so it stays put while
   a long list scrolls beneath it. Negative side margins + compensating padding
   bleed the hairline full-width while keeping the field aligned with the rows,
   mirroring MultiSelectDropdown's select-all. */
.sd-search {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 1.88889rem; /* ~34px — a proper, uniform field height */
  padding: 0 var(--space-sm);
  margin-bottom: var(--space-xs);
  background: var(--color-dropdown-hover);
  border: var(--space-px) solid var(--color-dropdown-panel-border);
  border-radius: var(--radius-input); /* 6px */
}

.sd-search-icon {
  width: 0.77778rem; /* ~14px */
  height: 0.77778rem;
  color: var(--color-dropdown-chevron);
  flex-shrink: 0;
}

.sd-search-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: "Manrope", var(--font-family-base);
  font-size: var(--font-size-base);
  color: var(--color-dropdown-option-text);
}

.sd-search-input::placeholder {
  color: var(--color-text-muted);
}

.sd-no-match {
  padding: var(--space-sm);
  font-family: "Manrope", var(--font-family-base);
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  text-align: center;
}

.sd-align-end {
  align-self: flex-end;
}

.sd-chevron-icon {
  display: block;
  width: 100%;
  height: 100%;
  flex-shrink: 0;
}
/* Response Curve modal — kept visually identical to the Media Optimisation
   Results screen's `.mor-modal` (see MediaOptimisationResults.css): same
   centered overlay above the navbar (z-index 1000), lightgrey header bar with
   title + action icons, and a scrollable white body. */
.pgm-backdrop {
  position: fixed;
  inset: 0;
  background: var(--color-backdrop-overlay);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.pgm-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: min(72rem, 92vw);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-5) var(--space-15) var(--color-shadow-tooltip);
  overflow: hidden;
}

.pgm-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
  background: var(--color-lightgrey);
  flex-shrink: 0;
}

.pgm-title {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
}

.pgm-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.pgm-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--color-primary);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background 0.15s,
    color 0.15s;
  padding: var(--space-0-8);
}

.pgm-icon-btn:hover {
  background: var(--color-section-icon-hover-bg);
  color: var(--color-primary);
}

.pgm-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-7);
  height: var(--space-7);
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background var(--motion-duration-fast),
    color var(--motion-duration-fast);
  padding: 0;
}

.pgm-close:hover {
  color: var(--color-primary);
  background: var(--color-bg-hover-light);
}

.pgm-close-icon {
  display: block;
  width: var(--space-4-5);
  height: var(--space-4-5);
  flex-shrink: 0;
}

.pgm-body {
  overflow-y: auto;
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
}

.pgm-no-data {
  align-items: center;
  justify-content: center;
  min-height: var(--space-50);
  font-size: var(--font-size-md);
  color: var(--color-text-secondary);
}
.po-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  /* Without this, the FilterBar's dropdown panel (position: absolute,
     up to --space-22 tall) can extend past this page's own 100vh box —
     since nothing here clips it, the browser adds a genuine page-level
     scrollbar to reveal the overflow the moment the panel opens, on top
     of .po-body's own CustomScrollbar. .um-page already has this; the
     other pages using FilterBar were missing it. */
  overflow: hidden;
}

/* AppTabs: disable sticky — page no longer window-scrolls */
.po-page .app-tabs-wrapper {
  position: static;
}

/* FilterBar override — white bg, inset black line matches po-body horizontal padding */
.po-page .fb-wrapper {
  position: relative;
  top: 0;
  /* cancel the sticky top offset from FilterBar.css */
  background: var(--color-white);
  border-bottom: none;
  margin: 0;
}

/* Divider below FilterBar — inset to match body padding */
.po-filter-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-lg);
}

/* Black divider line (after KPIs, after charts) */
.po-kpi-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0;
}


.po-kpi-note {
  text-align: right;
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  font-family: var(--font-family-base);
  padding: 0 var(--space-md);
  padding-top: var(--space-sm);
  margin-bottom: calc(var(--space-sm) * -1);
}

.po-body {
  flex: 1;
  min-height: 0;
}

.po-body-content {
  padding: 0 var(--space-lg) var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.po-kpi-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-md);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding: 0 var(--space-md) var(--space-md);
  padding-bottom: var(--space-xs);
}

.po-kpi-row::-webkit-scrollbar {
  display: none;
}

/* each KPI card gets a minimum width so row scrolls instead of cards shrinking */
.po-kpi-row .kpi-card {
  min-width: var(--space-35);
  flex: 1 0 var(--space-35);
  scroll-snap-align: start;
}

/* ── Charts row — grid ───────────────────────────────────── */
.po-charts-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
}

/* Single visible chart takes full width, no divider */
.po-charts-row--single {
  grid-template-columns: 1fr;
}

.po-charts-row--has-divider {
  border-bottom: var(--space-px) solid var(--color-kpigrey);
  padding-bottom: var(--space-md);
}

.po-chart-half:first-child {
  border-right: var(--space-px) solid var(--color-kpigrey);
}

.po-charts-row--single .po-chart-half:first-child {
  border-right: none;
}

/* full-width panel (Annual Sales) */
.po-chart-full {
  background: var(--color-bg-card);
  padding: var(--space-xs) var(--space-md) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.po-chart-half {
  background: var(--color-white);
  min-width: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.po-chart-half:first-child .po-chart-inner {
  padding-right: var(--space-md);
}

.po-chart-half:nth-child(2) .po-chart-inner {
  padding-left: var(--space-md);
}

/* inner wrapper — carries the padding and enforces minimum width */
.po-chart-inner {
  min-width: var(--space-34);
  padding: var(--space-md) var(--space-md) var(--space-md);
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-xs);
}

/* ── Chart header ─────────────────────────────────────────── */
.po-chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-md);
}

.po-chart-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.po-chart-subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  margin: var(--space-px) 0 0;
  font-family: var(--font-family-base);
}

/* ── Toggle group ─────────────────────────────────────────── */
.po-toggle-group {
  display: flex;
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex-shrink: 0;
}

.po-toggle {
  padding: var(--space-xs) var(--space-2-5);
  background: none;
  border: none;
  font-family: var(--font-family-base);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary);
  cursor: pointer;
  transition:
    background var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
}

.po-toggle--active {
  background: var(--color-primary);
  color: var(--color-white);
}

/* ── Chart action bar ────────────────────────────────────── */
.po-chart-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-shrink: 0;
}

.po-icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-primary);
  padding: var(--space-0-8);
  display: flex;
  align-items: center;
  border-radius: var(--radius-sm);
  transition:
    color var(--motion-duration-fast) ease,
    background var(--motion-duration-fast) ease;
}

.po-icon-btn:hover {
  color: var(--color-primary);
  background: var(--color-bg-hover-light);
}

/* ── YoY chart year label ────────────────────────────────── */
.po-yoy-chart-wrap {
  display: flex;
  flex-direction: column;
}

.po-yoy-year-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  margin: 0;
  padding: 0 var(--space-lg) 0 var(--space-12);
  /* 1rem = Plotly r:16px, 3rem = Plotly l:48px */
}

/* Multi-bracket container — sits below the chart, aligned to plot area */
.po-yoy-brackets {
  position: relative;
  display: flex;
  height: var(--space-xxl);
  box-sizing: border-box;
}

/* Each bracket item is absolutely positioned by left% + width% */
.po-yoy-bracket-item {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
}

/* Vertical tick at the left edge of each bracket (except the first) */
.po-yoy-bracket-divider {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--space-px);
  height: var(--space-0-6rem);
  background: var(--color-kpigrey);
  transform: translateX(-50%);
}

.po-yoy-year-line {
  width: 100%;
  border-top: var(--space-px) solid var(--color-kpigrey);
  position: relative;
}

.po-yoy-year-line::before,
.po-yoy-year-line::after {
  content: "";
  position: absolute;
  top: 0;
  width: var(--space-px);
  height: var(--space-sm);
  background: var(--color-kpigrey);
}

.po-yoy-year-line::before {
  left: 0;
}

.po-yoy-year-line::after {
  right: 0;
}

.po-yoy-year-text {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
}

/* ── Flip-to-table view ──────────────────────────────────── */
.po-flip-table-wrap {
  overflow-y: auto;
  max-height: var(--space-33);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
}

.po-flip-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
}

.po-flip-table thead tr {
  background: var(--color-white);
  position: sticky;
  top: 0;
}

.po-flip-table th {
  padding: var(--space-sm) var(--space-md);
  text-align: left;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
  white-space: nowrap;
}

.po-flip-table td {
  padding: var(--space-sm) var(--space-md);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
}

.po-flip-table tbody tr:hover {
  background: var(--color-bg-hover-light);
}

/* ── Table pagination ────────────────────────────────────── */
.po-table-pagination {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  justify-content: flex-end;
  padding: var(--space-xs) 0;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.po-table-rows-select {
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-px) var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--color-primary);
  background: var(--color-white);
}

.po-table-nav-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-primary);
  padding: var(--space-px) var(--space-xs);
  font-size: var(--font-size-base);
  display: flex;
  align-items: center;
  line-height: var(--line-height-none);
}

.po-table-nav-btn:disabled {
  color: var(--color-text-placeholder);
  cursor: not-allowed;
}

/* ── Platform Performance Analysis ───────────────────────── */
.po-full-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  padding: var(--space-xs) var(--space-md) var(--space-sm);
}

.po-full-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* ── Platform Performance table ──────────────────────────── */
.po-perf-table-wrap {
  overflow-x: auto;
  overflow-y: auto;
  max-height: var(--space-22);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
}

.po-perf-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-family-display);
  font-size: var(--font-size-sm);
  min-width: var(--space-32);
}

.po-perf-table thead tr {
  background: var(--color-white);
  position: sticky;
  top: 0;
  z-index: 1;
}

.po-perf-table th {
  padding: var(--space-2-5) var(--space-lg);
  text-align: left;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
  white-space: nowrap;
}

.po-th-inner {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
}

.po-perf-table td {
  padding: var(--space-md) var(--space-lg);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
  white-space: nowrap;
}

.po-perf-table .td-platform {
  color: var(--color-accent);
  font-weight: var(--font-weight-medium);
}

.td-trend {
  width: var(--space-xl);
  text-align: center;
  padding: var(--space-sm) var(--space-sm);
}

.po-trend-icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  padding: 0;
  transition: color var(--motion-duration-fast) ease;
}

.po-trend-icon-btn:hover {
  color: var(--color-accent);
}

.po-perf-table tbody tr:hover {
  background: var(--color-bg-hover-light);
}

/* ── Table footer (pagination + action buttons) ──────────── */
.po-table-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-lg);
  flex-wrap: wrap;
}

.po-action-btns {
  display: flex;
  gap: var(--space-sm);
  justify-content: flex-end;
  margin-top: var(--space-xs);
}

.po-btn-primary {
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.po-btn-primary:hover {
  background: var(--color-primary-hover);
}

.po-btn-secondary {
  background: var(--color-white);
  color: var(--color-primary);
  border: var(--space-px) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.po-btn-secondary:hover {
  background: var(--color-bg-hover-light);
}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 1200px) {
  .po-kpi-row {
    flex-wrap: wrap;
  }
}

/* Below ~600px, flex-wrap's natural reflow depends on each card's own
   min-width vs. the exact remaining space, which can land on 1-per-row
   (a lot of dead space beside each card) as often as 2. Switch to an
   explicit 2-column grid so mobile always gets a predictable 2-and-2
   layout; an odd trailing card spans both columns instead of leaving an
   empty cell beside it. */
@media (max-width: 600px) {
  .po-kpi-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  .po-kpi-row .kpi-card:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 1024px) {
  .po-charts-row {
    grid-template-columns: 1fr;
  }

  .po-chart-half:first-child {
    border-right: none;
    border-bottom: var(--space-px) solid var(--color-kpigrey);
  }

  .po-chart-half:first-child .po-chart-inner,
  .po-chart-half:nth-child(2) .po-chart-inner {
    padding-left: var(--space-md);
    padding-right: var(--space-md);
  }
}
.bp-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  /* Without this, the FilterBar's dropdown panel (position: absolute,
     up to --space-22 tall) can extend past this page's own 100vh box —
     since nothing here clips it, the browser adds a genuine page-level
     scrollbar to reveal the overflow the moment the panel opens, on top
     of .bp-body's own CustomScrollbar. .um-page already has this; the
     other pages using FilterBar were missing it. */
  overflow: hidden;
}

.bp-page .app-tabs-wrapper {
  position: static;
}

.bp-page .fb-wrapper {
  position: relative;
  top: 0;
  background: var(--color-white);
  border-bottom: none;
  margin: 0;
}

.bp-filter-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-lg);
}

.bp-kpi-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0;
}

.bp-kpi-note {
  text-align: right;
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  font-family: var(--font-family-base);
  padding: 0 var(--space-md);
  padding-top: var(--space-sm);
  margin-bottom: calc(var(--space-sm) * -1);
}

.bp-body {
  flex: 1;
  min-height: 0;
}

.bp-body-content {
  padding: 0 var(--space-lg) var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.bp-kpi-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-md);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding: 0 var(--space-md) var(--space-md);
  padding-bottom: var(--space-xs);
}

.bp-kpi-row::-webkit-scrollbar {
  display: none;
}

.bp-kpi-row .kpi-card {
  min-width: var(--space-35);
  flex: 1 0 var(--space-35);
  scroll-snap-align: start;
}

/* ── Full-width chart section ─────────────────────────────── */
.bp-chart-full {
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding: var(--space-xs) var(--space-md) 0;
  gap: var(--space-xs);
}

/* ── Chart header ─────────────────────────────────────────── */
.bp-chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-md);
}

.bp-chart-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.bp-chart-subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  margin: var(--space-px) 0 0;
  font-family: var(--font-family-base);
}

/* ── Chart action bar ────────────────────────────────────── */
.bp-chart-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-shrink: 0;
}

.bp-icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-primary);
  padding: var(--space-0-8);
  display: flex;
  align-items: center;
  border-radius: var(--radius-sm);
  transition:
    color var(--motion-duration-fast) ease,
    background var(--motion-duration-fast) ease;
}

.bp-icon-btn:hover {
  color: var(--color-primary);
  background: var(--color-bg-hover-light);
}

/* ── Charts row — grid ───────────────────────────────────── */
.bp-charts-row-wrapper {
  display: flex;
  flex-direction: column;
}

.bp-collapse-header {
  display: flex;
  justify-content: flex-end;
  padding: var(--space-xs) var(--space-md);
}

.bp-collapse-btn {
  background: var(--color-white);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  width: var(--space-5);
  height: var(--space-5);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--color-primary);
  transition: all var(--motion-duration-fast) ease;
  box-shadow: 0 var(--space-0-5) var(--space-xs) rgba(0, 0, 0, 0.1);
}

.bp-collapse-btn:hover {
  background: var(--color-bg-hover-light);
  border-color: var(--color-primary);
}

.bp-charts-row {
  display: grid;
  grid-template-columns: 2.2fr 3fr;
  gap: 0;
}

.bp-chart-half {
  background: var(--color-white);
  min-width: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.bp-chart-half:first-child {
  border-right: var(--space-px) solid var(--color-kpigrey);
}

.bp-chart-half:first-child .bp-chart-inner {
  padding-right: var(--space-xs);
}

.bp-chart-half:nth-child(2) .bp-chart-inner {
  padding-left: var(--space-md);
}

.bp-chart-half:only-child {
  border-right: none;
}

.bp-chart-inner {
  min-width: var(--space-34);
  padding: var(--space-md) var(--space-md) 0;
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-xs);
}

/* ── Donut stats strip ──────────────────────────────────── */
.bp-donut-stats {
  display: flex;
  justify-content: center;
  gap: var(--space-lg);
  padding: var(--space-xs) 0;
  flex-wrap: wrap;
}

.bp-donut-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-0-5);
}

.bp-donut-stat-swatch {
  width: var(--space-sm);
  height: var(--space-sm);
  border-radius: var(--space-0-5);
}

.bp-donut-stat-label {
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
}

.bp-donut-stat-value {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
}

/* ── Scroll-to-top button ─────────────────────────────────── */
.bp-scroll-top {
  position: fixed;
  bottom: var(--space-5);
  right: var(--space-5);
  width: var(--space-10);
  height: var(--space-10);
  border-radius: 50%;
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 var(--space-0-5) var(--space-md) var(--color-shadow-panel);
  transition: background var(--motion-duration-fast) ease;
  z-index: 50;
  font-size: var(--font-size-base);
  line-height: 1;
}

.bp-scroll-top:hover {
  background: var(--color-primary-hover);
}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 1200px) {
  .bp-kpi-row {
    flex-wrap: wrap;
  }
}

/* Below ~600px, flex-wrap's natural reflow depends on each card's own
   min-width vs. the exact remaining space, which can land on 1-per-row
   (a lot of dead space beside each card) as often as 2. Switch to an
   explicit 2-column grid so mobile always gets a predictable 2-and-2
   layout; an odd trailing card spans both columns instead of leaving an
   empty cell beside it. */
@media (max-width: 600px) {
  .bp-kpi-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  .bp-kpi-row .kpi-card:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 1024px) {
  .bp-charts-row {
    grid-template-columns: 1fr;
  }

  .bp-chart-half:first-child {
    border-right: none;
    border-bottom: var(--space-px) solid var(--color-kpigrey);
  }

  .bp-chart-half:first-child .bp-chart-inner,
  .bp-chart-half:nth-child(2) .bp-chart-inner {
    padding-left: var(--space-md);
    padding-right: var(--space-md);
  }
}
.cd-backdrop {
  position: fixed;
  inset: 0;
  background: var(--color-backdrop-overlay, rgba(0, 0, 0, 0.4));
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.cd-dialog {
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: 0 var(--space-xs) var(--space-xxl) var(--color-shadow-modal);
  width: min(420px, 92vw);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.cd-header {
  padding: var(--space-lg) var(--space-xl) var(--space-sm);
}

.cd-title {
  font-size: var(--font-size-base);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  margin: 0;
  line-height: var(--line-height-snug);
}

.cd-message {
  padding: 0 var(--space-xl) var(--space-lg);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  margin: 0;
  line-height: var(--line-height-relaxed);
  overflow-wrap: break-word;
}

.cd-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-xl) var(--space-md);
  border-top: var(--space-px) solid var(--color-border);
}

.cd-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  padding: 0 var(--space-md);
  height: var(--space-6-5);
  box-sizing: border-box;
  cursor: pointer;
  border: var(--space-px) solid transparent;
  transition:
    background var(--motion-duration-fast) ease,
    opacity var(--motion-duration-fast) ease;
  white-space: nowrap;
  line-height: var(--line-height-none);
}

.cd-btn--cancel {
  background: var(--color-white);
  border-color: var(--color-border);
  color: var(--color-text-body);
}

.cd-btn--cancel:hover {
  border-color: var(--color-text-muted);
}

.cd-btn--confirm {
  background: var(--color-primary);
  color: var(--color-white);
  border-color: var(--color-primary);
}

.cd-btn--confirm:hover {
  opacity: 0.88;
}

.cd-btn--danger {
  background: var(--color-danger);
  color: var(--color-white);
  border-color: var(--color-danger);
}

.cd-btn--danger:hover {
  opacity: 0.88;
}

.cd-btn--mo-primary,
.cd-btn--mo-secondary {
  gap: var(--space-xs);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  height: auto;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-normal);
}

.cd-btn--mo-primary {
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
}

.cd-btn--mo-primary:hover {
  background: var(--color-primary-hover);
  opacity: 1;
}

.cd-btn--mo-secondary {
  background: var(--color-white);
  color: var(--color-primary);
  border: var(--space-px) solid var(--color-border-strong);
}

.cd-btn--mo-secondary:hover {
  background: var(--color-bg-hover-light);
  border-color: var(--color-border-strong);
}

/* ─── Simulator variant ─────────────────────────────────────── */
.cd-simulator-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
}

.cd-simulator-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: 26.25rem;
  max-width: 95vw;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-sm) var(--space-10) rgba(0, 0, 0, 0.18);
}

.cd-simulator-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-lg) var(--space-5) var(--space-3-5);
}

.cd-simulator-title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
}

.cd-simulator-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-xxl);
  height: var(--space-xxl);
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
}

.cd-simulator-close:hover {
  background: var(--color-lightgrey);
  color: var(--color-text-body);
}

.cd-simulator-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-5) var(--space-xs);
  border-radius: var(--space-0-5);
}

.cd-simulator-body {
  padding: var(--space-lg) var(--space-5) var(--space-md);
}

.cd-simulator-text {
  font-size: var(--font-size-lg);
  color: var(--color-text-body);
  margin: 0;
  line-height: var(--line-height-relaxed);
  overflow-wrap: break-word;
}

.cd-simulator-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2-5);
  padding: var(--space-md) var(--space-5) var(--space-lg);
}
.app-toggle {
  position: relative;
  width: var(--space-1-875);
  height: var(--space-lg);
  border-radius: var(--space-sm);
  border: none;
  background: var(--color-text-placeholder);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
  padding: 0;
  flex-shrink: 0;
}

.app-toggle--on {
  background: var(--color-primary);
}

.app-toggle-thumb {
  position: absolute;
  top: var(--space-0-5);
  left: var(--space-0-5);
  width: var(--space-md);
  height: var(--space-md);
  border-radius: 50%;
  background: var(--color-white);
  transition: transform var(--motion-duration-fast) ease;
  box-shadow: 0 var(--space-px) var(--space-xs) var(--color-shadow-tooltip);
}

.app-toggle--on .app-toggle-thumb {
  transform: translateX(var(--space-3-5));
}

.app-toggle--disabled,
.app-toggle:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.md-section {
  display: flex;
  flex-direction: column;
  gap: 0;
  flex: 1;
  min-height: 0;
}

/* ── Cards ─────────────────────────────────────────────── */
.md-cards {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-lg);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-top: var(--space-1-5);
  padding-bottom: var(--space-xs);
  margin-bottom: var(--space-xl);
}

.md-cards::-webkit-scrollbar {
  display: none;
}

.md-card {
  background: var(--color-white);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-lg) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  cursor: pointer;
  transition: all var(--motion-duration-fast) ease;
  font-family: var(--font-family-display);
  text-align: left;
  box-shadow: 0 var(--space-0-5) var(--space-sm) var(--color-shadow-card);
  min-width: var(--space-60);
  flex: 1 0 var(--space-60);
  scroll-snap-align: start;
}

.md-card:hover {
  border-color: var(--color-primary);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-card-md);
  transform: translateY(calc(var(--space-0-5) * -1));
}

.md-card--active {
  background: linear-gradient(
    135deg,
    var(--color-bg-card-alt) 0%,
    var(--color-lightblue) 100%
  );
  border-color: var(--color-primary);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-card-md);
}

/* ── Table section ─────────────────────────────────────── */
.md-table-section {
  display: flex;
  flex-direction: column;
  gap: 0;
  flex: 1;
  min-height: 0;
  position: relative;
}

.md-table-overlay {
  position: absolute;
  inset: 0;
  background: var(--color-overlay-white, rgba(255, 255, 255, 0.6));
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  pointer-events: all;
}

.md-card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-sm);
}

.md-card-label {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  letter-spacing: 0.05em;
}

.md-card-abbr {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
}

.md-card-value {
  font-size: var(--font-size-6xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-heading);
  line-height: var(--line-height-none);
}

/* ── Toolbar ───────────────────────────────────────────── */
.md-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: 0;
  flex-wrap: wrap;
  min-height: var(--space-10);
  padding: var(--space-xs) var(--space-md);
  background: var(--color-bg-card-alt);
  border: var(--space-px) solid var(--color-border);
  border-bottom: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

.md-search-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-md);
  background: var(--color-white);
  min-width: var(--space-40);
  max-width: var(--space-22);
  flex: 1;
  height: var(--space-1-875);
  box-sizing: border-box;
}

.md-search-icon {
  color: var(--color-text-placeholder);
  flex-shrink: 0;
}

.md-search {
  border: none;
  outline: none;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  background: transparent;
  width: 100%;
}

.md-search::placeholder {
  color: var(--color-text-placeholder);
}

.md-toolbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-shrink: 0;
}

/* ── Edit toggle wrapper ────────────────────────────────── */
.md-edit-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: 0 var(--space-xs);
}

.md-edit-label {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  font-weight: var(--font-weight-medium);
}

/* ── Buttons ───────────────────────────────────────────── */
.md-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  padding: 0 var(--space-sm);
  height: var(--space-6-5);
  box-sizing: border-box;
  cursor: pointer;
  transition:
    background var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease,
    border-color var(--motion-duration-fast) ease;
  white-space: nowrap;
  border: var(--space-px) solid transparent;
  line-height: var(--line-height-none);
}

/* Ghost — no border, primary text */
.md-btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--color-primary);
}

.md-btn--ghost:hover {
  opacity: 0.75;
}
.md-btn--ghost:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Outlined — border + primary text */
.md-btn--outline {
  background: var(--color-white);
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.md-btn--outline:hover {
  background: var(--color-bg-card-alt);
}

.md-btn--outline.md-btn--active {
  background: var(--color-bg-card-alt);
}

.md-btn--outline:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.md-btn--save {
  background: var(--color-white);
  color: var(--color-text-muted);
  border-color: var(--color-primary);
  padding: var(--space-xs) var(--space-xxl);
  font-weight: var(--font-weight-semibold);
}

.md-btn--save:hover {
  color: var(--color-primary);
}
.md-btn--save:disabled {
  opacity: 0.45;
  border-color: var(--color-primary);
  cursor: not-allowed;
}
.md-btn--save-active {
  color: var(--color-primary);
  opacity: 1;
}

/* ── Table wrapper ─────────────────────────────────────── */
.md-table-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-x: auto;
}

.md-table-wrap .dt-wrapper {
  flex: 1;
  min-height: 0;
}

.md-table-wrap .dt-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.md-table-wrap .dt-inner-wrap {
  flex: 1;
  min-height: 0;
}

.md-table-wrap .dt-inner-h {
  height: 100%;
  max-height: none;
}

/* ── Edit-mode cell inputs ─────────────────────────────── */
.md-cell-input {
  width: 100%;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  outline: none;
  background: var(--color-white);
  min-width: 0;
  height: var(--space-xxl);
  box-sizing: border-box;
}

.md-cell-input:focus {
  border-color: var(--color-primary);
}

/* ── Delete button ─────────────────────────────────────── */
.md-del-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-danger);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-0-8);
  border-radius: var(--radius-sm);
  transition: background var(--motion-duration-fast) ease;
}

.md-del-btn:hover {
  background: var(--color-danger-bg);
}

.md-del-btn-wrap--disabled {
  cursor: not-allowed;
}

.md-del-btn--disabled {
  opacity: 0.35;
  pointer-events: none;
}

.md-del-tooltip {
  position: fixed;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  max-width: 240px;
  white-space: normal;
  pointer-events: none;
  z-index: 9999;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  line-height: 1.5;
}

.md-del-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5));
  right: var(--md-arrow-right, 12px);
  left: auto;
  transform: translateX(50%);
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

.md-del-tooltip--above::before {
  top: auto;
  bottom: calc(-1 * var(--space-1-5));
  right: var(--md-arrow-right, 12px);
  left: auto;
  transform: translateX(50%);
  border-bottom: none;
  border-top: var(--space-1-5) solid var(--color-tooltip-bg);
}

.md-del-tooltip--centered {
  white-space: nowrap;
}

.md-del-tooltip--centered::before {
  left: 50%;
  right: auto;
  transform: translateX(-50%);
}

.md-del-tooltip--above.md-del-tooltip--centered::before {
  left: 50%;
  right: auto;
  transform: translateX(-50%);
}

/* ── Required field star ───────────────────────────────── */
.md-required-star {
  color: var(--color-danger);
  font-size: var(--font-size-sm);
  line-height: 1;
  margin-left: var(--space-px);
  font-weight: var(--font-weight-bold);
}

/* ── Save footer ───────────────────────────────────────── */
.md-save-footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-sm);
  padding-top: var(--space-sm);
  flex-wrap: wrap;
}
/* ─── Multi-select / single-select cell ─────────────────── */
.um-multisel {
  /* Checkbox geometry — sub-pixel values with no clean token equivalent */
  --tc-chk-border: 0.09375rem;  /* 1.5px border */
  --tc-check-left: 0.175rem;
  --tc-check-top: 0.025rem;
  --tc-check-w: 0.3rem;

  position: relative;
  width: 100%;
}

.um-multisel-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xs);
  width: 100%;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--space-xs);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  background: var(--color-white);
  cursor: pointer;
  text-align: left;
  min-width: 0;
  height: var(--space-xxl);
  box-sizing: border-box;
}

.um-multisel-trigger:focus {
  outline: none;
  border-color: var(--color-primary);
}
.um-multisel-trigger--open {
  border-color: var(--color-primary);
}

.um-multisel-val {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.um-sel-placeholder {
  color: var(--color-text-placeholder);
}

.um-multisel-dropdown {
  z-index: 9999;
  background: var(--color-cell-dropdown-bg);
  border: var(--space-px) solid var(--color-cell-dropdown-border);
  border-radius: var(--space-1-5);
  box-shadow: 0 var(--space-0-5) var(--space-1-5) var(--color-shadow-popover);
  min-width: 100%;
  max-height: var(--space-16);
  overflow-y: auto;
  padding: var(--space-xs) 0;
}

.um-multisel-option {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-sm) var(--space-2-5);
  font-size: var(--font-size-sm);
  color: var(--color-cell-dropdown-text);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  font-weight: var(--font-weight-regular);
}

.um-multisel-option:hover {
  background: var(--color-cell-dropdown-hover-bg);
}

.um-sel-option {
  cursor: pointer;
}

.um-sel-option--selected {
  background: var(--color-cell-dropdown-hover-bg);
  color: var(--color-cell-dropdown-text);
  font-weight: var(--font-weight-medium);
}

/* Custom checkbox */
.um-multisel-option input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: var(--space-3-5);
  height: var(--space-3-5);
  border: var(--tc-chk-border) solid var(--color-cell-checkbox-color);
  border-radius: var(--space-xs);
  background: var(--color-white);
  cursor: pointer;
  flex-shrink: 0;
  position: relative;
  transition: background var(--motion-duration-fast) ease;
}

.um-multisel-option input[type="checkbox"]:checked {
  background: var(--color-cell-checkbox-color);
  border-color: var(--color-cell-checkbox-color);
}

.um-multisel-option input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: var(--tc-check-left);
  top: var(--tc-check-top);
  width: var(--tc-check-w);
  height: var(--space-sm);
  border: var(--tc-chk-border) solid var(--color-white);
  border-top: none;
  border-left: none;
  transform: rotate(45deg);
}
.um-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ─── Body ──────────────────────────────────────────────── */
.um-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: var(--space-12) var(--space-lg) var(--space-10);
  gap: 0;
  min-height: 0;
  overflow: hidden;
}

/* ─── Sub-tabs ──────────────────────────────────────────── */
.um-subtabs {
  display: flex;
  gap: 0;
  border-bottom: var(--space-px) solid var(--color-border);
  margin-bottom: var(--space-md);
  overflow-x: auto;
  scrollbar-width: none;
  flex-shrink: 0;
}

.um-subtabs::-webkit-scrollbar {
  display: none;
}

.um-subtab {
  background: none;
  border: none;
  border-bottom: var(--space-0-1875) solid transparent;
  padding: var(--space-2-5) var(--space-xl);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  cursor: pointer;
  transition:
    color var(--motion-duration-fast) ease,
    border-color var(--motion-duration-fast) ease;
  white-space: nowrap;
  flex-shrink: 0;
}

.um-subtab:hover {
  color: var(--color-primary);
}

.um-subtab--active {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
}

/* ─── Toolbar ───────────────────────────────────────────── */
.um-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: 0;
  flex-wrap: wrap;
  min-height: var(--space-10);
  padding: var(--space-xs) var(--space-md);
  background: var(--color-bg-card-alt);
  border: var(--space-px) solid var(--color-border);
  border-bottom: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

.um-search-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-md);
  background: var(--color-white);
  min-width: var(--space-40);
  max-width: var(--space-22);
  flex: 1;
  height: var(--space-1-875);
  box-sizing: border-box;
}

.um-search-icon {
  color: var(--color-text-placeholder);
  flex-shrink: 0;
}

.um-search {
  border: none;
  outline: none;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  background: transparent;
  width: 100%;
}

.um-search::placeholder {
  color: var(--color-text-placeholder);
}

.um-search-clear {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-placeholder);
  font-size: var(--font-size-lg);
  line-height: var(--line-height-none);
  padding: 0;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-lg);
  height: var(--space-lg);
  border-radius: var(--radius-sm);
  transition: color var(--motion-duration-fast) ease;
}

.um-search-clear:hover {
  color: var(--color-text-body);
}

.um-required-star {
  color: var(--color-danger);
  font-size: var(--font-size-sm);
  line-height: 1;
  margin-left: var(--space-px);
  font-weight: var(--font-weight-bold);
}

.um-toolbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-shrink: 0;
  flex-wrap: wrap;
}

/* ─── Edit toggle wrapper ───────────────────────────────── */
.um-edit-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: 0 var(--space-xs);
}

.um-edit-label {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  font-weight: var(--font-weight-medium);
}

/* ─── Buttons ───────────────────────────────────────────── */
.um-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1-5);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  padding: 0 var(--space-sm);
  height: var(--space-6-5);
  box-sizing: border-box;
  cursor: pointer;
  transition:
    background var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease,
    border-color var(--motion-duration-fast) ease;
  white-space: nowrap;
  border: var(--space-px) solid transparent;
  line-height: var(--line-height-none);
}

.um-btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--color-primary);
}

.um-btn--ghost:hover {
  opacity: 0.75;
}
.um-btn--ghost:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.um-btn--outline {
  background: var(--color-white);
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.um-btn--outline:hover {
  background: var(--color-bg-card-alt);
}

.um-btn--outline.um-btn--active {
  background: var(--color-bg-card-alt);
}

.um-btn--outline:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.um-btn--primary {
  background: var(--color-primary);
  color: var(--color-white);
  border-color: var(--color-primary);
}

.um-btn--primary:hover {
  opacity: 0.88;
}

.um-btn--primary:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.um-btn--icon {
  background: transparent;
  border-color: transparent;
  color: var(--color-text-body);
  padding: var(--space-xs) var(--space-xs);
}

.um-btn--icon:hover {
  color: var(--color-primary);
}

.um-btn--save {
  background: var(--color-white);
  color: var(--color-text-muted);
  border-color: var(--color-primary);
  padding: var(--space-xs) var(--space-xxl);
  font-weight: var(--font-weight-semibold);
}

.um-btn--save:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.um-btn--save-active {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.um-btn--save:disabled {
  opacity: 0.5;
  border-color: var(--color-primary);
  cursor: not-allowed;
}

/* ─── Table wrapper ─────────────────────────────────────── */
.um-table-wrap {
  margin-bottom: var(--space-md);
}

/* ─── Edit-mode cell inputs ─────────────────────────────── */
.um-cell-input {
  width: 100%;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  outline: none;
  background: var(--color-white);
  min-width: 0;
  height: var(--space-xxl);
  box-sizing: border-box;
}

.um-cell-input:focus {
  border-color: var(--color-primary);
}

/* ─── Table save overlay ────────────────────────────────── */
.um-table-wrap--relative {
  position: relative;
}

.um-table-overlay {
  position: absolute;
  inset: 0;
  background: var(--color-overlay-white, rgba(255, 255, 255, 0.6));
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  pointer-events: all;
}

.um-table-spinner {
  display: inline-block;
  width: var(--space-7);
  height: var(--space-7);
  border: 3px solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: um-spin 0.7s linear infinite;
}

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

/* ─── Delete button ─────────────────────────────────────── */
.um-del-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-danger);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-0-8);
  border-radius: var(--radius-sm);
  transition: background var(--motion-duration-fast) ease;
}

.um-del-btn:hover {
  background: var(--color-danger-bg);
}

.um-del-tooltip {
  position: fixed;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  white-space: normal;
  pointer-events: none;
  z-index: 9999;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  line-height: 1.5;
}

.um-del-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5));
  left: var(--um-arrow-left, 50%);
  transform: translateX(-50%);
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

.um-del-tooltip--above::before {
  top: auto;
  bottom: calc(-1 * var(--space-1-5));
  border-bottom: none;
  border-top: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* ─── Save footer ───────────────────────────────────────── */
.um-save-footer {
  display: flex;
  justify-content: flex-end;
  padding-top: var(--space-sm);
}

/* ─── Placeholder tab ───────────────────────────────────── */
.um-placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  padding: var(--space-4) 0;
}

.um-placeholder span {
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin-right: var(--space-1-5);
}

/* ─── Access denied ─────────────────────────────────────── */
.um-access-denied {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  padding: var(--space-4) var(--space-xxl);
  text-align: center;
}

.um-access-denied-icon {
  opacity: 0.5;
  flex-shrink: 0;
}

.um-access-denied-title {
  font-size: var(--font-size-xl);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  margin: 0;
}

.um-access-denied-desc {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  margin: 0;
  max-width: var(--space-28);
  line-height: var(--line-height-relaxed);
}

.um-access-denied-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary);
  background: none;
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-md);
  cursor: pointer;
  text-decoration: none;
  transition: background var(--motion-duration-fast) ease;
  margin-top: var(--space-xs);
}

.um-access-denied-back:hover {
  background: var(--color-bg-card-alt);
}

/* ─── Capabilities badge (Users tab) ────────────────────── */
.um-cap-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0-5) var(--space-sm);
  background: var(--color-bg-hover-light);
  border: var(--space-px) solid var(--color-chip-view-border);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs);
  color: var(--color-chip-view-text);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════
   BULK UPLOAD MODAL
═══════════════════════════════════════════════════════════ */

.bum-backdrop {
  position: fixed;
  inset: 0;
  background: var(--color-backdrop-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.bum-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  box-shadow: 0 var(--space-0-5) var(--space-xxl) var(--color-shadow-modal);
  width: min(var(--space-48), 92vw);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.bum-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-lg) var(--space-xl);
  border-bottom: var(--space-px) solid var(--color-border);
  flex-shrink: 0;
}

.bum-title {
  font-size: var(--font-size-lg);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
}

.bum-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xs);
  border-radius: var(--radius-sm);
  transition: color var(--motion-duration-fast) ease;
}

.bum-close:hover {
  color: var(--color-text-body);
}

.bum-close-icon,
.bum-download-icon {
  display: block;
  width: var(--space-lg);
  height: var(--space-lg);
  flex-shrink: 0;
}

.bum-body {
  padding: var(--space-xl);
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.bum-template-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background: var(--color-primary);
  color: var(--color-white);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--radius-sm);
  padding: var(--space-sm) var(--space-lg);
  text-decoration: none;
  transition: opacity var(--motion-duration-fast) ease;
  width: 100%;
  box-sizing: border-box;
}

.bum-template-btn:hover {
  opacity: 0.88;
}

.bum-dropzone {
  border: var(--space-0-5) dashed var(--color-border);
  border-radius: var(--radius-md);
  min-height: var(--space-16);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  cursor: pointer;
  transition:
    border-color var(--motion-duration-fast) ease,
    background var(--motion-duration-fast) ease;
  padding: var(--space-xl);
  text-align: center;
  box-sizing: border-box;
  position: relative;
}

.bum-dropzone:hover,
.bum-dropzone--drag {
  border-color: var(--color-primary);
  background: var(--color-lightblue);
}

.bum-dropzone--has-file {
  border-color: var(--color-primary);
}

.bum-file-input {
  position: absolute;
  inset: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
  cursor: pointer;
  display: none;
}

.bum-dropzone-icon {
  color: var(--color-primary);
  opacity: 0.7;
}

.bum-dropzone-text {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
}

.bum-dropzone-link {
  color: var(--color-primary);
  text-decoration: underline;
  cursor: pointer;
}

.bum-dropzone-hint {
  font-size: var(--font-size-xs);
  color: var(--color-text-placeholder);
}

.bum-results {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  min-height: var(--space-6-0);
}

.bum-results-summary {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
}

.bum-pill {
  display: inline-flex;
  align-items: center;
  padding: var(--space-xs) var(--space-md);
  border-radius: var(--radius-full);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-semibold);
}

.bum-pill--ok {
  background: var(--color-success-bg);
  color: var(--color-success);
}

.bum-pill--fail {
  background: var(--color-danger-bg);
  color: var(--color-danger);
}

.bum-error-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  max-height: var(--space-12-0);
  overflow-y: auto;
}

.bum-error-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-danger-bg);
  border-radius: var(--radius-sm);
}

.bum-error-row {
  color: var(--color-text-muted);
  flex-shrink: 0;
  white-space: nowrap;
}

.bum-error-email {
  font-weight: var(--font-weight-medium);
  color: var(--color-text-body);
  flex-shrink: 0;
}

.bum-error-msg {
  color: var(--color-danger);
  font-size: var(--font-size-sm);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bum-error-group {
  padding: var(--space-sm) 0;
  border-bottom: 1px solid var(--color-border);
}

.bum-error-group:last-child {
  border-bottom: none;
}

.bum-error-group-hd {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-xs);
}

.bum-error-group-count {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.bum-error-sublist {
  list-style: none;
  padding: 0 0 0 var(--space-md);
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.bum-file-error {
  margin: 0;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-danger);
  text-align: center;
}

.bum-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-lg) var(--space-xl);
  border-top: var(--space-px) solid var(--color-border);
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════
   USER ROLE TAB
═══════════════════════════════════════════════════════════ */

.ur-saving-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-overlay-white, rgba(255, 255, 255, 0.6));
  pointer-events: all;
  z-index: 10;
}

.ur-layout {
  display: flex;
  flex: 1;
  position: relative;
  gap: 0;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  min-width: 0;
  min-height: 0;
}

.ur-sidebar {
  width: clamp(var(--space-9), 18%, var(--space-56));
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  border-right: var(--space-px) solid var(--color-border);
  background: var(--color-lightgrey);
  min-width: 0;
  overflow: visible;
}

.ur-sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
  flex-shrink: 0;
  min-width: 0;
  overflow: hidden;
}

.ur-sidebar-title {
  font-size: var(--font-size-base);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.ur-new-btn {
  font-size: var(--font-size-sm) !important;
  padding: 0 var(--space-sm) !important;
  height: var(--space-7) !important;
  flex-shrink: 0;
}

.ur-sidebar-search {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-sm) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
  color: var(--color-text-placeholder);
  flex-shrink: 0;
  height: var(--space-2-25);
  min-width: 0;
  overflow: hidden;
}

.ur-sidebar-search-input {
  flex: 1;
  border: none;
  outline: none;
  background: transparent;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ur-sidebar-search-input::placeholder {
  color: var(--color-text-placeholder);
}

.ur-role-scroll {
  flex: 1;
  min-height: 0;
}

.ur-role-list {
  list-style: none;
  padding: var(--space-xs) 0;
}

.ur-role-empty {
  text-align: center;
  padding: var(--space-xl) var(--space-sm);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
}

.ur-role-list-item {
  display: flex;
  align-items: stretch;
  position: relative;
}

.ur-role-del-btn {
  flex-shrink: 0;
  align-self: center;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-danger);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xs);
  margin-right: var(--space-sm);
  border-radius: var(--radius-sm);
  transition: background var(--motion-duration-fast) ease;
}

.ur-role-del-btn:hover {
  background: var(--color-danger-bg);
}
.ur-role-del-btn:disabled {
  opacity: 0.3;
  pointer-events: none;
}

.ur-role-del-wrap {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  align-self: center;
}

.ur-role-del-wrap--disabled {
  cursor: not-allowed;
}

.ur-role-list-item .ur-role-item {
  flex: 1;
  min-width: 0;
}

.ur-role-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  width: 100%;
  padding: var(--space-sm) var(--space-lg);
  background: none;
  border: none;
  cursor: pointer;
  min-width: 0;
  overflow: hidden;
  text-align: left;
  transition: background var(--motion-duration-fast) ease;
  gap: var(--space-sm);
}

.ur-role-item:hover {
  background: var(--color-bg-hover-light);
}
.ur-role-item--active {
  background: var(--color-lightblue);
}
.ur-role-item--active:hover {
  background: var(--color-lightblue);
}

.ur-role-item-main {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.ur-role-item-name {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-base);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ur-role-item-desc {
  margin-top: var(--space-px);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: var(--line-height-normal);
}

.ur-role-item-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-px);
  flex-shrink: 0;
  min-width: var(--space-4);
}

.ur-role-item-caps,
.ur-role-item-users {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  white-space: nowrap;
}

.ur-tag-system {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-wider);
  color: var(--color-white);
  background: var(--color-primary);
  border-radius: var(--radius-sm);
  padding: var(--space-px) var(--space-xs);
  flex-shrink: 0;
}

.ur-dot-dirty {
  display: inline-block;
  width: var(--space-0-45);
  height: var(--space-0-45);
  border-radius: var(--radius-full);
  background: var(--color-error);
  flex-shrink: 0;
}

/* ── Editor ──────────────────────────────────────────────── */
.ur-editor {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--color-white);
}

.ur-editor-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-xl);
  border-bottom: var(--space-px) solid var(--color-border);
  flex-shrink: 0;
  background: var(--color-bg-card-alt);
  overflow: hidden;
  min-width: 0;
}

.ur-editor-head-left {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.ur-editor-eyebrow {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-eyebrow);
}

.ur-editor-name {
  font-size: clamp(var(--font-size-lg), 2.5vw, var(--font-size-2xl));
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-bold);
  color: var(--color-primary);
  border: none;
  outline: none;
  background: transparent;
  width: 100%;
  padding: 0;
  line-height: var(--line-height-tight);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ur-editor-name:disabled {
  cursor: default;
  opacity: 0.85;
}
.ur-editor-name:not(:disabled):focus {
  border-bottom: var(--space-0-5) solid var(--color-primary);
}

.ur-editor-desc {
  font-size: var(--font-size-base);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  border: none;
  outline: none;
  background: transparent;
  width: 100%;
  padding: 0;
  line-height: var(--line-height-normal);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ur-editor-desc:focus {
  border-bottom: var(--space-px) solid var(--color-input-border);
}
.ur-editor-desc::placeholder {
  color: var(--color-text-placeholder);
}

.ur-editor-stats {
  display: flex;
  gap: var(--space-lg);
  flex-shrink: 0;
  align-items: center;
  overflow: hidden;
}

.ur-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  min-width: var(--space-3-5rem);
}

.ur-stat-num {
  font-size: clamp(var(--font-size-2xl), 3vw, var(--font-size-4xl));
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-bold);
  color: var(--color-primary);
  line-height: var(--line-height-none);
}

.ur-stat-num--dirty {
  color: var(--color-error);
}

.ur-stat-lbl {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  white-space: nowrap;
  text-align: center;
}

.ur-cap-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-xl);
  border-bottom: var(--space-px) solid var(--color-border);
  flex-shrink: 0;
  min-height: var(--space-11);
  flex-wrap: wrap;
}

.ur-cap-search {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-white);
  max-width: var(--space-24);
  flex: 1;
  color: var(--color-text-placeholder);
  height: var(--space-2);
}

.ur-cap-search-input {
  flex: 1;
  border: none;
  outline: none;
  background: transparent;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  min-width: 0;
}

.ur-cap-search-input::placeholder {
  color: var(--color-text-placeholder);
}

.ur-cap-search-clear {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--font-size-xl);
  line-height: var(--line-height-none);
  padding: 0;
  flex-shrink: 0;
}

.ur-cap-toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-shrink: 0;
}

.ur-link-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-primary);
  text-decoration: underline;
  padding: 0;
}

.ur-link-btn:hover {
  opacity: 0.75;
}

.ur-dot-sep {
  color: var(--color-text-placeholder);
  font-size: var(--font-size-base);
  user-select: none;
}

.ur-cap-list {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
  max-height: none;
  overscroll-behavior: contain;
  background: var(--color-lightgrey);
  scrollbar-width: none;
}

.ur-cap-list::-webkit-scrollbar {
  display: none;
}

.ur-cap-empty {
  text-align: center;
  padding: var(--space-xxl);
  font-size: var(--font-size-base);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
}

.ur-feature {
  border-bottom: var(--space-px) solid var(--color-border);
  background: var(--color-white);
}

.ur-feature-head {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-lg);
  cursor: pointer;
  background: var(--color-white);
  transition: background var(--motion-duration-fast) ease;
  min-height: var(--space-11);
  min-width: 0;
  overflow: hidden;
  position: relative;
}

.ur-feature-head:hover {
  background: var(--color-bg-hover-light);
}

.ur-feature-disclose {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-5);
  height: var(--space-5);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  transition: transform var(--motion-duration-fast) ease;
}

.ur-feature--open .ur-feature-disclose svg {
  transform: rotate(0deg);
}
.ur-feature:not(.ur-feature--open) .ur-feature-disclose svg {
  transform: rotate(-90deg);
}

.ur-feature-info {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.ur-feature-title {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  margin: 0;
  line-height: var(--line-height-snug);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ur-feature-desc {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  margin: var(--space-px) 0 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: var(--line-height-normal);
}

.ur-feature-meta {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-shrink: 0;
  overflow: hidden;
}

.ur-screen-status {
  font-size: var(--font-size-xs);
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
  line-height: 1.4;
}
.ur-screen-status--on {
  background: #e6f4ea;
  color: #1e7e34;
}
.ur-screen-status--off {
  background: #f1f1f3;
  color: #8a8a93;
}

.ur-feature-count {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
}

.ur-feature-count-total {
  color: var(--color-text-muted);
  font-weight: var(--font-weight-regular);
}

.ur-badge-dirty {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  background: var(--color-warning-bg-tint);
  color: var(--color-error);
  border-radius: var(--radius-sm);
  padding: var(--space-px) var(--space-xs);
  white-space: nowrap;
}

.ur-bulk-btn {
  background: var(--color-white);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  cursor: pointer;
  white-space: nowrap;
  transition:
    border-color var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
}

.ur-bulk-btn:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}
.ur-bulk-btn--on {
  border-color: var(--color-danger);
  color: var(--color-danger);
}
.ur-bulk-btn--mixed {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.ur-feature-body {
  background: var(--color-white);
  padding: var(--space-xs) 0 var(--space-md);
}

.ur-subrow {
  display: block;
  padding: var(--space-sm) var(--space-lg) var(--space-sm) var(--space-10);
  min-height: 0;
  overflow: visible;
}

.ur-subrow + .ur-subrow {
  border-top: none;
  margin-top: var(--space-sm);
}

.ur-subrow-name {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  width: clamp(var(--space-6-0), 20%, var(--space-11-0));
  flex-shrink: 0;
  min-width: 0;
  overflow: hidden;
}

.ur-subrow-tri {
  display: none;
}

.ur-subrow-label {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-body);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: var(--line-height-normal);
  min-width: 0;
}

.ur-subrow-count {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-placeholder);
  white-space: nowrap;
  flex-shrink: 0;
}

.ur-subrow-actions {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  flex-wrap: wrap;
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.ur-cap-tree {
  display: block;
  width: 100%;
  min-width: 0;
}

.ur-cap-node-row {
  display: grid;
  grid-template-columns: minmax(var(--space-12-0), 1fr) auto;
  align-items: center;
  gap: var(--space-lg);
  min-height: var(--space-2-35);
  min-width: 0;
  position: relative;
}

.ur-cap-node-main,
.ur-cap-node-actions {
  display: flex;
  align-items: center;
  min-width: 0;
}

.ur-cap-node-main {
  gap: var(--space-sm);
}

.ur-cap-node-actions {
  gap: var(--space-sm);
  flex-wrap: wrap;
  justify-content: flex-end;
}

.ur-cap-node-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-lg);
  height: var(--space-lg);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  flex-shrink: 0;
}

.ur-cap-node-toggle:disabled {
  cursor: default;
  opacity: 0;
}

.ur-cap-node-chevron {
  display: block;
  width: var(--space-2-5);
  height: var(--space-2-5);
  transform: rotate(0deg);
  transition: transform var(--motion-duration-fast) ease;
}

.ur-cap-tree--closed > .ur-cap-node-row .ur-cap-node-chevron {
  transform: rotate(-90deg);
}

.ur-cap-node-label {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-heading);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ur-cap-node-row--child .ur-cap-node-label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
}

.ur-cap-node-count {
  border-radius: var(--radius-full);
  background: var(--color-bg-card-alt);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-none);
  padding: var(--space-px) var(--space-xs);
  white-space: nowrap;
}

.ur-cap-tree-children {
  margin-left: var(--space-sm);
  padding-left: var(--space-2-25);
  padding-top: var(--space-sm);
  position: relative;
  transition:
    opacity var(--motion-duration-fast) ease,
    max-height var(--motion-duration-fast) ease;
}

.ur-cap-tree--closed > .ur-cap-tree-children {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  padding-top: 0;
}

.ur-cap-tree--open > .ur-cap-tree-children {
  max-height: 2000px;
  opacity: 1;
}

.ur-cap-tree-children::before {
  content: "";
  position: absolute;
  left: var(--space-sm);
  top: 0;
  bottom: var(--space-1-2rem);
  width: var(--space-px);
  background: var(--color-border);
}

.ur-cap-tree-branch {
  position: relative;
}

.ur-cap-node-row--child::before {
  content: "";
  position: absolute;
  left: calc(var(--space-7) * -1);
  top: 50%;
  width: var(--space-5);
  height: var(--space-px);
  background: var(--color-border);
}

.ur-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  border-radius: var(--radius-md);
  border: var(--space-px) solid var(--color-border);
  padding: var(--space-px) var(--space-sm);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition:
    opacity var(--motion-duration-fast) ease,
    border-color var(--motion-duration-fast) ease;
  white-space: nowrap;
  line-height: var(--line-height-none);
  user-select: none;
  min-height: var(--space-7);
}

.ur-chip--locked {
  cursor: default;
  opacity: 0.65;
}
.ur-chip--readonly {
  cursor: not-allowed;
  opacity: 0.55;
}

.ur-chip-dot {
  width: var(--space-0-35);
  height: var(--space-0-35);
  border-radius: var(--radius-full);
  flex-shrink: 0;
}

.ur-chip-lock {
  font-size: var(--font-size-xs);
  opacity: 0.6;
}

.ur-chip--off {
  background: var(--color-white);
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

.ur-chip--off .ur-chip-dot {
  background: var(--color-text-placeholder);
}
.ur-chip--off:hover:not(.ur-chip--locked) {
  border-color: var(--color-input-border);
  color: var(--color-text-body);
}

.ur-chip--view.ur-chip--on {
  background: var(--color-white);
  border-color: var(--color-chip-view-border);
  color: var(--color-chip-view-text);
}
.ur-chip--view.ur-chip--on .ur-chip-dot {
  background: var(--color-chip-view-text);
}

.ur-chip--edit.ur-chip--on {
  background: var(--color-white);
  border-color: var(--color-warning-border);
  color: var(--color-warning);
}
.ur-chip--edit.ur-chip--on .ur-chip-dot {
  background: var(--color-warning);
}

.ur-chip--interact.ur-chip--on {
  background: var(--color-white);
  border-color: var(--color-chip-interact-border);
  color: var(--color-chip-interact-text);
}
.ur-chip--interact.ur-chip--on .ur-chip-dot {
  background: var(--color-chip-interact-text);
}

.ur-chip--action.ur-chip--on {
  background: var(--color-white);
  border-color: var(--color-chip-action-border);
  color: var(--color-chip-action-text);
}
.ur-chip--action.ur-chip--on .ur-chip-dot {
  background: var(--color-chip-action-text);
}

.ur-chip-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
}

.ur-chip-key {
  font-family: var(--font-family-mono);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  background: var(--color-lightgrey);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-px) var(--space-xs);
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: var(--line-height-relaxed);
  letter-spacing: var(--letter-spacing-wide);
}

.ur-chip-wrap--dirty .ur-chip {
  outline: var(--space-px) dashed var(--color-error);
  outline-offset: var(--space-0-4);
}

.ur-chip-status {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  padding: var(--space-0-4) var(--space-sm);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-snug);
  white-space: nowrap;
  flex-shrink: 0;
  cursor: help;
}

.ur-chip-status--deprecated {
  background: var(--color-chip-deprecated-bg);
  color: var(--color-chip-deprecated-text);
}

.ur-chip-status--removed {
  background: var(--color-chip-removed-bg);
  color: var(--color-chip-removed-text);
  text-decoration: line-through;
}

.ur-chip--deprecated {
  opacity: 0.85;
}

/* ── Editor footer ───────────────────────────────────────── */
.ur-editor-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-xl);
  border-top: var(--space-px) solid var(--color-border);
  background: var(--color-white);
  flex-shrink: 0;
  gap: var(--space-md);
  transition: background var(--motion-duration-fast) ease;
  min-height: var(--space-12);
}

.ur-editor-foot--dirty {
  background: var(--color-warning-bg);
  border-top-color: var(--color-warning-border);
}

.ur-foot-status {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  line-height: var(--line-height-normal);
}

.ur-foot-saved {
  color: var(--color-text-muted);
}
.ur-foot-readonly {
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  font-style: italic;
}

.ur-foot-error {
  color: var(--color-danger);
  font-size: var(--font-size-xs);
}

.ur-foot-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  flex-shrink: 0;
}

/* ─── Editable wrap ─────────────────────────────────────── */
.ur-editable-wrap {
  position: relative;
  display: flex;
  align-items: center;
  width: fit-content;
  max-width: 100%;
}


.ur-edit-hint {
  opacity: 1;
  margin-left: var(--space-xs);
  color: var(--color-text-placeholder);
  flex-shrink: 0;
}

.ur-edit-hint-icon {
  display: block;
  width: var(--space-md);
  height: var(--space-md);
  flex-shrink: 0;
}

.ur-input-mirror {
  position: absolute;
  visibility: hidden;
  white-space: pre;
  pointer-events: none;
}

.ur-input-mirror--name {
  font-size: clamp(var(--font-size-lg), 2.5vw, var(--font-size-2xl));
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-bold);
}

.ur-input-mirror--desc {
  font-size: var(--font-size-base);
  font-family: var(--font-family-base);
}

/* ─── Desc / delete tooltip ─────────────────────────────── */
.ur-desc-tooltip {
  position: fixed;
  z-index: 9999;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  pointer-events: none;
  max-width: 240px;
  white-space: normal;
  line-height: 1.5;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
}

.ur-desc-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5));
  left: var(--ur-arrow-left, 50%);
  transform: translateX(-50%);
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

.ur-desc-tooltip--above::before {
  top: auto;
  bottom: calc(-1 * var(--space-1-5));
  border-bottom: none;
  border-top: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* ═══════════════════════════════════════════════════════════
   CAPABILITIES CATALOG TAB
═══════════════════════════════════════════════════════════ */

.uc-layout {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 0;
  min-height: 0;
}

.uc-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-xl);
  padding: var(--space-lg) 0 var(--space-md);
  flex-wrap: wrap;
}

.uc-header-left {
  flex: 1;
  min-width: 0;
}

.uc-title {
  font-size: var(--font-size-3xl);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-bold);
  color: var(--color-primary);
  margin: 0 0 var(--space-xs);
  line-height: var(--line-height-tight);
}

.uc-subtitle {
  font-size: var(--font-size-base);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  margin: 0;
  line-height: var(--line-height-relaxed);
}

.uc-header-stats {
  display: flex;
  gap: var(--space-xl);
  flex-shrink: 0;
  align-items: center;
  flex-wrap: wrap;
}

.uc-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: 0 0 var(--space-md);
  border-bottom: var(--space-px) solid var(--color-border);
  flex-wrap: wrap;
}

.uc-search {
  max-width: var(--space-28) !important;
  flex: 1;
}

.uc-result-count {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.uc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--space-22), 1fr));
  gap: var(--space-lg);
  padding: var(--space-lg) 0 var(--space-10);
  overflow: visible;
  max-height: none;
}

/* Ensure CustomScrollbar controls scrolling for capabilities catalog */
.uc-custom-scrollbar {
  height: auto;
  max-height: calc(100vh - var(--space-20-0));
}

.uc-card {
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-white);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.uc-card-head {
  padding: var(--space-md) var(--space-lg);
  background: var(--color-bg-card-alt);
  border-bottom: var(--space-px) solid var(--color-border);
}

.uc-card-head-main {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-bottom: var(--space-xs);
}

.uc-card-title {
  font-size: var(--font-size-base);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
  line-height: var(--line-height-snug);
}

.uc-card-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--space-xl);
  height: var(--space-xl);
  padding: 0 var(--space-xs);
  background: var(--color-lightblue);
  border-radius: var(--radius-full);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  flex-shrink: 0;
}

.uc-card-desc {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  margin: 0;
  line-height: var(--line-height-normal);
}

.uc-card-body {
  flex: 1;
  padding: var(--space-sm) 0;
}

.uc-sub {
  padding: 0 var(--space-lg) var(--space-sm);
}

.uc-sub:not(:first-child) {
  border-top: var(--space-px) solid var(--color-border);
  padding-top: var(--space-sm);
  margin-top: var(--space-xs);
}

.uc-sub-label {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  margin-bottom: var(--space-xs);
  line-height: var(--line-height-snug);
}

.uc-tree-node {
  margin-top: var(--space-xs);
  padding-left: var(--space-md);
  border-left: var(--space-px) solid var(--color-border);
}

.uc-tree-label {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-muted);
  line-height: var(--line-height-snug);
  margin-bottom: var(--space-xs);
}

.uc-tree-actions {
  min-width: 0;
}

.uc-action-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-xs) 0;
  border-bottom: var(--space-px) solid var(--color-bg-card-alt);
}

.uc-action-row:last-child {
  border-bottom: none;
}

.uc-action-label {
  flex: 1;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-text-body);
  line-height: var(--line-height-normal);
  min-width: 0;
}

.uc-action-key {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-mono);
  color: var(--color-text-muted);
  background: var(--color-lightgrey);
  border-radius: var(--radius-sm);
  padding: var(--space-px) var(--space-xs);
  white-space: nowrap;
  flex-shrink: 0;
  max-width: var(--space-12-0);
  overflow: hidden;
  text-overflow: ellipsis;
}

.uc-implies {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  color: var(--color-text-placeholder);
  white-space: nowrap;
  flex-shrink: 0;
  cursor: help;
}

.uc-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: var(--space-xxl);
  font-size: var(--font-size-base);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
}

/* NOTE: CSS media features can't reference custom properties (var(--space-48)
   is not a valid media condition and this query never matched in any
   browser) — pinned to the literal px value the token resolves to (48rem). */
@media (max-width: 48rem) {
  .ur-cap-node-row {
    grid-template-columns: 1fr;
    gap: var(--space-sm);
  }

  .ur-cap-node-actions {
    justify-content: flex-start;
    padding-left: var(--space-2-2);
  }
}

/* ── Responsive: two-pane role editor ─────────────────────
   Sidebar + editor sit side by side (.ur-layout, display:flex) sized for
   desktop. Stack them on narrower viewports instead of squeezing both
   panes past readability. */
@media (max-width: 48rem) {
  .ur-layout {
    flex-direction: column;
  }

  .ur-sidebar {
    width: 100%;
    max-height: 40vh;
    border-right: none;
    border-bottom: var(--space-px) solid var(--color-border);
  }

  .ur-editor {
    min-height: 50vh;
  }
}

/* ── Responsive: toolbar search width ──────────────────────
   Fixed max-width kept the search box needlessly narrow once the
   toolbar has already wrapped onto its own line on small screens. */
@media (max-width: 40rem) {
  .um-search-wrap {
    max-width: none;
    width: 100%;
  }
}
.hs-wrap {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-sm);
  width: fit-content;
  min-width: var(--hs-min-w, var(--space-60));
  max-width: var(--hs-max-w, none);
}

.hs-label {
  position: absolute;
  top: calc(var(--space-px) * -8);
  left: var(--space-md);
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  background: var(--color-white);
  padding: 0 var(--space-0-8);
  white-space: nowrap;
  pointer-events: none;
  z-index: 1;
  max-width: calc(100% - var(--space-md));
  overflow: visible;
}

/* ── Trigger ─────────────────────────────────────────────── */
.hs-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  background: transparent;
  border: none;
  cursor: pointer;
  padding: var(--space-xs) var(--space-sm);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  color: var(--color-black);
  min-width: var(--space-8);
  text-align: left;
  width: 100%;
  transition: border-color var(--motion-duration-fast) ease;
}

.hs-trigger--open,
.hs-trigger:hover {
  border-color: var(--color-primary);
}

.hs-trigger-label {
  display: none;
}

.hs-trigger-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  min-width: 0;
  width: 100%;
}

.hs-trigger-value {
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  color: var(--color-black);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}

.hs-trigger-chevron {
  display: flex;
  align-items: center;
  color: var(--color-text-muted);
  flex-shrink: 0;
  transition: transform var(--motion-duration-fast) ease;
}

.hs-trigger-chevron--open {
  transform: rotate(180deg);
}

/* ── Dropdown panel ──────────────────────────────────────── */
/* Rendered through a portal to document.body (see useDropdownPosition) so it
   can't be visually clipped by an ancestor with overflow:hidden (e.g. a
   chart card) — position/top/bottom/right/min-width are all set inline per
   instance from the hook's fixed-viewport-coordinate calculation. */
.hs-dropdown {
  width: max-content;
  max-width: var(--space-105); /* 26.25rem = 420px */
  background: var(--color-white);
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-sm);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-dropdown);
  z-index: 9999;
  overflow: hidden;
}

/* ── Search ──────────────────────────────────────────────── */
.hs-search-wrap {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-md) var(--space-sm);
  border-bottom: var(--space-px) solid var(--color-border);
  background: var(--color-white);
}

.hs-search-icon {
  display: flex;
  align-items: center;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.hs-search {
  flex: 1;
  border: none;
  outline: none;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  color: var(--color-text-body);
  background: transparent;
  min-width: 0;
}

.hs-search::placeholder {
  color: var(--color-text-muted);
}

.hs-search-clear {
  border: none;
  background: none;
  cursor: pointer;
  color: var(--color-text-muted);
  font-size: var(--font-size-md);
  line-height: var(--line-height-none);
  padding: 0 var(--space-0-5);
  display: flex;
  align-items: center;
}

.hs-search-clear:hover {
  color: var(--color-text-body);
}

/* ── Match highlight ─────────────────────────────────────── */
.hs-highlight {
  background: var(--color-subtleblue);
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--space-0-5);
  padding: 0 var(--space-px);
}

/* ── Tree scroll area padding ────────────────────────────── */
.hs-dropdown .dsl-list {
  padding: var(--space-0-5) 0;
}

/* ── No results ──────────────────────────────────────────── */
.hs-no-results {
  padding: var(--space-sm) var(--space-md);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  text-align: center;
  margin: 0;
}

/* ── Group header ────────────────────────────────────────── */
.hs-group-header {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  width: 100%;
  padding: var(--space-sm) var(--space-md);
  padding-left: calc(var(--space-sm) + var(--hs-depth, 0) * var(--space-3-5));
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  color: var(--color-violet);
  font-weight: var(--font-weight-medium);
  transition: background var(--motion-duration-fast) ease;
}

.hs-group-header:hover {
  background: var(--color-lightgrey);
}

.hs-group-chevron {
  display: flex;
  align-items: center;
  color: var(--color-text-muted);
  transition: transform var(--motion-duration-fast) ease;
  flex-shrink: 0;
}

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

/* ── Icon sizes ──────────────────────────────────────────── */
.hs-search-icon-svg {
  display: block;
  width: var(--space-3-25);  /* 0.8125rem = 13px */
  height: var(--space-3-25);
  flex-shrink: 0;
}

.hs-chevron-right {
  display: block;
  width: var(--space-2-5);   /* 0.625rem = 10px */
  height: var(--space-2-5);
}

.hs-trigger-chevron-icon {
  display: block;
  width: var(--space-sm);    /* 0.5rem = 8px */
  height: var(--space-1-5);  /* 0.375rem = 6px */
  flex-shrink: 0;
}

/* ── Leaf item ───────────────────────────────────────────── */
.hs-leaf {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  width: 100%;
  padding: var(--space-sm) var(--space-md);
  padding-left: calc(var(--space-sm) + var(--space-3-5) + var(--hs-depth, 0) * var(--space-3-5));
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  color: var(--color-violet);
  transition: background var(--motion-duration-fast) ease;
}

.hs-leaf:hover {
  background: var(--color-lightgrey);
}

/* ── Briefly highlight the selected option when the dropdown opens ─ */
@keyframes hs-leaf-pulse {
  0% {
    background: var(--color-subtleblue);
  }
  100% {
    background: transparent;
  }
}

.hs-leaf--pulse {
  animation: hs-leaf-pulse 0.9s ease-out;
}

/* ── Radio indicator ─────────────────────────────────────── */
.hs-radio {
  --hs-radio-size: var(--space-3-25); /* 0.8125rem = 13px */
  --hs-radio-border: 0.09375rem; /* 1.5px */
  width: var(--hs-radio-size);
  height: var(--hs-radio-size);
  border-radius: 50%;
  border: var(--hs-radio-border) solid var(--color-violet);
  flex-shrink: 0;
  display: inline-block;
}

.hs-radio--selected {
  border-color: var(--color-violet);
  background: var(--color-primary);
  box-shadow: inset 0 0 0 var(--space-0-8) var(--color-white); /* ~3px inset ring */
}
.mia-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  /* Without this, the FilterBar's dropdown panel (position: absolute,
     up to --space-22 tall) can extend past this page's own 100vh box —
     since nothing here clips it, the browser adds a genuine page-level
     scrollbar to reveal the overflow the moment the panel opens, on top
     of .mia-body's own CustomScrollbar. .um-page already has this; the
     other pages using FilterBar were missing it. */
  overflow: hidden;
}

.mia-page .app-tabs-wrapper {
  position: static;
}

.mia-page .fb-wrapper {
  position: relative;
  top: 0;
  background: var(--color-white);
  border-bottom: none;
  margin: 0;
}

.mia-filter-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-lg);
}

.mia-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0;
}

.mia-body {
  flex: 1;
  min-height: 0;
}

.mia-body-content {
  padding: 0 var(--space-lg) var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ── KPI row ─────────────────────────────────────────────── */
.mia-kpi-note {
  text-align: right;
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  font-family: var(--font-family-base);
  padding: 0 var(--space-md);
  padding-top: var(--space-sm);
  margin-bottom: calc(var(--space-sm) * -1);
}

.mia-kpi-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-md);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding: 0 var(--space-md) var(--space-md);
  padding-bottom: var(--space-xs);
}

.mia-kpi-row::-webkit-scrollbar {
  display: none;
}

.mia-kpi-row .kpi-card {
  min-width: var(--space-35);
  flex: 1 0 var(--space-35);
  scroll-snap-align: start;
}

/* ── Two-column charts row ───────────────────────────────── */
.mia-charts-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  align-items: stretch;
}

.mia-chart-half {
  background: var(--color-white);
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.mia-chart-half:first-child {
  border-right: var(--space-px) solid var(--color-kpigrey);
}

.mia-chart-half:only-child {
  border-right: none;
}

.mia-charts-row:has(.mia-chart-half:only-child) {
  grid-template-columns: 1fr;
}

.mia-chart-inner {
  position: relative;
  min-width: var(--space-34);
  padding: var(--space-md) var(--space-md) 0;
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--space-xs);
}

.mia-media-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.75);
  z-index: 10;
  border-radius: var(--radius-sm);
}

/* ── Full-width chart ────────────────────────────────────── */
.mia-chart-full {
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding: var(--space-xs) var(--space-md) 0;
  gap: var(--space-xs);
}

/* ── Chart header ────────────────────────────────────────── */
.mia-chart-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-md);
  flex-wrap: nowrap;
}

.mia-chart-header > div:first-child {
  flex: 1;
  min-width: 0;
}

.mia-chart-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  white-space: nowrap;
}

.mia-chart-subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  margin: var(--space-px) 0 0;
  font-family: var(--font-family-base);
}

/* ── Chart actions ───────────────────────────────────────── */
.mia-chart-actions {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  flex-shrink: 0;
  flex-wrap: nowrap;
}

.mia-chart-actions--stack {
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-xs);
}

.mia-chart-actions-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.mia-chart-actions-row--end {
  justify-content: flex-end;
  padding-top: var(--space-2-5);
}

.mia-chart-actions .hs-wrap {
  max-width: var(--space-13-75);
  min-width: var(--space-9-375);
}

/* ── Toggle group ────────────────────────────────────────── */
.mia-toggle-group {
  display: flex;
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex-shrink: 0;
}

.mia-toggle {
  padding: var(--space-xs) var(--space-2-5);
  background: none;
  border: none;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  font-family: var(--font-family-base);
  color: var(--color-primary);
  cursor: pointer;
  transition:
    background var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
  white-space: nowrap;
}

.mia-toggle--active {
  background: var(--color-primary);
  color: var(--color-white);
}

/* ── Icon button ─────────────────────────────────────────── */
.mia-icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-primary);
  padding: var(--space-0-8);
  display: flex;
  align-items: center;
  border-radius: var(--radius-sm);
  transition:
    color var(--motion-duration-fast) ease,
    background var(--motion-duration-fast) ease;
}

.mia-icon-btn:hover {
  background: var(--color-bg-hover-light);
}

/* ── Bubble chart legend ─────────────────────────────────── */
.mia-bubble-legend {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-xs);
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
}

.mia-bubble-legend-dot {
  width: var(--space-md);
  height: var(--space-md);
  border-radius: 50%;
  border: var(--space-px) solid var(--color-kpigrey);
  background: transparent;
  display: inline-block;
}

/* ── Platform dropdown row ───────────────────────────────── */
.mia-platform-dropdown-row {
  display: flex;
  justify-content: flex-end;
}

/* ── Campaign Efficiency chart wrap ──────────────────────── */
.mia-eff-chart-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* ── Campaign efficiency funnel no-data placeholder ─────── */
.mia-eff-no-funnel {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 8rem;
  background: var(--color-lightgrey);
  border-radius: var(--radius-sm);
}

.mia-eff-no-funnel-text {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  text-align: center;
  padding: var(--space-md);
}

/* ── Campaign KPI grid ───────────────────────────────────── */
.mia-kpi-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
}

.mia-kpi-grid-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--color-lightgrey);
  border-radius: var(--radius-sm);
  padding: var(--space-sm) var(--space-md);
  gap: var(--space-md);
}

.mia-kpi-grid-label {
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-family: var(--font-family-base);
}

.mia-kpi-grid-value {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  font-family: var(--font-family-display);
}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 1200px) {
  .mia-kpi-row {
    flex-wrap: wrap;
  }
}

/* Below ~600px, flex-wrap's natural reflow depends on each card's own
   min-width vs. the exact remaining space, which can land on 1-per-row
   (a lot of dead space beside each card) as often as 2. Switch to an
   explicit 2-column grid so mobile always gets a predictable 2-and-2
   layout; an odd trailing card spans both columns instead of leaving an
   empty cell beside it. */
@media (max-width: 600px) {
  .mia-kpi-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  .mia-kpi-row .kpi-card:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 1024px) {
  .mia-charts-row {
    grid-template-columns: 1fr;
  }

  .mia-chart-half:first-child {
    border-right: none;
    border-bottom: var(--space-px) solid var(--color-kpigrey);
  }
}

/* .mia-kpi-grid (Campaign Efficiency's embedded KPI grid) lives inside
   .mia-chart-half, one column of the 2-up .mia-charts-row above. A plain
   @media query can only see the viewport, not this card's actual rendered
   width — so a breakpoint tied to "narrow viewport" alone would leave the
   grid stuck at 2 columns for the whole range where the row is still
   2-up but each half is only ~450–550px (roughly 1024–1300px viewport),
   which is genuinely cramped for label+value KPI pairs. Collapsing at the
   same 1024px breakpoint as the parent row guarantees the grid is never
   forced into 2 columns while its own card is still half-width. */
@media (max-width: 1024px) {
  .mia-kpi-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  /* .mia-chart-title has white-space: nowrap AND display: flex (for icon
     alignment) — text-overflow: ellipsis silently does not apply to a
     flex container's content, so this never actually truncated anything;
     the title just kept its full width and rendered underneath/behind the
     toggle group and table/download icons sitting beside it in
     .mia-chart-actions. Wrap the header instead — the same fix already
     used for .ir-chart-header's dropdown — so the title gets its own full
     row and the actions (toggle group + icons) drop to a row below
     whenever they don't both fit on one line. */
  .mia-chart-header {
    flex-wrap: wrap;
  }

  .mia-chart-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
    flex: 1 0 100%;
  }
}
.pd-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ── Section ─────────────────────────────────────────────── */
.pd-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.pd-section-title {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
  margin: 0;
}

.pd-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
}

/* ── Performance Highlights ──────────────────────────────── */
.pd-highlights-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
}

.pd-highlight-card {
  background: var(--color-white);
  border: var(--space-px) solid var(--color-highlight-card-border);
  border-radius: var(--radius-sm);
  padding: var(--space-sm) var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
}

.pd-highlight-card:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.pd-highlight-header {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  color: var(--color-black);
}

.pd-highlight-emoji {
  font-size: var(--font-size-xl);
  line-height: var(--line-height-none);
}

.pd-highlight-user {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary);
  font-family: var(--font-family-display);
  margin-top: var(--space-0-5);
}

.pd-highlight-desc {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
}

.pd-highlight-value {
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  margin-top: var(--space-0-5);
}

.pd-highlight-value-label {
  color: var(--color-text-muted);
}

/* ── Campaign Overview ───────────────────────────────────── */
.pd-metrics-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-sm);
}

.pd-metric-card {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  background: var(--color-white);
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-sm);
  padding: var(--space-sm) var(--space-md);
}

.pd-metric-card:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.pd-metric-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.pd-metric-icon-svg {
  display: block;
  width: var(--space-5);
  height: var(--space-5);
  flex-shrink: 0;
}

.pd-metric-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-0-5);
  min-width: 0;
}

.pd-metric-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
  white-space: nowrap;
}

.pd-metric-value {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
}

/* ── Key Performance Insights ────────────────────────────── */
.pd-insights-section {
  background: var(--color-bg-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.pd-insights-header {
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
}

.pd-insights-title {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
  margin: 0;
}

.pd-insights-subtitle {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
  margin: 0;
}

.pd-insights-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: var(--space-sm);
}

.pd-insight-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-xs);
}

.pd-insight-item:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

.pd-insight-circle {
  width: var(--space-11);
  height: var(--space-11);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-white);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  flex-shrink: 0;
}

.pd-insight-title {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  font-family: var(--font-family-display);
}

.pd-insight-desc {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
  line-height: var(--line-height-relaxed);
}

/* ── Responsive ─────────────────────────────────────────────
   This dashboard renders inside .ir-split-right, which itself collapses
   to full page width on narrow viewports (see InfluencerROI.css) — at
   that point its fixed 4-and-3-column grids get too cramped. */
@media (max-width: 600px) {
  .pd-metrics-row {
    grid-template-columns: repeat(2, 1fr);
  }

  .pd-insights-row {
    grid-template-columns: 1fr;
  }
}
.ir-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  /* Without this, the FilterBar's dropdown panel (position: absolute,
     up to --space-22 tall) can extend past this page's own 100vh box —
     since nothing here clips it, the browser adds a genuine page-level
     scrollbar to reveal the overflow the moment the panel opens, on top
     of .ir-body's own CustomScrollbar. .um-page already has this; the
     other pages using FilterBar were missing it. */
  overflow: hidden;
}

.ir-page .app-tabs-wrapper {
  position: static;
}

.ir-page .fb-wrapper {
  position: relative;
  top: 0;
  background: var(--color-white);
  border-bottom: none;
  margin: 0;
}

.ir-filter-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-lg);
}

.ir-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0;
}

.ir-body {
  flex: 1;
  min-height: 0;
}

.ir-body-content {
  padding: 0 var(--space-lg) var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ── KPI row ─────────────────────────────────────────────── */
.ir-kpi-note {
  text-align: right;
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  font-family: var(--font-family-base);
  padding-top: var(--space-sm);
  margin-bottom: calc(var(--space-sm) * -1);
}

.ir-kpi-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-md);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-bottom: var(--space-xs);
}

.ir-kpi-row::-webkit-scrollbar {
  display: none;
}

.ir-kpi-row .kpi-card {
  min-width: var(--space-35);
  flex: 1 0 var(--space-35);
  scroll-snap-align: start;
}

/* ── Chart section (full width) ──────────────────────────── */
.ir-chart-full {
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding: var(--space-xs) var(--space-md) 0;
  gap: var(--space-xs);
}

/* Extend IPC chart to both card edges so "Impressions" label aligns
   with the component title on the left, and "Spend(R$)" aligns with
   the download icon on the right */
.ir-ipc-chart {
  margin-left: calc(-1 * var(--space-md));
  margin-right: calc(-1 * var(--space-md));
}

/* ── Chart header ────────────────────────────────────────── */
.ir-chart-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-md);
  flex-wrap: nowrap;
}

/* Title/subtitle wrapper (unclassed in markup) — without min-width: 0 a
   flex item's floor is its content's natural (nowrap) width, so the
   .ir-chart-title below can never actually shrink far enough to ellipsis
   and instead pushes the header wider than its card at narrow widths. */
.ir-chart-header > div:first-child {
  flex: 1;
  min-width: 0;
}

.ir-chart-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  white-space: nowrap;
}

.ir-chart-subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-kpiblack);
  margin: var(--space-px) 0 0;
  font-family: var(--font-family-base);
}

/* ── Chart actions ───────────────────────────────────────── */
.ir-chart-actions {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  flex-shrink: 0;
  flex-wrap: nowrap;
}

.ir-chart-actions .hs-wrap {
  max-width: var(--space-13-75);
}

/* ── Icon button ─────────────────────────────────────────── */
.ir-icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-primary);
  padding: var(--space-0-8);
  display: flex;
  align-items: center;
  border-radius: var(--radius-sm);
  transition:
    color var(--motion-duration-fast) ease,
    background var(--motion-duration-fast) ease;
}

.ir-icon-btn:hover {
  background: var(--color-bg-hover-light);
}

/* ── Pills row ───────────────────────────────────────────── */
.ir-pills-row {
  display: flex;
  gap: var(--space-sm);
  flex-wrap: wrap;
}

.ir-pill {
  flex: 1;
  min-width: var(--space-8-75);
  background: var(--color-subtleblue);
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-pill);
  padding: var(--space-xs) var(--space-md);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-base);
  color: var(--color-kpi-title);
  white-space: nowrap;
}

.ir-pill:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.ir-pill-icon {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  line-height: 0;
}

.ir-pill-icon svg {
  width: auto;
  height: var(--space-2-75);
}

.ir-pill-value {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-accent);
  font-family: var(--font-family-display);
}

.ir-pill-value--ahead {
  color: var(--color-delta-positive);
}

/* ── Split layout (Performance by Influencer) ────────────── */
.ir-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
  align-items: start;
  min-height: 0;
}

.ir-split-left {
  min-width: 0;
}

.ir-split-right {
  min-width: 0;
  overflow-y: auto;
}

.ir-widget-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--space-50);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

/* Bubble Size legend icon — thin grey circle, scoped to IVPM chart only */
.ir-ivpm-chart .legend g.traces:first-child .legendsymbols path {
  stroke-width: 1px !important;
  stroke: #888888 !important;
  fill: none !important;
}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 1200px) {
  .ir-kpi-row {
    flex-wrap: wrap;
  }
}

/* Below ~600px, flex-wrap's natural reflow depends on each card's own
   min-width vs. the exact remaining space, which can land on 1-per-row
   (a lot of dead space beside each card) as often as 2. Switch to an
   explicit 2-column grid so mobile always gets a predictable 2-and-2
   layout; an odd trailing card spans both columns instead of leaving an
   empty cell beside it. */
@media (max-width: 600px) {
  .ir-kpi-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  .ir-kpi-row .kpi-card:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 1024px) {
  .ir-split {
    grid-template-columns: 1fr;
  }

  .ir-split-right {
    max-height: var(--space-25);
  }
}

@media (max-width: 768px) {
  /* .ir-chart-title has white-space: nowrap for desktop alignment; at
     mobile widths that can push the header wider than its card and
     overflow the page. Let it truncate with an ellipsis instead. */
  .ir-chart-title {
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* .ir-chart-header/.ir-chart-actions never wrap, and the
     "Select Channel, Platform[, Campaign]" HierarchySelect dropdown here
     (Influencers vs Paid Media, Performance by Influencer) is given a hard
     minWidth={280}/{300} prop — turned into an inline `min-width` that's
     LARGER than this rule's own `max-width: var(--space-13-75)` (220px)
     above, so per the CSS cascade min-width already always won and that
     max-width has never actually applied at any width. Let the header wrap
     to its own row and the dropdown shrink to fit instead of forcing the
     card wider than the viewport. */
  .ir-chart-header {
    flex-wrap: wrap;
  }

  .ir-chart-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
    flex: 1 0 100%;
  }

  .ir-chart-actions .hs-wrap {
    min-width: 0;
    max-width: 100%;
    flex: 1 1 auto;
  }

  /* .ir-pill has white-space: nowrap and only a 140px min-width — at narrow
     widths a pill's real (unwrappable) text content is far wider than that
     floor, so instead of the row wrapping the *pill* onto its own line,
     each pill's text overflowed its own rounded border and visually
     overlapped the next pill. Let each pill wrap its own text and take a
     full row instead of trying to fit label+value on one line. */
  .ir-pill {
    flex: 1 1 100%;
    white-space: normal;
    text-align: center;
  }
}
/* ─── Page Layout ────────────────────────────────────────── */
.mo-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  /* Without this, the FilterBar's dropdown panel (position: absolute, up
     to --space-22 tall) can extend past this page's own 100vh box — since
     nothing here clips it, the browser adds a genuine page-level scrollbar
     to reveal the overflow the moment the panel opens, on top of
     .mo-body's own CustomScrollbar. .um-page already has this; the other
     pages using FilterBar were missing it. */
  overflow: hidden;
}

/* Keep AppTabs non-sticky inside this page */
.mo-page .app-tabs-wrapper {
  position: static;
}

/* FilterBar: white bg, no sticky offset */
.mo-page .fb-wrapper {
  position: relative;
  top: 0;
  background: var(--color-white);
  border-bottom: none;
  margin: 0;
}

.mo-filter-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-lg);
}

.mo-body {
  flex: 1;
  min-height: 0;
}

.mo-body-content {
  padding: var(--space-md) var(--space-lg) var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* ─── Breadcrumb (static above filter bar) ───────────────── */
.mo-breadcrumb-bar {
  padding: 0 var(--space-lg);
}

.mo-breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.mo-breadcrumb-item {
  color: var(--color-text-muted);
}

.mo-breadcrumb-sep {
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
}

.mo-breadcrumb-active {
  color: var(--color-primary);
  font-weight: var(--font-weight-medium);
}

/* ─── KPI Note ───────────────────────────────────────────── */
.mo-kpi-note {
  text-align: right;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  margin-bottom: calc(var(--space-sm) * -1);
}

/* ─── KPI Row ────────────────────────────────────────────── */
.mo-kpi-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-md);
  overflow-x: auto;
  scrollbar-width: none;
}

.mo-kpi-row::-webkit-scrollbar {
  display: none;
}

.mo-kpi-row .kpi-card {
  min-width: var(--space-35);
  flex: 1 0 var(--space-35);
}

/* ─── Collapsible Section ────────────────────────────────── */
.mo-section {
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-white);
}

.mo-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--space-md) var(--space-lg);
  background: var(--color-section-header-bg);
  border: none;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  cursor: pointer;
  text-align: left;
  transition: background var(--motion-duration-fast) ease;
}

.mo-section-header:hover {
  background: var(--color-section-header-bg-hover);
}

.mo-section-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
}

.mo-section-chevron {
  display: flex;
  align-items: center;
  color: var(--color-primary);
  transition: transform var(--motion-duration-normal) ease;
}

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

.mo-section-refresh-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  margin-right: var(--space-sm);
  padding: var(--space-xs);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--color-primary);
  cursor: pointer;
  transition: color var(--motion-duration-fast) ease, background var(--motion-duration-fast) ease;
}

.mo-section-refresh-btn:hover:not(:disabled) {
  color: var(--color-primary);
  background: var(--color-section-icon-hover-bg);
}

.mo-section-refresh-btn:disabled {
  cursor: default;
  opacity: 0.5;
}

.mo-section-loader {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-12) 0;
}

.mo-section-spinner {
  width: var(--space-7);
  height: var(--space-7);
  border: var(--space-0-1875) solid var(--color-section-spinner-track);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: mo-spin 0.7s linear infinite;
}

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

.mo-sections-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0;
}

.mo-section-header--static {
  cursor: default;
  pointer-events: none;
}

.mo-section-header--static:hover {
  background: var(--color-section-header-bg);
}

/* ─── Enter Constraints (plain, no accordion wrapper) ───────── */
.mo-constraints-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-top: var(--space-lg);
}

/* ─── Full-width SelectDropdown in form ─────────────────────── */
.mo-sd-full {
  width: 100%;
}

.mo-sd-full .sd-trigger {
  width: 100%;
  min-width: 100%;
}

.mo-section-body {
  padding: var(--space-lg);
  border-top: var(--space-px) solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.mo-section-body--table {
  padding: 0;
  gap: 0;
}

.mo-section-body--table .mo-scenario-actions {
  padding: var(--space-md) var(--space-lg);
  border-top: var(--space-px) solid var(--color-border);
}

/* ─── Shared checkbox ────────────────────────────────────── */
.mo-checkbox {
  width: var(--space-lg);
  height: var(--space-lg);
  accent-color: var(--color-primary);
  cursor: pointer;
  display: block;
}

/* ─── Status Badge ───────────────────────────────────────── */
.mo-status-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-0-4) var(--space-md);
  border-radius: var(--space-5);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
}

.mo-status-badge--completed {
  background: rgba(4, 151, 124, 0.12);
  color: var(--color-success);
}

.mo-status-badge--in-progress {
  background: rgba(0, 84, 216, 0.1);
  color: var(--color-accent);
}

.mo-status-badge--queued {
  background: rgba(237, 138, 0, 0.1);
  color: var(--color-warning);
}

.mo-status-badge--failed {
  background: rgba(211, 47, 47, 0.1);
  color: var(--color-error);
}

.mo-status-badge--clickable {
  cursor: pointer;
}

.mo-status-badge--clickable:hover {
  filter: brightness(0.92);
}

.mo-status-info-btn {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: currentColor;
  opacity: 0.7;
  transition: opacity 0.15s;
}

.mo-status-info-btn:hover {
  opacity: 1;
}

/* ─── Scenario action buttons ────────────────────────────── */
.mo-scenario-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-sm);
}

.mo-action-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-lg);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition:
    background var(--motion-duration-fast) ease,
    opacity var(--motion-duration-fast) ease;
  border: var(--space-px) solid;
}

.mo-action-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.mo-action-btn--outline {
  background: var(--color-white);
  color: var(--color-primary);
  border-color: var(--color-primary);
}

.mo-action-btn--outline:hover:not(:disabled) {
  background: var(--color-bg-hover-light);
}

.mo-action-btn--primary {
  background: var(--color-primary);
  color: var(--color-white);
  border-color: var(--color-primary);
}

.mo-action-btn--primary:hover:not(:disabled) {
  background: var(--color-navbar);
  border-color: var(--color-navbar);
}

/* ─── Subsection Header ──────────────────────────────────── */
.mo-subsection-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0.625rem;
}

.mo-subsection-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
}

.mo-form-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-sm);
}

/* ─── Import Button ──────────────────────────────────────── */
.mo-import-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-3-5);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-primary);
  font-size: var(--font-size-base);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.mo-import-btn:hover {
  background: var(--color-bg-hover-light);
}

/* ─── Outlined Field (floating label style) ──────────────── */
.mo-ofield {
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-input);
  background: var(--color-white);
  padding: var(--space-0-6) var(--space-md) var(--space-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-0-4);
  width: 100%;
  box-sizing: border-box;
}

.mo-ofield--tall {
  height: 100%;
  min-height: var(--space-30);
}

.mo-ofield-label {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-regular);
  white-space: nowrap;
  line-height: var(--line-height-tight);
}

.mo-ofield-select {
  border: none;
  background: transparent;
  font-size: var(--font-size-base);
  color: var(--color-text-body);
  padding: 0;
  appearance: none;
  cursor: pointer;
  width: 100%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'%3E%3Cpath fill='%2364748B' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0 center;
  padding-right: var(--space-lg);
}

.mo-ofield-select:focus {
  outline: none;
}

.mo-ofield-input {
  border: none;
  background: transparent;
  font-size: var(--font-size-base);
  color: var(--color-text-body);
  padding: 0;
  width: 100%;
  flex: 1;
}

.mo-ofield-input:focus {
  outline: none;
}

.mo-ofield-textarea {
  border: none;
  background: transparent;
  font-size: var(--font-size-base);
  color: var(--color-text-body);
  padding: 0;
  width: 100%;
  flex: 1;
  resize: none;
  min-height: 5rem;
}

.mo-ofield-textarea:focus {
  outline: none;
}

.mo-ofield-spend-value {
  font-size: var(--font-size-base);
  color: var(--color-text-body);
  font-weight: var(--font-weight-medium);
  padding: var(--space-0-5) 0;
}

.mo-ofield-pct-wrap {
  display: flex;
  align-items: center;
  width: 100%;
}

.mo-ofield-pct-suffix {
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  margin-left: auto;
  padding-right: var(--space-0-5);
}

.mo-ofield:focus-within {
  border-color: var(--color-primary);
}

/* ─── Form Grid ──────────────────────────────────────────── */
.mo-form-grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr 1.3fr;
  gap: var(--space-lg);
  align-items: stretch;
}

.mo-form-left,
.mo-form-middle {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.mo-form-right {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* ── Scenario Name: grows to fill remaining left-column height ── */
.mo-form-name-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  flex: 1;
  min-height: 0;
}

/* let the InputField wrapper stretch */
.mo-form-name-wrap .input-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.mo-form-name-wrap .input-field-inner {
  flex: 1;
  align-items: flex-start;
}

.mo-form-name-wrap .input-field {
  height: 100%;
}

/* ── Grey borders for Scenario Details ─────────────────────── */
.mo-form-left .input-field {
  border-color: var(--color-kpigrey);
  color: var(--color-black);
  font-size: var(--font-size-base);
}

.mo-form-left .input-label {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

.mo-form-left .input-field:focus ~ .input-label,
.mo-form-left .input-field.has-value ~ .input-label {
  color: var(--color-text-muted);
  font-size: var(--font-size-2xs);
}

/* Scenario Type dropdown — same compact height */
.mo-sd-full .sd-trigger {
  height: var(--space-11);
  min-height: var(--space-11);
}


/* Red required asterisk for Scenario Type and Scenario Name labels */
.mo-sd-full .sd-label::after,
.mo-form-name-wrap .input-label::after {
  content: " *";
  color: var(--color-error);
}

.mo-field-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.mo-field-wrap--full {
  flex: 1;
}

.mo-field-label {
  font-size: var(--font-size-md);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-medium);
  margin: 0 var(--space-2-5);
}

.mo-required {
  color: var(--color-error);
}

/* ─── Select ─────────────────────────────────────────────── */
.mo-select {
  width: 100%;
  padding: var(--space-sm) var(--space-xxl) var(--space-sm) var(--space-2-5);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-input);
  background: var(--color-white);
  color: var(--color-text-body);
  font-size: var(--font-size-base);
  appearance: none;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'%3E%3Cpath fill='%2364748B' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-sm) center;
}

.mo-select:focus {
  outline: none;
  border-color: var(--color-primary);
}

/* ─── Input ──────────────────────────────────────────────── */
.mo-input {
  padding: var(--space-sm) var(--space-2-5);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-input);
  background: var(--color-white);
  color: var(--color-text-body);
  font-size: var(--font-size-base);
  width: 100%;
  box-sizing: border-box;
}

.mo-input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.mo-input--suffix {
  padding-right: var(--space-7);
}

.mo-name-meta-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-sm);
}

.mo-name-error-text {
  font-size: var(--font-size-sm);
  color: var(--color-error);
  padding-left: var(--space-md);
  flex: 1;
}

.mo-char-count {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  white-space: nowrap;
}

.mo-char-count--error {
  color: var(--color-error);
  font-weight: var(--font-weight-medium);
}

.mo-input-suffix-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.mo-input-suffix {
  position: absolute;
  right: var(--space-2-5);
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  pointer-events: none;
}

/* ─── Textarea ───────────────────────────────────────────── */
.mo-textarea {
  width: 100%;
  padding: var(--space-sm) var(--space-2-5);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-input);
  background: var(--color-white);
  color: var(--color-black);
  font-size: var(--font-size-base);
  resize: vertical;
  box-sizing: border-box;
  min-height: 5.625rem;
}

.mo-textarea:focus {
  outline: none;
  border-color: var(--color-black);
}

/* ─── Target Spend Display ───────────────────────────────── */
.mo-spend-display {
  display: flex;
  align-items: baseline;
  gap: var(--space-1-5);
  padding: var(--space-sm) var(--space-2-5);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-input);
  background: var(--color-white);
  font-size: var(--font-size-base);
}

.mo-spend-prefix {
  color: var(--color-text-muted);
  font-size: var(--font-size-md);
}

.mo-spend-value {
  color: var(--color-text-body);
  font-weight: var(--font-weight-medium);
}

/* ─── Target Spend Slider ────────────────────────────────── */
.mo-spend-slider {
  position: relative;
  padding-top: var(--space-xl);
  padding-bottom: var(--space-xl);
  margin-top: 0;
}

.mo-spend-range-input {
  position: absolute;
  width: 100%;
  left: 0;
  top: 1.375rem;
  appearance: none;
  -webkit-appearance: none;
  height: var(--space-xs);
  background: transparent;
  z-index: 4;
  cursor: grab;
  touch-action: none;
}

.mo-spend-range-input:active {
  cursor: grabbing;
}

.mo-spend-range-input::-webkit-slider-runnable-track {
  height: var(--space-0-5);
  background: var(--color-border);
  border-radius: var(--space-px);
  width: 100%;
}

.mo-spend-range-input::-moz-range-track {
  height: var(--space-0-5);
  background: var(--color-border);
  border-radius: var(--space-px);
  width: 100%;
}

/* ── Slider thumb: the visible blue dot — native element for smooth drag ─ */
.mo-spend-range-input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: var(--space-3-5);
  height: var(--space-3-5);
  border-radius: 50%;
  background: var(--color-primary);
  margin-top: calc(-1 * var(--space-1-2));
  cursor: grab;
  border: none;
  box-shadow: 0 var(--space-px) var(--space-xs) rgba(0, 84, 216, 0.35);
  will-change: transform;
  transition: box-shadow var(--motion-duration-fast) ease;
}

.mo-spend-range-input:active::-webkit-slider-thumb {
  cursor: grabbing;
  box-shadow: 0 var(--space-0-5) var(--space-sm) rgba(0, 84, 216, 0.5);
}

.mo-spend-range-input::-moz-range-thumb {
  width: var(--space-3-5);
  height: var(--space-3-5);
  border-radius: 50%;
  background: var(--color-primary);
  cursor: grab;
  border: none;
  box-shadow: 0 var(--space-px) var(--space-xs) rgba(0, 84, 216, 0.35);
  will-change: transform;
  transition: box-shadow var(--motion-duration-fast) ease;
}

.mo-spend-range-input:active::-moz-range-thumb {
  cursor: grabbing;
  box-shadow: 0 var(--space-0-5) var(--space-sm) rgba(0, 84, 216, 0.5);
}

/* ── Hover badge — sits in the padding area above the track ─ */
.mo-spend-indicator-pct {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  z-index: 5;
  pointer-events: none;
  visibility: hidden;
  background: rgba(40, 60, 126, 0.08);
  color: var(--color-primary);
  border-radius: 20px;
  padding: 4px 8px;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
  line-height: var(--line-height-snug);
}

.mo-spend-slider:hover .mo-spend-indicator-pct {
  visibility: visible;
}

.mo-spend-tick-value {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  white-space: nowrap;
  line-height: 1;
  margin-top: 1px;
}

/* ── Static tick marks (always grey, z-index ABOVE track) ── */
.mo-spend-ticks {
  position: absolute;
  top: 1.25rem;
  left: 0;
  right: 0;
  z-index: 3;
  pointer-events: none;
}

.mo-spend-tick {
  position: absolute;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
}

.mo-spend-tick--first {
  transform: translateX(0);
  align-items: flex-start;
}

.mo-spend-tick--last {
  transform: translateX(-100%);
  align-items: flex-end;
}

.mo-spend-tick-dot {
  width: var(--space-sm);
  height: var(--space-sm);
  border-radius: 50%;
  background: var(--color-border);
}

.mo-spend-tick-label {
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  white-space: nowrap;
}

.mo-spend-zero-label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin-top: var(--space-0-4);
}

/* ─── Form Divider ───────────────────────────────────────── */
.mo-form-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
}

/* ─── Optimisation Level ─────────────────────────────────── */
.mo-optim-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.mo-optim-level {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.mo-radio-group {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  margin: 0 var(--space-lg);
}

.mo-radio-label {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
  font-size: var(--font-size-base);
  cursor: pointer;
  color: var(--color-text-body);
}

.mo-radio {
  accent-color: var(--color-primary);
  cursor: pointer;
}

.mo-radio-text--disabled {
  color: var(--color-text-muted);
  opacity: 0.6;
}

.mo-radio-label--disabled {
  cursor: not-allowed;
}

.mo-radio-label--disabled .mo-radio {
  cursor: not-allowed;
}

.mo-recap-btn {
  padding: var(--space-1-5) var(--space-lg);
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-primary);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.mo-recap-btn:hover {
  background: var(--color-bg-hover-light);
}

/* ─── Global Constraints Bar ─────────────────────────────── */
.mo-constraints-wrapper {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.mo-global-constraints {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  background: var(--color-lightgrey);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  gap: var(--space-md);
  /* Anchors .mo-gc-col-section/.mo-gc-slider-section's absolute
     left/width, which MediaOptimisationSimulator.tsx sets from the live
     table header cells' own measured position (see
     useLayoutEffect there) so they track the table's real Min/Slider/Max
     column boundaries exactly, at any width, instead of a static guess. */
  position: relative;
}

.mo-gc-col-section {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  justify-content: center;
  position: absolute;
  top: 0;
  height: 100%;
}

.mo-gc-slider-section {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 0;
  height: 100%;
}

.mo-global-label {
  font-size: var(--font-size-base);
  color: var(--color-text-body);
  font-weight: var(--font-weight-medium);
  flex: 1;
}

.mo-global-label-accent {
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
}

.mo-gc-field-label {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  color: var(--color-black);
}

.mo-gc-input-wrap {
  display: flex;
  align-items: center;
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-sm);
  background: var(--color-lightgrey);
  overflow: hidden;
}

.mo-gc-input {
  padding: var(--space-1-4) var(--space-sm);
  border: none;
  background: var(--color-lightgrey);
  color: var(--color-text-body);
  font-size: var(--font-size-base);
  width: 4.25rem;
  text-align: right;
}

.mo-gc-input:focus {
  outline: none;
}

.mo-gc-suffix {
  padding: var(--space-1-4) var(--space-sm) var(--space-1-4) 0;
  font-size: var(--font-size-base);
  color: var(--color-black);
  background: var(--color-lightgrey);
}

.mo-gc-reset-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-5);
  height: var(--space-5);
  border: none;
  border-radius: var(--radius-lg);
  background: var(--color-lightgrey);
  color: var(--color-text-muted);
  cursor: pointer;
  transition:
    color var(--motion-duration-fast) ease,
    background var(--motion-duration-fast) ease;
}

.mo-gc-reset-btn:hover {
  color: var(--color-text-muted);
  background: var(--color-grey);
}

/* ─── Constraints Table ──────────────────────────────────── */
.mo-table-wrap {
  overflow: auto;
  max-height: 24rem;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  position: relative;
}

.mo-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-base);
  background: var(--color-white);
}

.mo-table thead {
  background: var(--color-lightgrey);
  position: sticky;
  top: 0;
  z-index: 1;
}

.mo-table th {
  padding: var(--space-sm) var(--space-md);
  text-align: left;
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
  white-space: nowrap;
  background: var(--color-lightgrey);
}

.mo-table td {
  padding: var(--space-sm) var(--space-md);
  border-bottom: var(--space-px) solid var(--color-border);
  color: var(--color-text-body);
  font-size: var(--font-size-base);
}

.mo-table tbody tr:last-child td {
  border-bottom: none;
}

.mo-table tbody tr:hover {
  background: var(--color-bg-hover-light);
}

.mo-th-lock,
.mo-td-lock {
  width: var(--space-10);
  text-align: center;
}

.mo-lock-btn {
  background: none;
  border: none;
  padding: var(--space-xs);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background var(--motion-duration-fade) ease;
}

.mo-lock-btn:hover {
  background: var(--color-lightgrey);
}

.mo-row-locked {
  background: rgba(0, 0, 0, 0.02);
  opacity: 0.6;
}

.mo-row-locked input:disabled {
  cursor: not-allowed;
}

/* Grey out the whole pct container (input + % sign) so the % remains visible */
.mo-row-locked .mo-constraint-pct {
  background: var(--color-lightgrey);
}

/* Grey out the R$ input too for visual consistency */
.mo-row-locked .mo-constraint-r-input {
  background: var(--color-lightgrey);
}

.mo-dual-range--disabled {
  opacity: 0.5;
  pointer-events: none;
}

.mo-th-center {
  text-align: center;
}

.mo-td-slider {
  min-width: 10rem;
  padding: var(--space-sm) var(--space-lg);
}

/* ─── Constraints Table Header ───────────────────────────── */
.mo-cth-inner {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.mo-th-sort-btn {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.mo-th-sort-btn:hover {
  color: var(--color-primary);
}

/* ─── Constraint Inputs ──────────────────────────────────── */
.mo-constraint-inputs {
  display: flex;
  align-items: center;
  gap: var(--space-1-5);
}

.mo-constraint-r-input {
  width: 6.5rem;
  padding: var(--space-1-4) var(--space-1-5);
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text-body);
  font-size: var(--font-size-md);
  text-align: right;
}

.mo-constraint-r-input:focus {
  outline: none;
  border-color: var(--color-primary);
}

.mo-constraint-pct {
  display: flex;
  align-items: center;
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  overflow: hidden;
}

.mo-constraint-pct-input {
  width: 3.5rem;
  padding: var(--space-1-4) var(--space-xs) var(--space-1-4) var(--space-1-5);
  border: none;
  background: transparent;
  color: var(--color-text-body);
  font-size: var(--font-size-md);
  text-align: right;
}

.mo-constraint-pct-input:focus {
  outline: none;
}

.mo-pct-sign {
  padding: var(--space-1-4) var(--space-1-5) var(--space-1-4) var(--space-0-5);
  font-size: var(--font-size-md);
  color: var(--color-text-muted);
}


/* ─── Dual Range Slider ──────────────────────────────────── */
.mo-dual-range {
  position: relative;
  height: var(--space-5);
  display: flex;
  align-items: center;
}

.mo-dual-range-track {
  position: absolute;
  left: 0;
  right: 0;
  height: var(--space-xs);
  background: var(--color-border);
  border-radius: var(--space-0-5);
}

.mo-dual-range-fill {
  position: absolute;
  height: 100%;
  background: var(--color-primary);
  border-radius: var(--space-0-5);
}

.mo-range-thumb {
  position: absolute;
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  height: var(--space-5);
  pointer-events: none;
  margin: 0;
}

.mo-range-thumb::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: var(--space-3-5);
  height: var(--space-3-5);
  border-radius: 50%;
  background: var(--color-primary);
  cursor: pointer;
  pointer-events: all;
  border: none;
  box-shadow: 0 var(--space-px) var(--space-0-8) rgba(0, 84, 216, 0.3);
}

.mo-range-thumb:disabled::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  background: var(--color-text-muted);
  cursor: not-allowed;
  box-shadow: none;
}

.mo-range-thumb::-moz-range-thumb {
  width: var(--space-3-5);
  height: var(--space-3-5);
  border-radius: 50%;
  background: var(--color-primary);
  cursor: pointer;
  pointer-events: all;
  border: none;
  box-shadow: 0 var(--space-px) var(--space-0-8) rgba(0, 84, 216, 0.3);
}

.mo-range-thumb:disabled::-moz-range-thumb {
  background: var(--color-text-muted);
  cursor: not-allowed;
  box-shadow: none;
}

/* ─── Constraints Footer ─────────────────────────────────── */
.mo-constraints-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-lg);
  border: var(--space-px) solid var(--color-border);
  border-top: none;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  background: var(--color-white);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* ─── Run Scenario Wrapper ────────────────────────────────── */
.mo-run-scenario-wrapper {
  display: flex;
  justify-content: flex-end;
  padding-top: var(--space-md);
}

.mo-run-scenario-btn {
  padding: var(--space-2-5) var(--space-7);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.mo-btn-spinner {
  width: 1rem;
  height: 1rem;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #ffffff;
  border-radius: 50%;
  animation: mo-spin 0.7s linear infinite;
  flex-shrink: 0;
}

/* ─── Pagination (constraints) ───────────────────────────── */
.mo-pagination {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mo-pg-label {
  white-space: nowrap;
}

.mo-pg-select {
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-0-4) var(--space-1-2);
  background: var(--color-white);
  font-size: var(--font-size-sm);
  color: var(--color-primary);
  cursor: pointer;
  font-family: var(--font-family-base);
  outline: none;
}

.mo-pg-info {
  white-space: nowrap;
  min-width: 4rem;
  text-align: center;
}

.mo-pg-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-primary);
  font-size: var(--font-size-2xl);
  line-height: 1;
  padding: 0 var(--space-0-4);
  display: flex;
  align-items: center;
  transition: color var(--motion-duration-fast) ease;
}

.mo-pg-btn:disabled {
  color: var(--color-text-placeholder);
  cursor: not-allowed;
}

/* ─── Run Scenario Button ────────────────────────────────── */
.mo-run-btn {
  padding: var(--space-2-5) var(--space-7);
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  transition: background var(--motion-duration-normal) ease;
}

.mo-run-btn:hover {
  background: var(--color-navbar);
}

.mo-run-btn:active {
  transform: translateY(var(--space-px));
}

/* ─── Shared Button Styles (matching PerformanceOverview) ─── */
.po-btn-primary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.po-btn-primary svg {
  color: var(--color-white);
  fill: currentColor;
}

.po-btn-primary:hover:not(:disabled) {
  background: var(--color-primary-hover);
}

.po-btn-primary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.po-btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  background: var(--color-white);
  color: var(--color-primary);
  border: var(--space-px) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.po-btn-secondary svg {
  color: var(--color-primary);
  fill: currentColor;
}

.mo-delete-btn svg {
  fill: none;
  stroke: var(--color-primary);
}

.po-btn-secondary:hover:not(:disabled) {
  background: var(--color-bg-hover-light);
}

.po-btn-secondary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.po-btn-secondary--compact {
  padding-left: var(--space-md);
  padding-right: var(--space-md);
}

/* ─── Responsive ─────────────────────────────────────────── */
@media (max-width: 1200px) {
  .mo-kpi-row {
    flex-wrap: wrap;
  }

  .mo-form-grid {
    grid-template-columns: 1fr 1fr;
  }

  .mo-form-right {
    grid-column: 1 / -1;
  }
}

/* The Global Constraints bar's three sections (.mo-gc-col-section × 2 +
   .mo-gc-slider-section) are absolutely positioned to mirror the live
   DataTable's Min/Slider/Max column boundaries below it (measured in
   MediaOptimisationSimulator.tsx) — but that alignment only matters once
   those columns are actually visible side by side, which the table itself
   already abandons at narrow widths (it scrolls horizontally on its own,
   via DataTable's standard dt-inner-h overflow). Below that same table's
   own column widths' combined footprint, the bar had no responsive
   treatment at all: its absolutely-positioned sections don't wrap or
   scroll, so on a mobile viewport (~350–390px available) the Max section —
   and on anything narrower than ~1024px, increasingly more of the bar —
   gets positioned off past the card edge and is effectively unreachable
   (no scrollbar, no wrap). Let the bar wrap onto multiple rows instead:
   the instruction label gets its own full row, and Min / reset / Max fall
   back to their natural (unfixed, normal-flow) width and position —
   `!important` is needed because MediaOptimisationSimulator.tsx sets
   left/width as inline styles (for the desktop-aligned case), which
   otherwise always outrank a stylesheet media query. */
@media (max-width: 1024px) {
  .mo-global-constraints {
    flex-wrap: wrap;
    row-gap: var(--space-sm);
  }

  .mo-global-label {
    flex: 1 0 100%;
  }

  .mo-gc-col-section,
  .mo-gc-slider-section {
    position: static !important;
    width: auto !important;
    flex: 0 0 auto;
  }
}

/* Below ~600px, flex-wrap's natural reflow depends on each card's own
   min-width vs. the exact remaining space, which can land on 1-per-row
   (a lot of dead space beside each card) as often as 2. Switch to an
   explicit 2-column grid so mobile always gets a predictable 2-and-2
   layout; an odd trailing card spans both columns instead of leaving an
   empty cell beside it. */
@media (max-width: 600px) {
  .mo-kpi-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  .mo-kpi-row .kpi-card:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 768px) {
  .mo-form-grid {
    grid-template-columns: 1fr;
  }

  .mo-form-right {
    grid-column: auto;
  }
}

/* ─── Performance Recap Modal ────────────────────────────── */
.mo-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
}

.mo-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: 92%;
  max-width: 81.25rem;
  /* Size to content (header + table + footer) rather than a fixed height, so a
     short table doesn't leave whitespace below it. The table caps its own height
     at 350px and scrolls beyond that; max-height keeps the modal within the
     viewport. */
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-sm) var(--space-10) rgba(0, 0, 0, 0.18);
  overflow: hidden;
}

.mo-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-lg) var(--space-sm);
  border-bottom: var(--space-px) solid var(--color-kpigrey);
  flex-shrink: 0;
  margin: 0 var(--space-xl);
}

.mo-modal-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
}

.mo-modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-xxl);
  height: var(--space-xxl);
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
}

.mo-modal-close:hover {
  background: var(--color-lightgrey);
  color: var(--color-text-body);
}

.mo-modal-body {
  flex: 1;
  min-height: 0;
  padding: var(--space-xl);
  overflow-y: auto;
  outline: none;
}

.mo-modal-body:focus {
  outline: none;
}

.mo-modal-body::-webkit-scrollbar {
  display: none;
}

.mo-modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2-5);
  padding: var(--space-md) 0;
  border-top: var(--space-px) solid var(--color-kpigrey);
  margin: 0 var(--space-xl);
  flex-shrink: 0;
}

/* ─── Confirm Delete Modal ────────────────────────────────── */
.mo-delete-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: 26.25rem;
  max-width: 95vw;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-sm) var(--space-10) rgba(0, 0, 0, 0.18);
}

.mo-delete-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-lg) var(--space-5) var(--space-3-5);
}

.mo-delete-modal-title {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
}

.mo-delete-modal-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-5) var(--space-xs);
  border-radius: var(--space-0-5);
}

.mo-delete-modal-body {
  padding: var(--space-lg) var(--space-5) var(--space-md);
}

.mo-delete-modal-text {
  font-size: var(--font-size-lg);
  color: var(--color-text-body);
  margin: 0;
  line-height: var(--line-height-relaxed);
}

.mo-delete-modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2-5);
  padding: var(--space-md) var(--space-5) var(--space-lg);
}

/* ─── Download Toast ─────────────────────────────────────── */
.mo-toast {
  position: fixed;
  top: var(--space-5);
  right: var(--space-xl);
  z-index: 2000;
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  background: var(--color-success);
  color: var(--color-white);
  border-radius: var(--radius-sm);
  padding: var(--space-md) var(--space-lg);
  font-size: var(--font-size-base);
  box-shadow: 0 var(--space-xs) var(--space-lg) rgba(0, 0, 0, 0.18);
  max-width: 28.75rem;
  animation: mo-toast-in var(--motion-duration-normal) ease;
}

@keyframes mo-toast-in {
  from {
    opacity: 0;
    transform: translateY(-0.5rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.mo-toast-icon {
  flex-shrink: 0;
}

.mo-toast-msg {
  flex: 1;
  line-height: 1.4;
}

.mo-toast-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-white);
  opacity: 0.8;
  padding: 0;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.mo-toast-close:hover {
  opacity: 1;
}

/* ─── Floating Label Textarea ────────────────────────────── */
.mo-textarea-wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.mo-textarea-field {
  width: 100%;
  flex: 1;
  min-height: 5rem;
  padding: var(--space-md) var(--space-md) var(--space-xs);
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-input);
  background-color: var(--color-input-bg);
  font-size: var(--font-size-sm);
  color: var(--color-black);
  outline: none;
  resize: none;
  font-family: var(--font-family-base);
  transition: border-color var(--motion-duration-normal) ease;
}

.mo-textarea-label {
  position: absolute;
  left: var(--space-md);
  top: var(--space-md);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  pointer-events: none;
  transition:
    top var(--motion-duration-fast) ease,
    font-size var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease;
}

.mo-textarea-field:focus ~ .mo-textarea-label,
.mo-textarea-field:not(:placeholder-shown) ~ .mo-textarea-label {
  top: calc(var(--space-px) * -6);
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  background: var(--color-input-bg);
  padding: 0 var(--space-xs);
  line-height: var(--line-height-none);
  margin-left: calc(var(--space-xs) * -1);
}

.mo-textarea-field:focus {
  border-color: var(--color-input-border-focus);
}

/* ─── Floating Label Number Input with Suffix ────────────── */
.mo-number-input-wrapper {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  margin-top: var(--space-lg);
}

.mo-number-input-field {
  width: 100%;
  height: var(--space-10);
  padding: var(--space-xs) var(--space-xxl) 0 var(--space-md);
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-input);
  background-color: var(--color-input-bg);
  font-size: var(--font-size-base);
  color: var(--color-black);
  outline: none;
  transition: border-color var(--motion-duration-normal) ease;
}

.mo-number-input-label {
  position: absolute;
  left: var(--space-md);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  pointer-events: none;
  transition:
    top var(--motion-duration-fast) ease,
    font-size var(--motion-duration-fast) ease,
    color var(--motion-duration-fast) ease,
    transform var(--motion-duration-fast) ease;
}

.mo-number-input-field:focus ~ .mo-number-input-label,
.mo-number-input-field:not(:placeholder-shown) ~ .mo-number-input-label {
  top: calc(var(--space-px) * -6);
  transform: none;
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  background: var(--color-input-bg);
  padding: 0 var(--space-xs);
  line-height: var(--line-height-none);
  margin-left: calc(var(--space-xs) * -1);
}

.mo-number-input-suffix {
  position: absolute;
  right: var(--space-md);
  top: 50%;
  transform: translateY(-50%);
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  pointer-events: none;
}

.mo-number-input-field:focus {
  border-color: var(--color-input-border-focus);
}

/* ─── Target Spend Editable Input with Currency Adornment ─── */
.mo-display-field-wrapper {
  position: relative;
  width: 100%;
}

.mo-spend-input-adornment {
  position: absolute;
  left: var(--space-md);
  top: calc(47% + var(--space-xs) / 2);
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  pointer-events: none;
  z-index: 1;
}

.mo-display-field {
  width: 100%;
  height: var(--space-10);
  padding: var(--space-xs) var(--space-md) 0 var(--space-2);
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-input);
  background-color: var(--color-input-bg);
  font-size: var(--font-size-base);
  color: var(--color-black);
}

.mo-display-field--input {
  outline: none;
  cursor: text;
}

.mo-display-field--input:focus {
  border-color: var(--color-input-border-focus);
}


.mo-display-field-label {
  position: absolute;
  left: var(--space-md);
  top: calc(var(--space-px) * -6);
  font-size: var(--font-size-2xs);
  color: var(--color-text-muted);
  background: var(--color-input-bg);
  padding: 0 var(--space-xs);
  line-height: var(--line-height-none);
  margin-left: calc(var(--space-xs) * -1);
  pointer-events: none;
}

/* ─── Import Confirm Loader ──────────────────────────────── */
.mo-import-confirm-loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-lg);
  height: 100%;
  min-height: 12rem;
  color: var(--color-text-muted);
  font-size: var(--font-size-base);
}

.mo-import-spinner {
  width: var(--space-10);
  height: var(--space-10);
  border: var(--space-0-1875) solid var(--color-border);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: mo-spin 0.7s linear infinite;
}

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

/* ─── Error Details Modal ────────────────────────────────── */
.mo-error-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: var(--space-31-25);
  max-width: 95vw;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-sm) var(--space-10) rgba(0, 0, 0, 0.18);
}

.mo-error-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: var(--space-lg) var(--space-5);
  border-bottom: var(--space-px) solid var(--color-border);
  margin: 0 var(--space-5);
  padding-left: 0;
  padding-right: 0;
}

.mo-error-modal-title-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-1875);
}

.mo-error-modal-title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
}

.mo-error-modal-subtitle {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-normal);
}

.mo-error-modal-body {
  padding: var(--space-lg) var(--space-5);
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.mo-error-modal-text {
  font-size: var(--font-size-base);
  color: var(--color-text-body);
  margin: 0;
  line-height: var(--line-height-relaxed);
}

.mo-stage-steps {
  display: flex;
  flex-direction: column;
}

.mo-stage-item {
  display: flex;
  gap: var(--space-lg);
  align-items: stretch;
}

.mo-stage-item--pending {
  opacity: 0.6;
}

.mo-stage-left {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  width: var(--space-2-25);
}

.mo-stage-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-2-25);
  height: var(--space-2-25);
  border-radius: 50%;
  flex-shrink: 0;
}

.mo-stage-icon--success {
  background: rgba(4, 151, 124, 0.12);
  border: var(--space-0-5) solid var(--color-success);
  color: var(--color-success);
}

.mo-stage-icon--failed {
  background: rgba(211, 47, 47, 0.08);
  border: var(--space-0-5) solid var(--color-error);
  color: var(--color-error);
}

.mo-stage-icon--pending {
  background: var(--color-surface, #f8f9fa);
  border: var(--space-0-5) dashed var(--color-border);
  color: var(--color-text-muted);
}

.mo-stage-line {
  width: var(--space-0-5);
  flex: 1;
  min-height: var(--space-5);
  margin-top: var(--space-0-1875);
}

.mo-stage-line--solid {
  background: var(--color-success);
}

.mo-stage-line--dashed {
  background: repeating-linear-gradient(
    to bottom,
    var(--color-text-placeholder) 0,
    var(--color-text-placeholder) var(--space-xs),
    transparent var(--space-xs),
    transparent var(--space-sm)
  );
}

.mo-stage-right {
  flex: 1;
  min-width: 0;
  padding-bottom: var(--space-5);
}

.mo-stage-item:last-child .mo-stage-right {
  padding-bottom: var(--space-sm);
}

.mo-stage-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-1875);
  padding-top: var(--space-0-4375);
}

.mo-stage-name {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
}

.mo-stage-name--success {
  color: var(--color-success);
}

.mo-stage-name--failed {
  color: var(--color-error);
}

.mo-stage-name--pending {
  color: var(--color-text-muted);
}

.mo-stage-sublabel {
  font-size: var(--font-size-md);
  color: var(--color-text-muted);
  font-weight: var(--font-weight-normal);
  line-height: 1.4;
}

.mo-stage-callout {
  position: relative;
  border: var(--space-0-09375) solid rgba(211, 47, 47, 0.35);
  border-radius: var(--radius-md);
  background: rgba(211, 47, 47, 0.04);
  overflow: hidden;
}

.mo-stage-callout-bar {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: var(--space-0-1875);
  background: var(--color-error);
}

.mo-stage-callout-inner {
  padding: var(--space-md) var(--space-3-5) var(--space-md) var(--space-4-5);
}

.mo-stage-callout-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}

.mo-stage-callout-divider {
  height: var(--space-px);
  background: rgba(211, 47, 47, 0.2);
  margin: var(--space-2-5) 0;
}

.mo-stage-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0-1875) var(--space-2-5);
  border-radius: var(--radius-pill);
  background: var(--color-error);
  color: var(--color-white);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
  flex-shrink: 0;
  letter-spacing: 0.02em;
}

.mo-stage-error-msg {
  display: flex;
  gap: var(--space-sm);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  line-height: var(--line-height-relaxed);
  margin: 0;
  align-items: flex-start;
}

.mo-stage-error-icon {
  flex-shrink: 0;
  color: var(--color-error);
  margin-top: var(--space-px);
}


/* ─── Running Scenario Modal ─────────────────────────────── */
.mo-running-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: var(--space-37-5);
  max-width: 95vw;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-sm) var(--space-10) rgba(0, 0, 0, 0.18);
}

.mo-running-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-lg) var(--space-5);
  border-bottom: var(--space-px) solid var(--color-border);
  margin: 0 var(--space-5);
  padding-left: 0;
  padding-right: 0;
}

.mo-running-modal-title {
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
}

.mo-running-modal-body {
  padding: var(--space-xxl) var(--space-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-lg);
}

.mo-running-illustration {
  margin-bottom: var(--space-md);
}

.mo-running-text-primary {
  font-size: var(--font-size-base);
  color: var(--color-success);
  font-weight: var(--font-weight-medium);
  margin: 0;
  line-height: var(--line-height-relaxed);
}

.mo-running-text-secondary {
  font-size: var(--font-size-base);
  color: var(--color-text-body);
  margin: 0;
  line-height: var(--line-height-relaxed);
}

.mo-running-error-msg {
  font-size: var(--font-size-base);
  color: var(--color-error);
  font-weight: var(--font-weight-medium);
  margin: 0;
  line-height: var(--line-height-relaxed);
  text-align: center;
}

.mo-running-modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: var(--space-md) var(--space-5);
  border-top: var(--space-px) solid var(--color-border);
  margin: 0 var(--space-5);
  padding-left: 0;
  padding-right: 0;
}
/* ─── Page Layout ────────────────────────────────────────── */
.mor-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  /* Without this, the FilterBar's dropdown panel (position: absolute, up
     to --space-22 tall) can extend past this page's own 100vh box — since
     nothing here clips it, the browser adds a genuine page-level scrollbar
     to reveal the overflow the moment the panel opens, on top of
     .mor-body's own CustomScrollbar. .um-page already has this; the other
     pages using FilterBar were missing it. */
  overflow: hidden;
}

/* Keep AppTabs non-sticky inside this page */
.mor-page .app-tabs-wrapper {
  position: static;
}

/* FilterBar: white bg, no sticky offset */
.mor-page .fb-wrapper {
  position: relative;
  top: 0;
  background: var(--color-white);
  border-bottom: none;
  margin: 0;
}


.mor-filter-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-lg);
}

.mor-body {
  flex: 1;
  min-height: 0;
}

.mor-body-content {
  padding: var(--space-md) var(--space-lg) var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ─── Breadcrumb (static above filter bar) ───────────────── */
.mor-breadcrumb-bar {
  padding: 0 var(--space-lg);
}

.mor-breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.mor-breadcrumb-item {
  color: var(--color-text-muted);
}

.mor-breadcrumb-link {
  cursor: pointer;
  transition: color 0.15s;
}

.mor-breadcrumb-link:hover {
  color: var(--color-primary);
}

.mor-breadcrumb-sep {
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
}

.mor-breadcrumb-active {
  color: var(--color-primary);
  font-weight: var(--font-weight-medium);
}

/* ─── KPI Note ───────────────────────────────────────────── */
.mor-kpi-note {
  text-align: right;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  margin-bottom: calc(var(--space-sm) * -1);
}

/* ─── KPI Row ────────────────────────────────────────────── */
.mor-kpi-row {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-md);
  overflow-x: auto;
  scrollbar-width: none;
}

.mor-kpi-row::-webkit-scrollbar {
  display: none;
}

.mor-kpi-row .kpi-card {
  min-width: var(--space-35);
  flex: 1 0 var(--space-35);
}

/* ─── Section ────────────────────────────────────────────── */
.mor-section {
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-white);
}

.mor-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--space-md) var(--space-lg);
  background: var(--color-section-header-bg);
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: left;
  transition: background var(--motion-duration-fast) ease;
}


.mor-section-header--open {
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}

.mor-section-header:hover {
  background: var(--color-section-header-bg-hover);
}

.mor-section-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  font-family: var(--font-family-base);
}

.mor-section-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.mor-icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  /* padding-sized like the simulator's .mo-section-refresh-btn so the
     accordion header height matches the Existing/Create Scenario sections */
  padding: var(--space-xs);
  background: none;
  border: none;
  color: var(--color-primary);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background 0.15s,
    color 0.15s;
}

.mor-icon-btn:hover {
  background: var(--color-section-icon-hover-bg);
  color: var(--color-primary);
}

.mor-section-chevron {
  display: flex;
  align-items: center;
  color: var(--color-primary);
  transition: transform 0.2s;
}

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

.mor-section-body {
  padding: var(--space-lg);
  border-top: var(--space-px) solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* ─── Chart Legend ───────────────────────────────────────── */
.mor-chart-legend {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-lg);
  margin-bottom: var(--space-md);
}

.mor-legend-item {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  /* Match Plotly legend labels (chartFontSize.sm) so HTML and chart legends read as one size */
  font-size: var(--chart-font-size-sm);
  color: var(--color-black);
  font-weight: var(--font-weight-regular);
}

.mor-legend-dot {
  width: var(--space-3-5);
  height: var(--space-3-5);
  border-radius: var(--space-0-1875);
}

.mor-legend-dot--blue {
  background: var(--color-accent);
}

.mor-legend-dot--red {
  background: var(--color-error);
}

.mor-legend-dot--teal {
  background: #00CAB8;
}

/* ─── Bar Chart ──────────────────────────────────────────── */
.mor-chart {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.mor-chart-row {
  display: grid;
  grid-template-columns: 200px 1fr 80px;
  align-items: center;
  gap: var(--space-md);
}

.mor-chart-label {
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-weight: var(--font-weight-medium);
}

.mor-chart-bar-wrap {
  height: var(--space-xxl);
  background: var(--color-lightgrey);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.mor-chart-bar {
  height: 100%;
  transition: width 0.3s ease;
}

.mor-chart-bar--blue {
  background: var(--color-accent);
}

.mor-chart-bar--red {
  background: var(--color-error);
}

.mor-chart-bar--teal {
  background: var(--color-success);
}

.mor-chart-value {
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  font-weight: var(--font-weight-semibold);
  text-align: right;
}

/* ─── Section Divider ────────────────────────────────────── */
.mor-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
}

/* ─── Mini Bar Chart (inline in table cells) ─────────────── */
.mor-mini-bar-cell {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  min-width: var(--space-4);
}

.mor-mini-bar-track {
  height: var(--space-xs);
  background: var(--color-lightgrey);
  border-radius: var(--space-0-5);
  overflow: hidden;
}

.mor-mini-bar-fill {
  height: 100%;
  border-radius: var(--space-0-5);
  transition: width 0.3s ease;
}

.mor-mini-bar-fill--pos {
  background: var(--color-success);
}

.mor-mini-bar-fill--neg {
  background: var(--color-error);
}

/* ─── Scenario Header ────────────────────────────────────── */
.mor-scenario-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  padding: var(--space-md) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
  background: var(--color-section-header-bg);
}

.mor-scenario-header::-webkit-scrollbar {
  display: none;
}

.mor-scenario-info {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.mor-scenario-label {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
}

.mor-scenario-name {
  font-size: var(--font-size-md);
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mor-scenario-meta {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  flex-shrink: 0;
}

.mor-scenario-date {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mor-toggle-label {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  cursor: pointer;
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
}

.mor-toggle-checkbox {
  width: var(--space-4);
  height: var(--space-4);
  accent-color: var(--color-primary);
  cursor: pointer;
}

.mor-recap-btn {
  padding: var(--space-0-4375) var(--space-lg);
  border: var(--space-px) solid var(--color-primary);
  border-radius: var(--radius-sm);
  font-family: var(--font-family-display);
  background: var(--color-white);
  color: var(--color-primary);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition: background 0.15s;
}

.mor-recap-btn:hover {
  background: var(--color-bg-hover-light);
}

/* ─── View Toggle ────────────────────────────────────────── */
.mor-view-toggle {
  display: flex;
  align-items: center;
  gap: 0;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  width: fit-content;
  padding: var(--space-px);
}

.mor-tab-btn {
  padding: var(--space-xs) var(--space-md);
  border: none;
  background: transparent;
  color: var(--color-text-body);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  font-family: var(--font-family-display);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background 0.15s,
    color 0.15s;
}

.mor-tab-btn:hover {
  background: var(--color-lightgrey);
}

.mor-tab-btn--active {
  background: var(--color-primary);
  color: var(--color-white);
}

.mor-tab-btn--active:hover {
  background: var(--color-navbar);
}

/* ─── Table Section ──────────────────────────────────────── */
.mor-table-section {
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-white);
  overflow: hidden;
}

.mor-table-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  background: var(--color-lightgrey);
  border-bottom: var(--space-px) solid var(--color-border);
}

.mor-table-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.mor-icon-btn-outline {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  padding: var(--space-1-5) var(--space-md);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text-body);
  font-size: var(--font-size-base);
  cursor: pointer;
  transition:
    background 0.15s,
    border-color 0.15s;
}

.mor-icon-btn-outline:hover {
  background: var(--color-bg-hover-light);
  border-color: var(--color-primary);
}

/* ─── Compare Section ────────────────────────────────────── */
.mor-compare-section {
  display: flex;
  justify-content: flex-end;
  padding: var(--space-md) 0;
}

.mor-compare-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-display);
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease;
}

.mor-compare-btn:hover {
  background: var(--color-primary-hover);
}

.mor-compare-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ─── Legend dots (additional colours) ──────────────────── */
.mor-legend-dot--grey {
  background: #C8C8C8;
}

.mor-legend-dot--pink {
  background: #ec4899;
}

/* ─── Table toolbar ──────────────────────────────────────── */
.mor-table-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-lg);
}

.mor-table-toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.mor-icon-btn-sm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--color-primary);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background 0.15s,
    color 0.15s;
  padding: var(--space-0-8);
}

.mor-icon-btn-sm:hover {
  background: var(--color-section-icon-hover-bg);
  color: var(--color-primary);
}

/* ─── Results table ──────────────────────────────────────── */
.mor-table-scroll-wrap {
  width: 100%;
  /* Contain CustomScrollbar's thumb (z-index: 100) in its own stacking context
     so it can't paint over the rows-per-page dropdown opening up from the
     pagination footer below. */
  isolation: isolate;
}




.mor-results-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
  /* Let columns grow based on content to avoid bar overlap */
  table-layout: auto;
}


.mor-results-table thead {
  background: var(--color-lightgrey);
}

.mor-results-table th {
  padding: var(--space-sm) var(--space-lg);
  text-align: center;
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  border-bottom: var(--space-px) solid var(--color-border);
  white-space: nowrap;
  background: var(--color-lightgrey);
  vertical-align: middle;
}

.mor-th-sortable {
  cursor: pointer;
  user-select: none;
}

.mor-th-sortable:hover {
  background: var(--color-border);
}

/* Metric header labels carrying a definition tooltip. The whole <th> sorts on
   click, so keep the pointer cursor rather than MetricTooltip's help cursor. */
.mor-th-tip {
  cursor: inherit;
}

.mor-th-tip:focus-visible {
  outline: var(--space-0-5) solid var(--color-primary);
  outline-offset: var(--space-0-4);
  border-radius: var(--radius-sm);
}

.mor-results-table th.mor-th-channel {
  width: var(--space-9);
  min-width: var(--space-9);
  max-width: var(--space-9);
  text-align: center;
}

.mor-th-filter-wrap {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  justify-content: center;
}

.mor-th-filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-0-5);
  background: none;
  border: none;
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background var(--motion-duration-fast) ease;
}

.mor-th-filter-btn:hover {
  background: var(--color-bg-hover-light);
}

.mor-col-filter-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9998;
}

.mor-results-table th.mor-th-platform {
  width: var(--space-9);
  min-width: var(--space-9);
  max-width: var(--space-9);
  text-align: center;
}

.mor-results-table th.mor-th-metric {
  text-align: center;
  width: 1px;
}

.mor-th-flat {
  text-align: center;
}

.mor-td-flat {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.mor-icon-btn-sm--active {
  color: var(--color-primary);
  border-radius: var(--radius-sm);
}

.mor-tab-btn--disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.mor-results-table td {
  padding: var(--space-sm) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
  vertical-align: middle;
  background: var(--color-white);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  white-space: nowrap;
  text-align: center;
}

.mor-results-table tbody tr:hover td {
  background: var(--color-bg-hover-light);
}

.mor-results-table td.mor-td-channel {
  padding: var(--space-sm) var(--space-xs) var(--space-sm) var(--space-lg);
  width: var(--space-9);
  min-width: var(--space-9);
  max-width: var(--space-9);
  text-align: center;
  white-space: normal;
  word-break: break-word;
}

.mor-results-table td.mor-td-platform {
  padding: var(--space-sm) var(--space-xs) var(--space-sm) var(--space-lg);
  width: var(--space-9);
  min-width: var(--space-9);
  max-width: var(--space-9);
  text-align: center;
  white-space: normal;
  word-break: break-word;
}



.mor-platform-name {
  display: block;
  font-weight: var(--font-weight-regular);
  color: var(--color-text-body);
  font-size: var(--font-size-sm);
  white-space: normal;
  word-break: break-word;
  overflow-wrap: break-word;
}

.mor-channel-row {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-xs);
}

.mor-channel-name {
  display: block;
  font-weight: var(--font-weight-medium);
  color: var(--color-text-body);
  font-size: var(--font-size-sm);
  white-space: normal;
  word-break: break-word;
  overflow-wrap: break-word;
  flex: 1;
  min-width: 0;
}

.mor-linechart-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-5);
  height: var(--space-5);
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  padding: 0;
  transition:
    color 0.15s,
    background 0.15s;
}

.mor-linechart-btn:hover {
  color: var(--color-primary);
  background: var(--color-section-icon-hover-bg);
}

/* ─── Icon column (dedicated narrow column for response curve icon) ── */
.mor-th-icon {
  width: var(--space-10);
  padding: var(--space-sm) var(--space-xs);
}

.mor-td-icon {
  width: var(--space-10);
  padding: var(--space-sm) var(--space-xs);
  text-align: center;
}

.mor-results-table td.mor-td-metric {
  padding: var(--space-sm) var(--space-xs) var(--space-sm) var(--space-md);
  width: 1px;
}

/* ─── Metric cell with bars ──────────────────────────────── */
.mor-metric-cell {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
}

.mor-metric-cell--no-change {
  justify-content: flex-start;
}

.mor-bars-block {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-0-1875);
}

.mor-bar-row {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.mor-bar-value {
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-body);
  white-space: nowrap;
  flex-shrink: 0;
  text-align: left;
  width: var(--space-12);
}

.mor-bar-track {
  width: var(--space-9);
  flex-shrink: 0;
  height: var(--space-2-5);
  background: var(--color-lightgrey);
  border-radius: var(--space-lg);
  overflow: hidden;
  cursor: default;
}

.mor-bar-fill {
  height: 100%;
  border-radius: var(--space-0-5);
  transition: width 0.3s ease;
}

.mor-bar-fill--teal {
  background: #00CAB8;
}

.mor-bar-fill--grey {
  background: #C8C8C8;
}

.mor-bar-row:hover .mor-bar-fill--teal,
.mor-results-table tbody tr:hover .mor-bar-fill--teal {
  background: #00CAB8;
  filter: brightness(1.1);
}

.mor-bar-row:hover .mor-bar-fill--grey,
.mor-results-table tbody tr:hover .mor-bar-fill--grey {
  background: #C8C8C8;
  filter: brightness(1.15);
}

.mor-bar-row:hover .mor-bar-track,
.mor-results-table tbody tr:hover .mor-bar-track {
  background: var(--color-border);
}

/* Bar hover tooltip */
.mor-bar-tooltip-wrap {
  position: relative;
  flex: 1;
  min-width: 0;
}

.mor-bar-tooltip-wrap[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + var(--space-1-5));
  left: 50%;
  transform: translateX(-50%);
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  white-space: nowrap;
  pointer-events: none;
  z-index: 100;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
}

.mor-bar-tooltip-wrap[data-tooltip]:hover::before {
  content: "";
  position: absolute;
  bottom: calc(100% + var(--space-px));
  left: 50%;
  transform: translateX(-50%);
  border: var(--space-1-2) solid transparent;
  border-top-color: var(--color-tooltip-bg);
  pointer-events: none;
  z-index: 100;
}

/* ─── Change Indicator ───────────────────────────────────── */
.mor-change-indicator {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
  color: var(--color-text-muted);
  width: var(--space-20);
  flex-shrink: 0;
  text-align: right;
}

.mor-change-indicator--positive {
  color: #28a745;
}

.mor-change-indicator--negative {
  color: #dc3545;
}

.mor-change-indicator--empty {
  color: var(--color-text-muted);
  font-weight: var(--font-weight-normal);
}

/* ─── Toggle switch (pill style) ─────────────────────────── */
.mor-toggle-row {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.mor-toggle-text {
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
}

.mor-toggle-switch {
  position: relative;
  display: inline-block;
  width: var(--space-2-25);
  height: var(--space-5);
  flex-shrink: 0;
}

.mor-toggle-input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute;
}

.mor-toggle-slider {
  position: absolute;
  inset: 0;
  background: var(--color-lightgrey);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: background 0.2s;
  border: var(--space-px) solid var(--color-kpigrey);
}

.mor-toggle-slider::before {
  content: "";
  position: absolute;
  width: var(--space-3-5);
  height: var(--space-3-5);
  left: var(--space-0-1875);
  top: var(--space-0-1875);
  background: var(--color-text-placeholder);
  border-radius: 50%;
  transition: transform 0.2s;
}

.mor-toggle-input:checked + .mor-toggle-slider {
  background: var(--color-primary);
}

.mor-toggle-input:checked + .mor-toggle-slider::before {
  transform: translateX(var(--space-lg));
}

/* ─── Response Curve Modal ───────────────────────────────── */
.mor-modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--color-backdrop-overlay);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mor-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: min(72rem, 92vw);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-5) var(--space-15) var(--color-shadow-tooltip);
  overflow: hidden;
}

.mor-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
  background: var(--color-lightgrey);
  flex-shrink: 0;
}

.mor-modal-title {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
}

.mor-modal-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.mor-modal-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-7);
  height: var(--space-7);
  border: none;
  background: none;
  color: var(--color-text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background var(--motion-duration-fast),
    color var(--motion-duration-fast);
  padding: 0;
}

.mor-modal-close:hover {
  background: var(--color-bg-hover-light);
  color: var(--color-primary);
}

.mor-modal-body {
  overflow-y: auto;
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.mor-modal-chart-label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  margin-bottom: calc(var(--space-xs) * -1);
}
.mor-modal-chart-label--center {
  text-align: center;
}

/* ─── Responsive ─────────────────────────────────────────── */
@media (max-width: 1200px) {
  .mor-kpi-row {
    flex-wrap: wrap;
  }

  .mor-chart-row {
    grid-template-columns: 150px 1fr 70px;
  }
}

/* Below ~600px, flex-wrap's natural reflow depends on each card's own
   min-width vs. the exact remaining space, which can land on 1-per-row
   (a lot of dead space beside each card) as often as 2. Switch to an
   explicit 2-column grid so mobile always gets a predictable 2-and-2
   layout; an odd trailing card spans both columns instead of leaving an
   empty cell beside it. */
@media (max-width: 600px) {
  .mor-kpi-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  .mor-kpi-row .kpi-card:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}

@media (max-width: 768px) {
  .mor-chart-row {
    grid-template-columns: 1fr;
    gap: var(--space-xs);
  }

  .mor-chart-bar-wrap {
    height: 1.5rem;
  }

  .mor-table-actions {
    flex-wrap: wrap;
  }

  /* .mor-table-toolbar (Channel/Platform toggle + legend + view/download
     icons) is a single nowrap flex row with no responsive treatment at
     all — at narrow widths its combined content (toggle + 2 legend items
     + 2 icon buttons) overflows the card, cutting off the "Base" legend
     item and the download icon past the right edge. Let the toolbar wrap,
     with the legend/icons dropping to their own right-aligned row below
     the Channel/Platform toggle. */
  .mor-table-toolbar {
    flex-wrap: wrap;
    row-gap: var(--space-sm);
  }

  .mor-table-toolbar-right {
    flex-wrap: wrap;
    justify-content: flex-end;
    flex: 1 0 100%;
  }
}

/* ─── Recap Constraints Modal ────────────────────────────── */
.mor-rc-modal {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: min(60rem, 95vw);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-5) var(--space-15) var(--color-shadow-tooltip);
  overflow: hidden;
}

.mor-rc-info {
  border-bottom: var(--space-px) solid var(--color-border);
  display: flex;
  flex-direction: column;
  background: var(--color-lightgrey);
}

.mor-rc-info-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
  padding: var(--space-sm) var(--space-lg);
  border-bottom: var(--space-px) solid var(--color-border);
}

.mor-rc-info-row:last-child {
  border-bottom: none;
}

.mor-rc-info-cell {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.mor-rc-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-xl);
  height: var(--space-xl);
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: var(--color-white);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  flex-shrink: 0;
}

.mor-rc-info-text {
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
}

.mor-rc-info-label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
}

.mor-rc-info-value {
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
}

.mor-rc-tabs {
  display: flex;
  align-items: flex-end;
  gap: 0;
  border-bottom: calc(var(--space-px) * 2) solid var(--color-border);
  padding: 0 var(--space-lg);
  flex-shrink: 0;
}

.mor-rc-tab {
  padding: var(--space-sm) var(--space-md);
  border: none;
  background: none;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  cursor: pointer;
  border-bottom: calc(var(--space-px) * 2) solid transparent;
  margin-bottom: calc(var(--space-px) * -2);
  transition:
    color var(--motion-duration-fast),
    border-color var(--motion-duration-fast);
  font-family: var(--font-family-display);
}

.mor-rc-tab:hover {
  color: var(--color-primary);
}

.mor-rc-tab--active {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
}

.mor-rc-body {
  flex: 1;
  padding: var(--space-md) var(--space-lg);
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* Recap constraints modal DataTable should scroll within its own maxHeight */
.mor-rc-body .dt-inner-h {
  max-height: var(--dt-max-h, 260px);
}

/* Channel/Platform names must size to content on one line, not wrap; the
   table's existing horizontal scrollbar takes over if columns overflow. */
.mor-rc-body .dt-table td.mor-rc-td-nowrap {
  white-space: nowrap;
}


.mor-toggle-saving {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  margin-left: var(--space-1-5);
  font-style: italic;
}
/* ─── Page Layout ────────────────────────────────────────── */
.moc-page {
  height: 100vh;
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  padding-top: var(--space-10);
  /* Without this, the FilterBar's dropdown panel (position: absolute, up
     to --space-22 tall) can extend past this page's own 100vh box — since
     nothing here clips it, the browser adds a genuine page-level scrollbar
     to reveal the overflow the moment the panel opens, on top of
     .moc-body's own CustomScrollbar. .um-page already has this; the other
     pages using FilterBar were missing it. */
  overflow: hidden;
}

.moc-page .app-tabs-wrapper {
  position: static;
}

.moc-page .fb-wrapper {
  position: relative;
  top: 0;
  background: var(--color-white);
  border-bottom: none;
  margin: 0;
}

.moc-filter-divider {
  height: var(--space-px);
  background: var(--color-kpigrey);
  margin: 0 var(--space-lg);
}

.moc-body {
  flex: 1;
  min-height: 0;
}

.moc-body-content {
  padding: var(--space-md) var(--space-lg) var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* ─── Breadcrumb ─────────────────────────────────────────── */
.moc-breadcrumb-bar {
  padding: 0 var(--space-lg);
}

.moc-breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.moc-breadcrumb-item {
  color: var(--color-text-muted);
}
.moc-breadcrumb-link {
  cursor: pointer;
  transition: color var(--motion-duration-fast);
}
.moc-breadcrumb-link:hover {
  color: var(--color-primary);
}
.moc-breadcrumb-sep {
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
}
.moc-breadcrumb-active {
  color: var(--color-primary);
  font-weight: var(--font-weight-medium);
}

/* ─── Icon button ────────────────────────────────────────── */
.moc-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-7);
  height: var(--space-7);
  border: none;
  background: none;
  color: var(--color-primary);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background var(--motion-duration-fast),
    color var(--motion-duration-fast);
  padding: 0;
}

.moc-icon-btn:hover {
  background: var(--color-bg-hover-light);
  color: var(--color-primary);
}

.moc-icon-btn-outline {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-1-5) var(--space-3-5);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  color: var(--color-text-body);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-display);
  cursor: pointer;
  transition:
    background var(--motion-duration-fast),
    border-color var(--motion-duration-fast);
}

.moc-icon-btn-outline:hover {
  background: var(--color-bg-hover-light);
  border-color: var(--color-primary);
}

/* ─── Section (Insights) ─────────────────────────────────── */
.moc-section {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-white);
}

.moc-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--space-md) var(--space-md);
  background: var(--color-section-header-bg);
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: left;
  transition: background var(--motion-duration-fast) ease;
}

.moc-section-header:hover {
  background: var(--color-section-header-bg-hover);
}

.moc-section-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
}

.moc-section-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.moc-section-chevron {
  display: flex;
  align-items: center;
  color: var(--color-primary);
  transition: transform var(--motion-duration-normal);
}

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

.moc-section-body {
  padding: var(--space-lg);
  border-top: 1px solid var(--color-border);
}

/* ─── Insight Cards ──────────────────────────────────────── */
.moc-insight-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
}

.moc-insight-card {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.moc-insight-text {
  flex: 1;
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  line-height: var(--line-height-relaxed);
}

/* ─── Title ──────────────────────────────────────────────── */
.moc-comparison-title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  margin: 0;
}

/* ─── Toolbar ────────────────────────────────────────────── */
.moc-toolbar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.moc-toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.moc-view-toggle {
  display: flex;
  align-items: center;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-white);
  width: fit-content;
  padding: var(--space-0-5);
}

.moc-tab-btn {
  padding: var(--space-1-5) var(--space-lg);
  border: none;
  background: transparent;
  color: var(--color-text-body);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  font-family: var(--font-family-display);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition:
    background var(--motion-duration-fast),
    color var(--motion-duration-fast);
}

.moc-tab-btn--icon {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
}

.moc-tab-btn:hover {
  background: var(--color-lightgrey);
}
.moc-tab-btn--active {
  background: var(--color-primary);
  color: var(--color-white);
}
.moc-tab-btn--active:hover {
  background: var(--color-navbar);
}
.moc-tab-btn--disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ─── Table wrap ─────────────────────────────────────────── */
.moc-table-wrap {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-white);
}

.moc-table-inner {
  overflow-x: auto;
  width: 100%;
}

/* ─── Table base ─────────────────────────────────────────── */
.moc-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-size-sm);
  background: var(--color-white);
}

/* ── Header row 1 — Scenario Type ── */
.moc-thead-type th {
  padding: var(--space-md) var(--space-md);
  background: var(--color-tablegrey);
  text-align: center;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}

/* ── Header row 2 — Scenario Name ── */
.moc-thead-name th {
  padding: var(--space-md) var(--space-md);
  background: var(--color-tablegrey);
  text-align: center;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}

/* ── Header row 3 — Metric columns (auto-generated by DataTable) ── */
.moc-datatable-wrap .dt-table thead tr:last-child th {
  padding: var(--space-sm) var(--space-md);
  background: var(--color-lightgrey);
  text-align: center;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  border-bottom: calc(var(--space-px) * 2) solid var(--color-border);
  white-space: nowrap;
}

/* ── Scenario group left border ── */
.moc-th-group-border,
.moc-td-group-border {
  border-left: 2px solid var(--color-border);
}

.moc-th-metric-cell {
  min-width: 110px;
}

/* ─── Table body ─────────────────────────────────────────── */
.moc-table td {
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text-body);
  font-size: var(--font-size-sm);
}

.moc-table tbody tr:hover {
  background: var(--color-bg-hover-light);
}

.moc-td-value {
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ─── DataTable wrapper ──────────────────────────────────── */
.moc-datatable-wrap {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.moc-datatable-wrap .dt-table {
  border-collapse: separate;
  border-spacing: 0;
}

/*
 * Sticky header + sticky columns together:
 * DataTable.css uses `thead tr { position: sticky; top: 0 }` for vertical
 * stickiness, but a sticky tr prevents its th children from being sticky
 * horizontally. Fix: make thead itself sticky (supported in all modern
 * browsers), reset tr to static so th cells can independently stick left.
 */
.moc-datatable-wrap .dt-table thead {
  position: sticky;
  top: 0;
  z-index: 10;
}
.moc-datatable-wrap .dt-table thead tr {
  position: static;
}

.moc-datatable-wrap .dt-table thead th {
  position: static;
  top: auto;
}

/* Column filter dropdown height is sized inline (MediaOptimisationComparison.tsx,
   passed to CustomScrollbar's maxHeight prop). Don't give .dt-multi-list/.csb-content
   their own max-height + overflow-y:auto here — that creates a second native scroll
   region nested inside CustomScrollbar's own, so the custom thumb stops short of the
   list's real scroll range. */


/* Sticky fixed columns in header */
.moc-datatable-wrap .dt-table thead th.moc-th-fixed {
  position: sticky;
  background: var(--color-lightgrey);
  z-index: 11;
  text-align: center;
  vertical-align: middle;
  border-right: calc(var(--space-px) * 2) solid var(--color-border);
}

.moc-datatable-wrap .dt-table thead th.moc-th-channel-cell {
  left: 0;
  min-width: 160px;
  max-width: 160px;
}

.moc-datatable-wrap .dt-table thead th.moc-th-platform-cell {
  left: 160px;
  min-width: 160px;
  max-width: 160px;
}

/* Sticky fixed columns in body */
.moc-datatable-wrap .dt-table tbody td.moc-td-fixed {
  position: sticky;
  background: var(--color-white);
  z-index: 5;
  border-right: calc(var(--space-px) * 2) solid var(--color-border);
  font-weight: var(--font-weight-regular);
}

.moc-datatable-wrap .dt-table tbody td.moc-td-channel {
  left: 0;
  min-width: 160px;
  max-width: 160px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.moc-datatable-wrap .dt-table tbody td.moc-td-platform {
  left: 160px;
  min-width: 160px;
  max-width: 160px;
}

/* Channel cell's ellipsis lives on the inner span (a block child isn't clipped
   by the td's own text-overflow), so the whole cell — including the "…" —
   is the hover target for the span's title tooltip. */
.moc-datatable-wrap .dt-table tbody td.moc-td-channel .moc-td-name {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.moc-datatable-wrap .dt-table tbody tr:hover td.moc-td-fixed {
  background: var(--color-bg-hover-light);
}

/* Multi-line renderHeader() — 3 stacked lines per metric column */
.moc-th-multi {
  display: flex;
  flex-direction: column;
  gap: var(--space-px);
  padding: var(--space-0-5) 0;
  min-width: 0;
}

/* Left border = new scenario group */
.moc-th-group-border {
  border-left: calc(var(--space-px) * 2) solid var(--color-border);
  padding-left: var(--space-xs);
  margin-left: calc(var(--space-xs) * -1);
}

/* Row 1 — scenario type */
.moc-th-type-lbl {
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: var(--line-height-normal);
}

/* Row 2 — scenario name */
.moc-th-name-lbl {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: var(--line-height-normal);
}

/* Invisible spacers keep height consistent across all columns in a group */
.moc-th-hidden {
  visibility: hidden;
  pointer-events: none;
}

/* Row 3 — metric name, separated by top border */
.moc-th-metric-lbl {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
  white-space: nowrap;
  line-height: var(--line-height-normal);
  margin-top: var(--space-0-8);
  padding-top: var(--space-0-8);
  border-top: var(--space-px) solid var(--color-border);
}

/* ─── Selected scenario highlight ───────────────────────── */
.moc-datatable-wrap .dt-table tbody td.moc-td-selected {
  background: var(--color-tablegrey);
}
.moc-datatable-wrap .dt-table tbody tr:hover td.moc-td-selected {
  background: var(--color-bg-hover-light);
}

/* ─── Cell value with inline change ─────────────────────── */
.moc-cell-value {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  white-space: nowrap;
}

.moc-change-inline {
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-medium);
}

.moc-change-inline--positive { color: var(--color-success); }
.moc-change-inline--negative { color: var(--color-error); }
.moc-change-inline--neutral  { color: var(--color-text-placeholder); }

/* ─── Channel header filter wrap ────────────────────────── */
.moc-th-filter-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
}

.moc-col-filter-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9998;
}

/* ─── Table footer ───────────────────────────────────────── */
.moc-table-footer {
  display: flex;
  justify-content: flex-end;
  padding: var(--space-sm) var(--space-lg);
  border-top: 1px solid var(--color-border);
  background: var(--color-lightgrey);
}

/* ─── Charts view ────────────────────────────────────────── */
.moc-charts-view {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.moc-kpi-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.moc-kpi-group-label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
  padding-bottom: var(--space-xs);
  border-bottom: 2px solid var(--color-primary);
  width: fit-content;
}

.moc-kpi-row {
  display: flex;
  gap: var(--space-md);
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
}

.moc-kpi-row::-webkit-scrollbar {
  display: none;
}

.moc-kpi-row .kpi-card {
  min-width: var(--space-35);
  flex: 1 0 var(--space-35);
}

/* ─── Responsive ─────────────────────────────────────────── */
@media (max-width: 1200px) {
  .moc-insight-grid {
    grid-template-columns: 1fr;
  }
  .moc-th-metric-cell {
    min-width: 90px;
  }
  .moc-kpi-row {
    flex-wrap: wrap;
  }
}

@media (max-width: 768px) {
  .moc-toolbar-row {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-sm);
  }
  .moc-kpi-row {
    flex-wrap: wrap;
  }
}

/* Below ~600px, flex-wrap's natural reflow depends on each card's own
   min-width vs. the exact remaining space, which can land on 1-per-row
   (a lot of dead space beside each card) as often as 2. Switch to an
   explicit 2-column grid so mobile always gets a predictable 2-and-2
   layout; an odd trailing card spans both columns instead of leaving an
   empty cell beside it. */
@media (max-width: 600px) {
  .moc-kpi-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }

  .moc-kpi-row .kpi-card:nth-child(odd):last-child {
    grid-column: 1 / -1;
  }
}
/* Stage-progress popup opened from a card's clickable status badge.
   Structurally mirrors the old optimizer's "Scenario Status" modal
   (MediaOptimisationSimulator.css, the mo-error-modal / mo-stage- classes),
   rebuilt with plain design tokens — this popup has no Figma frame of its
   own (the old-optimizer one it mirrors doesn't use the ohf pixel/scale
   system either), so sizes come from the shared font-size/space token
   scales rather than Figma-node rem literals. */
.ssm-backdrop {
  position: fixed;
  inset: 0;
  background: var(--color-backdrop-overlay);
  /* One above the dialogs that can open this popup (RecentOptimizationsModal /
     ViewPortfolioModal, both 1000) so it always stacks over them. */
  z-index: 1001;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
  animation: ssm-fade-in var(--motion-duration-fade) var(--motion-easing-enter) both;
}

.ssm-dialog {
  background: var(--color-white);
  border-radius: var(--radius-md);
  width: var(--space-31-25);
  max-width: 95vw;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 var(--space-sm) var(--space-10) var(--color-shadow-modal-lg);
  animation: ssm-pop-in var(--motion-duration-slow) var(--motion-easing-spring) both;
}

@keyframes ssm-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes ssm-pop-in {
  from {
    opacity: 0;
    transform: translateY(var(--space-md)) scale(0.96);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.ssm-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-5) var(--space-md);
  border-bottom: var(--space-px) solid var(--color-border);
}

.ssm-title-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  min-width: 0;
}

.ssm-title {
  font-family: var(--ohf-body);
  font-size: var(--font-size-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-body);
}

.ssm-subtitle {
  font-family: var(--ohf-body);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-regular);
  color: var(--color-text-muted);
}

.ssm-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-xxl);
  height: var(--space-xxl);
  flex-shrink: 0;
  border: none;
  background: transparent;
  color: var(--color-text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--motion-duration-fast) var(--motion-easing-standard);
}

.ssm-close:hover {
  background: var(--color-bg-hover-light);
  color: var(--color-text-body);
}

.ssm-close-icon {
  width: var(--space-sm);
  height: var(--space-sm);
}

.ssm-body {
  padding: var(--space-lg) var(--space-5);
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.ssm-empty {
  font-family: var(--ohf-body);
  font-size: var(--font-size-base);
  color: var(--color-text-muted);
  margin: 0;
  line-height: var(--line-height-relaxed);
}

/* ── Vertical stepper ── */
.ssm-stage-steps {
  display: flex;
  flex-direction: column;
}

.ssm-stage-item {
  display: flex;
  gap: var(--space-lg);
  align-items: stretch;
  /* Staggered reveal: each stage slides in after the dialog lands, delayed by
     its index (--ssm-stage-index, set inline per item in the TSX). */
  animation: ssm-stage-in var(--motion-duration-normal) var(--motion-easing-enter) both;
  animation-delay: calc(var(--motion-duration-fade) + var(--ssm-stage-index, 0) * var(--motion-duration-stagger));
}

@keyframes ssm-stage-in {
  from {
    opacity: 0;
    transform: translateY(var(--space-sm));
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Pending rows are dimmed; their reveal keyframe lands on the same 0.6 so
   the stagger and the resting opacity can't fight. */
.ssm-stage-item--pending {
  opacity: 0.6;
  animation-name: ssm-stage-in-pending;
}

@keyframes ssm-stage-in-pending {
  from {
    opacity: 0;
    transform: translateY(var(--space-sm));
  }
  to {
    opacity: 0.6;
    transform: translateY(0);
  }
}

.ssm-stage-left {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  width: var(--space-2-25);
}

.ssm-stage-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-2-25);
  height: var(--space-2-25);
  border-radius: var(--radius-full);
  flex-shrink: 0;
  animation: ssm-icon-pop var(--motion-duration-slow) var(--motion-easing-spring) both;
  animation-delay: calc(var(--motion-duration-fade) + var(--ssm-stage-index, 0) * var(--motion-duration-stagger));
}

@keyframes ssm-icon-pop {
  from {
    transform: scale(0.4);
  }
  to {
    transform: scale(1);
  }
}

/* Check / cross strokes draw themselves in once their row has appeared
   (pathLength=1 in the TSX normalises every stroke to the same 0..1 range). */
.ssm-draw-stroke {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: ssm-stroke-draw var(--motion-duration-draw) var(--motion-easing-standard) forwards;
  animation-delay: calc(
    var(--motion-duration-fade) + var(--ssm-stage-index, 0) * var(--motion-duration-stagger) +
      var(--motion-duration-fast)
  );
}

.ssm-draw-stroke--second {
  animation-delay: calc(
    var(--motion-duration-fade) + var(--ssm-stage-index, 0) * var(--motion-duration-stagger) +
      var(--motion-duration-fast) + var(--motion-duration-draw) / 2
  );
}

@keyframes ssm-stroke-draw {
  to {
    stroke-dashoffset: 0;
  }
}

.ssm-stage-icon--success {
  background: var(--color-success-bg);
  border: var(--space-0-5) solid var(--color-success);
  color: var(--color-success);
}

.ssm-stage-icon--failed {
  background: var(--color-danger-bg);
  border: var(--space-0-5) solid var(--color-error);
  color: var(--color-error);
}

.ssm-stage-icon--pending {
  background: var(--color-bg-subtle);
  border: var(--space-0-5) dashed var(--color-border);
  color: var(--color-text-muted);
}

/* Pending dot breathes gently — the "waiting" affordance. Delayed by the
   row's own stagger so the pulse starts only once the icon has popped in. */
.ssm-stage-icon--pending svg {
  animation: ssm-pending-pulse calc(var(--motion-duration-spin) * 2) var(--motion-easing-ease-in-out) infinite;
  animation-delay: calc(var(--motion-duration-fade) + var(--ssm-stage-index, 0) * var(--motion-duration-stagger));
}

@keyframes ssm-pending-pulse {
  0%,
  100% {
    opacity: 0.5;
    transform: scale(0.85);
  }
  50% {
    opacity: 1;
    transform: scale(1.15);
  }
}

.ssm-stage-line {
  width: var(--space-0-5);
  flex: 1;
  min-height: var(--space-5);
  margin-top: var(--space-0-1875);
  /* Grows downward as the next stage reveals, reading as "progress flowing". */
  transform-origin: top;
  animation: ssm-line-grow var(--motion-duration-normal) var(--motion-easing-standard) both;
  animation-delay: calc(
    var(--motion-duration-fade) + (var(--ssm-stage-index, 0) + 1) * var(--motion-duration-stagger)
  );
}

@keyframes ssm-line-grow {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

.ssm-stage-line--solid {
  background: var(--color-success);
}

.ssm-stage-line--dashed {
  background: repeating-linear-gradient(
    to bottom,
    var(--color-text-placeholder) 0,
    var(--color-text-placeholder) var(--space-xs),
    transparent var(--space-xs),
    transparent var(--space-sm)
  );
}

.ssm-stage-right {
  flex: 1;
  min-width: 0;
  padding-bottom: var(--space-5);
}

.ssm-stage-item:last-child .ssm-stage-right {
  padding-bottom: var(--space-sm);
}

.ssm-stage-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-0-1875);
  padding-top: var(--space-0-4375);
}

.ssm-stage-name {
  font-family: var(--ohf-body);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
}

.ssm-stage-name--success {
  color: var(--color-success);
}

.ssm-stage-name--failed {
  color: var(--color-error);
}

.ssm-stage-name--pending {
  color: var(--color-text-muted);
}

.ssm-stage-sublabel {
  font-family: var(--ohf-body);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-regular);
  color: var(--color-text-muted);
  line-height: var(--line-height-relaxed);
}

/* ── Failed-stage callout ── */
.ssm-stage-callout {
  position: relative;
  border: var(--space-0-09375) solid var(--color-danger);
  border-radius: var(--radius-md);
  background: var(--color-danger-bg);
  overflow: hidden;
}

.ssm-stage-callout-bar {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: var(--space-0-1875);
  background: var(--color-error);
}

.ssm-stage-callout-inner {
  padding: var(--space-md) var(--space-3-5) var(--space-md) var(--space-4-5);
}

.ssm-stage-callout-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
}

.ssm-stage-callout-divider {
  height: var(--space-px);
  background: var(--color-danger-bg);
  margin: var(--space-2-5) 0;
}

.ssm-stage-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-0-1875) var(--space-2-5);
  border-radius: var(--radius-pill);
  background: var(--color-error);
  color: var(--color-white);
  font-family: var(--ohf-body);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  white-space: nowrap;
  flex-shrink: 0;
  letter-spacing: var(--letter-spacing-wide);
}

.ssm-stage-error-msg {
  display: flex;
  gap: var(--space-sm);
  font-family: var(--ohf-body);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  line-height: var(--line-height-relaxed);
  margin: 0;
  align-items: flex-start;
}

.ssm-stage-error-icon {
  flex-shrink: 0;
  color: var(--color-error);
  margin-top: var(--space-px);
}

/* ── Reduced motion: render everything in its final state, instantly ── */
@media (prefers-reduced-motion: reduce) {
  .ssm-backdrop,
  .ssm-dialog,
  .ssm-stage-item,
  .ssm-stage-icon,
  .ssm-stage-line,
  .ssm-stage-icon--pending svg {
    animation: none;
  }

  .ssm-draw-stroke {
    animation: none;
    stroke-dashoffset: 0;
  }
}
/*
 * Typography source of truth for the Optimization Home feature (landing
 * page, its start-optimisation stub, the OptimizationCard, and the Recent
 * Optimizations modal) — imported by each of their own CSS files.
 *
 * Values pulled from Figma file UhXM9FKphZVFcmOL5CeMpr, node 28:2535.
 * Declared on :root rather than a class because these two custom
 * properties are only ever referenced by this feature's own selectors —
 * nothing else in the app uses an --ohf-* prefixed name.
 *
 * ── rem in this feature is figma_px / 18, NOT figma_px / 16 ──
 *
 * The app scales the root font with viewport width (src/utils/viewportScale.ts):
 *
 *     root_px = 16 * min(viewport / 1280, 1.25)   // for viewport >= 1280
 *
 * so 1rem is 16px only at <=1280 — it is 18px at 1440 and 20px at >=1600.
 * This feature's Figma frames are 1440 wide, where the root is 18px. Every
 * rem literal across the optimiser CSS is therefore authored as figma_px/18,
 * which lands exactly on Figma at a 1440 viewport and scales proportionally
 * at every other width. The trailing "13px"-style comments throughout mean
 * "13px at a 1440 viewport".
 *
 * Dividing by 16 instead (the intuitive default, and how this feature was
 * first written) renders everything 1.125x too large at 1440 and 1.25x at
 * 1600+ — which reads as "cards look fat / too much white space", the exact
 * symptom that got misdiagnosed as a type-scale problem for several rounds.
 *
 * Shared, app-wide tokens (var(--space-*), var(--radius-*)) are deliberately
 * NOT rebased: they size the unconverted shared chrome, so they must keep
 * tracking it. .sc-page's `padding-top: var(--space-10)` clears the real
 * Navbar precisely because both scale together.
 */
:root {
  --ohf-heading: "Fraunces", serif;
  --ohf-body: "Manrope", sans-serif;
  /* Used by exactly one node across the whole feature — the "Your Scenario"
     heading on the "Scope setup" screen (Figma node 418:26737). */
  --ohf-display: "DM Serif Display", serif;
  /* Target spend amount + mono-styled labels on the "Scope setup" screen.
     Not the app's shared --font-family-mono (Menlo) — see the @font-face
     comment in optimisationHomeFonts.css. */
  --ohf-mono: "IBM Plex Mono", monospace;

  /* Default type scale: 1 = exactly the Figma pixel values. Screens that opt
     into a deviation override this on their own root (see .ss-page). Declared
     here so a `calc(<size> * var(--ohf-text-scale))` can never resolve against
     an undefined variable — that would make the whole declaration invalid and
     silently drop the font-size. */
  --ohf-text-scale: 1;
}
/* Palette scoped to the card (values from Figma). Local so it renders the same
   on the optimiser home screen and inside the "View all" modal, and touches
   nothing else in the app. */
.oc-card {
  --oc-bg: #fdfdfd;
  --oc-border: #e1e5eb;
  --oc-title: #171f30;
  --oc-desc: #505869;
  --oc-chip-bg: #eff2f7;
  --oc-chip-border: #d6dbe4;
  --oc-chip-label: #838996;
  --oc-chip-value: #505869;
  --oc-btn-text: #0a1a40;
  --oc-btn-border: #b1b8c5;
  /* One height shared by both action controls, so the square "⋯" button and
     the "View Results"/"View Portfolio" button always line up: the primary
     button's own box math — line box (font-size x line-height) + vertical
     padding + both 1px borders (box-sizing is border-box app-wide). */
  --oc-action-h: calc(
    0.69444rem * var(--ohf-text-scale) * 1.366 + 2 * var(--space-xs) + 2 *
      var(--space-px)
  );
  /* status + type badges */
  --oc-single-bg: rgba(19, 96, 190, 0.2);
  --oc-single-text: #023087;
  --oc-portfolio-bg: #fcebcc;
  --oc-portfolio-text: #9f6700;
  --oc-completed-bg: #ebf4e0;
  --oc-completed-text: #0b774f;
  --oc-progress-bg: #f4f3e0;
  --oc-progress-text: #817800;
  --oc-failed-bg: #fce4e4;
  --oc-failed-text: #b42318;
  --oc-queued-bg: #e7ecfb;
  --oc-queued-text: #3a4f9e;
  /* "Scope and Constraints Summary" — same colours ImportScenarioCard's own
     `.ism-summary-title`/`.ism-summary-meta` use, so the two mirror the same
     summary block's look wherever it appears. */
  --oc-summary-title: #222222;
  --oc-summary-meta: #6a7693;
  /* "Show more"/"Show less" toggle — same colour ImportScenarioCard's own
     `.ism-toggle` uses (`--ism-toggle-text`), so both summary blocks read
     as one system. */
  --oc-toggle-text: #0068d3;
  /* KPI tiles — same colours ImportScenarioCard's own `.ism-kpi-*` vars use. */
  --oc-kpi-border: rgba(0, 0, 0, 0.1);
  --oc-kpi-label: #6a7693;
  --oc-kpi-value: #001f82;
  --oc-kpi-up: #0fa870;
  --oc-kpi-down: var(--color-danger);
  --oc-kpi-flat: #8b8b8b;

  background: var(--oc-bg);
  border: 1px solid var(--oc-border);
  border-radius: 0.66667rem;
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  min-width: 0;
}

.oc-card--compact {
  padding: var(--space-md);
  gap: var(--space-xs);
  /* The aggregate Portfolio card (`isPortfolioAggregate`) omits the
     description paragraph and several chips (see `hideRunSpecificDetails`),
     so it renders noticeably shorter than a Single Cell card sitting right
     next to it in the same "Recent Optimisations" list — this floors every
     compact card to the height a full Single Cell card actually needs
     (measured: title/badges row + one clamped description line + one chips
     row + this variant's own padding), so the list reads as one uniform
     grid of cards regardless of how much content any single card has. */
  min-height: 6.35rem;
}

/* Modal node (136:15803) shows a white card fill, distinct from the compact
   landing-page card's #fdfdfd (node 490:44517) — scoped to the full variant
   only so the landing page isn't regressed. */
.oc-card--full {
  --oc-bg: #ffffff;
}

/* ── Top row: title + badges (left), actions (right) ── */
.oc-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  min-width: 0;
}

.oc-title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-sm);
  min-width: 0;
}

/* Figma distinguishes the card title's weight/size between the compact
   (home page recent list) and full (inside the "View all" modal) contexts;
   base rule below matches the full variant, compact overrides to match. */
.oc-title {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.80556rem * var(--ohf-text-scale));
  font-weight: 700;
  color: var(--oc-title);
  line-height: 1.366;
  min-width: 0;
  overflow-wrap: break-word;
}

.oc-card--compact .oc-title {
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 600;
}

/* ── Badges (Inter, matches Figma — not switched to Manrope) ── */
.oc-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.13333rem var(--space-sm);
  border-radius: var(--radius-pill);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: var(--font-weight-medium);
  /* 18.75px / 12px — without this the badge inherits the page line-height and
     its box comes out a different height than Figma's. */
  line-height: 1.562;
  white-space: nowrap;
}

.oc-badge--kind-single_cell {
  background: var(--oc-single-bg);
  color: var(--oc-single-text);
}

.oc-badge--kind-portfolio {
  background: var(--oc-portfolio-bg);
  color: var(--oc-portfolio-text);
}

.oc-badge--status-completed,
.oc-badge--status-successful {
  background: var(--oc-completed-bg);
  color: var(--oc-completed-text);
}

.oc-badge--status-in_progress {
  background: var(--oc-progress-bg);
  color: var(--oc-progress-text);
}

.oc-badge--status-failed {
  background: var(--oc-failed-bg);
  color: var(--oc-failed-text);
}

.oc-badge--status-queued {
  background: var(--oc-queued-bg);
  color: var(--oc-queued-text);
}

/* Status badge rendered as a <button> when the backend returns a stage
   pipeline (`card.statusDetail.infoModalForm`) — reset the button chrome so
   it stays visually identical to the plain <span> badge, plus a pointer +
   hover affordance so it reads as clickable (see ScenarioStatusModal). */
.oc-badge--clickable {
  border: none;
  font-family: inherit;
  cursor: pointer;
  transition:
    filter var(--motion-duration-fast) var(--motion-easing-standard),
    transform var(--motion-duration-fast) var(--motion-easing-spring),
    box-shadow var(--motion-duration-fast) var(--motion-easing-standard);
}

.oc-badge--clickable:hover,
.oc-badge--clickable:focus-visible {
  filter: brightness(0.96);
  transform: translateY(calc(-1 * var(--space-px)));
  box-shadow: 0 var(--space-0-1875) var(--space-sm) var(--color-shadow-card-lg);
}

.oc-badge--clickable:active {
  transform: translateY(0) scale(0.97);
  box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .oc-badge--clickable,
  .oc-badge--clickable:hover,
  .oc-badge--clickable:active {
    transition: none;
    transform: none;
  }
}

/* ── Actions ── */
.oc-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-shrink: 0;
}

/* "View Results"/"View Portfolio" and "Import" (see `showImportAction`)
   share the exact same outline-button look. */
.oc-results-btn,
.oc-import-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--oc-action-h);
  border: 1px solid var(--oc-btn-border);
  background: var(--color-white);
  color: var(--oc-btn-text);
  font-family: var(--ohf-body);
  font-size: calc(0.69444rem * var(--ohf-text-scale));
  font-weight: var(--font-weight-semibold);
  line-height: 1.366;
  padding: 0 var(--space-md);
  border-radius: 0.33333rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--motion-duration-fast)
    var(--motion-easing-standard);
}

.oc-results-btn:hover,
.oc-import-btn:hover:not(:disabled) {
  background: var(--color-bg-hover-light);
}

.oc-import-btn:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.oc-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Square, and exactly as tall as the button beside it — see `--oc-action-h`. */
  width: var(--oc-action-h);
  height: var(--oc-action-h);
  border: 1px solid var(--oc-btn-border);
  background: var(--color-white);
  color: #1c1b1f;
  border-radius: 0.38889rem;
  cursor: pointer;
  transition: background var(--motion-duration-fast)
    var(--motion-easing-standard);
}

.oc-menu-btn:hover {
  background: var(--color-bg-hover-light);
}

.oc-menu-btn:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.oc-menu-btn:disabled:hover {
  background: var(--color-white);
}

.oc-menu-icon {
  width: 0.77778rem;
  height: 0.22222rem;
  display: block;
}

/* ── "⋯" actions menu (Figma node 136:16132) ── */
.oc-menu-wrap {
  display: inline-flex;
}

.oc-menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 9998;
}

/* Rendered in a body portal (see OptimizationCard.tsx) and positioned from the
   button's viewport rect, so it can never be clipped by the card, the recent-
   optimisations list, or a modal's own scroll container — and flips above the
   button when there isn't room below. `top`/`left` come from the component. */
.oc-menu-popover {
  position: fixed;
  z-index: 9999;
  width: 10.55556rem; /* 190px */
  background: var(--color-white);
  /* Global tokens only in here — the portal renders outside `.oc-card`, so its
     card-scoped `--oc-*` palette does not resolve. */
  border: var(--space-px) solid var(--color-dropdown-panel-border);
  border-radius: 0.66667rem; /* 12px */
  box-shadow: 0 var(--space-sm) var(--space-xl) var(--color-shadow-popover);
  padding: var(--space-1-5); /* 6px — the items carry the rest of the inset */
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
}

.oc-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: 1.77778rem; /* 32px */
  padding: var(--space-1-4) var(--space-sm);
  border: none;
  background: transparent;
  border-radius: 0.44444rem; /* 8px */
  color: #151f31;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale)); /* 13px */
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}

.oc-menu-item:hover {
  background: var(--color-bg-hover-light);
}

.oc-menu-item:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.oc-menu-item-icon {
  width: 0.72222rem; /* ~13px */
  height: 0.72222rem;
  flex-shrink: 0;
}

.oc-menu-item--danger {
  color: var(--color-danger, #d32f2f);
}

/* ── Description ── */
.oc-description {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  color: var(--oc-desc);
  line-height: 1.5;
  overflow-wrap: break-word;
}

.oc-card--compact .oc-description {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Meta chips ── */
.oc-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-xs);
}

/* Pins the chip row to the BOTTOM of a compact card instead of the top —
   the aggregate Portfolio card (fewer chips, no description, see
   `hideRunSpecificDetails`) is the one this actually moves: with `.oc-card
   --compact`'s own `min-height` (see that rule) making every card in the
   list the same height, top-aligned chips there left the leftover blank
   space stranded below the chip row, right up against the card's own
   bottom edge; a "user decision" auto margin instead sends that same
   leftover space to sit ABOVE the chip row, so its bottom edge lines up
   with every other card's. Harmless on a fuller card (Single Cell, or the
   "View all"/"View Portfolio" full-variant cards, both of which pack their
   own height exactly, no slack to consume): `margin-top: auto` only ever
   pushes into space that already exists. */
.oc-card--compact .oc-chips {
  margin-top: auto;
}

/* ── KPI tiles (Total Spend/Incremental Sales/ROI/MROI) — shown above the
   summary once expanded (Figma node 2351:119107), same 4-tile look
   ImportScenarioCard's own `.ism-kpi-*` classes use. Present only on
   ViewPortfolioModal's own cards with results — see the `kpis` state's own
   doc comment above. ── */
.oc-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.66667rem;
  margin-bottom: 0.88889rem;
}

.oc-kpis-state {
  min-height: 5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.88889rem;
}

.oc-kpi-tile {
  min-width: 0;
  height: 5rem;
  background: transparent;
  border: 1px solid var(--oc-kpi-border);
  border-radius: 0.66667rem;
  padding: 0.55556rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.oc-kpi-label {
  font-family: var(--ohf-body);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 500;
  color: var(--oc-kpi-label);
}

.oc-kpi-value {
  font-family: var(--ohf-body);
  font-size: calc(1rem * var(--ohf-text-scale));
  font-weight: 600;
  color: var(--oc-kpi-value);
}

.oc-kpi-trend {
  display: flex;
  align-items: center;
  gap: 0.22222rem;
}

.oc-kpi-trend-icon {
  width: 0.73889rem;
  height: 0.48333rem;
  flex-shrink: 0;
}

.oc-kpi-trend-delta {
  font-family: var(--ohf-body);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
}

.oc-kpi-trend--up .oc-kpi-trend-icon,
.oc-kpi-trend--up .oc-kpi-trend-delta {
  color: var(--oc-kpi-up);
}

/* Icon is authored pointing up; flip it for "down" rather than shipping a
   second glyph — same convention as ImportScenarioCard's own
   `.ism-kpi-trend--down`. */
.oc-kpi-trend--down .oc-kpi-trend-icon {
  transform: scaleY(-1);
}

.oc-kpi-trend--down .oc-kpi-trend-icon,
.oc-kpi-trend--down .oc-kpi-trend-delta {
  color: var(--oc-kpi-down);
}

.oc-kpi-trend--flat .oc-kpi-trend-icon,
.oc-kpi-trend--flat .oc-kpi-trend-delta {
  color: var(--oc-kpi-flat);
}

/* ── "Scope and Constraints Summary" — real, computed detail line; present
   only on ViewPortfolioModal's own cards, see `ScenarioCard["constraints
   Summary"]`'s doc comment. Same title/meta styling as ImportScenarioCard's
   `.ism-summary`/`.ism-summary-meta`, laid out inline here (a single
   pre-joined string, not the Import card's separate title/version/detail
   spans). Gated behind the "Show more"/"Show less" toggle (`summaryExpanded`
   state) above the KPI tiles. ── */
.oc-constraints-summary {
  display: flex;
  flex-direction: column;
  gap: 0.33333rem;
}

.oc-constraints-summary-title {
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 500;
  color: var(--oc-summary-title);
}

.oc-constraints-summary-detail {
  font-family: var(--ohf-body);
  font-size: calc(0.69444rem * var(--ohf-text-scale));
  font-weight: 500;
  color: var(--oc-summary-meta);
}

/* Relocates: right below `.oc-chips` while collapsed, or as the last child
   of `.oc-constraints-summary` once expanded — same pattern
   ImportScenarioCard's own `.ism-toggle` uses. */
.oc-summary-toggle {
  display: inline-flex;
  align-items: center;
  align-self: flex-end;
  gap: 0.27778rem;
  border: none;
  background: transparent;
  padding: 0;
  margin: 0;
  color: var(--oc-toggle-text);
  font-family: var(--ohf-body);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 500;
  cursor: pointer;
}

.oc-summary-toggle-icon {
  width: 0.55556rem;
  height: 0.33333rem;
  color: var(--oc-toggle-text);
  transition: transform var(--motion-duration-fast) var(--motion-easing-standard);
}

.oc-summary-toggle-icon--open {
  transform: rotate(180deg);
}

.oc-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.22222rem;
  padding: 0.17778rem var(--space-sm);
  border: 1px solid var(--oc-chip-border);
  border-radius: 0.33333rem;
  background: var(--oc-chip-bg);
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  line-height: 1.366;
  white-space: nowrap;
}

/* The scope chip carries a hover tooltip listing every combination the
   scenario spans (see `scopeCellsTooltip`) — `default` matches KpiCard's own
   hoverable value/label (`.kpi-value`), which doesn't change the cursor either. */
.oc-chip--detailed {
  cursor: default;
}

/* Matches KpiCard's own `.kpi-value-tooltip` — same fixed/portalled
   positioning, same tooltip skin tokens — but `pre-line` (not `nowrap`) since
   `scopeCellsTooltip` joins multiple scope combinations with "\n", and a
   `max-width` since that list can run long. */
.oc-chip-tooltip {
  position: fixed;
  max-width: 15rem;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  white-space: pre-line;
  pointer-events: none;
  z-index: 9999;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  line-height: 1.5;
}

/* Arrow sits a fixed inset from the LEFT edge (matches InfoButton's own
   default `.ib-tooltip::before`) rather than centred — the tooltip's `left`
   is set to the chip's own left edge (see `OptimizationCard.tsx`), so a
   centred arrow drifted away from the chip once the box grew wider than it
   to fit the scope list. */
.oc-chip-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5));
  left: var(--space-2-5);
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* Flipped up when there isn't room below the chip to the viewport's bottom
   edge (see the chip's `onMouseEnter`, which measures against the hidden
   twin) — same flip KpiCard's own `.kpi-value-tooltip--above` does. */
.oc-chip-tooltip--above::before {
  top: auto;
  bottom: calc(-1 * var(--space-1-5));
  border-bottom: none;
  border-top: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* Flipped to a side when the tooltip is too tall to fit above OR below the
   chip (e.g. a scope chip listing 20+ combinations) — see the chip's
   `onMouseEnter`, which also sets `--tooltip-arrow-top` so the arrow tracks
   the chip's own vertical center rather than a fixed corner, since the box
   itself is vertically centered on the chip (then clamped to the viewport). */
.oc-chip-tooltip--right::before,
.oc-chip-tooltip--left::before {
  top: var(--tooltip-arrow-top);
  left: auto;
  border-top: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid transparent;
}

.oc-chip-tooltip--right::before {
  left: calc(-1 * var(--space-1-5));
  border-right: var(--space-1-5) solid var(--color-tooltip-bg);
  border-left: none;
}

.oc-chip-tooltip--left::before {
  right: calc(-1 * var(--space-1-5));
  border-left: var(--space-1-5) solid var(--color-tooltip-bg);
  border-right: none;
}

.oc-chip-tooltip-scroll {
  overflow-y: auto;
}

.oc-chip-label {
  color: var(--oc-chip-label);
}

/* Bold so a chip's value stands out from its (regular-weight) label at a
   glance — a label-less chip (e.g. "Public", "Created 2 hours ago") is all
   value, so it bolds too. */
.oc-chip-value {
  color: var(--oc-chip-value);
  font-weight: var(--font-weight-semibold);
}

/* Scope chips carry brand / market / region / sub-brand, all lowercase in the
   source data — see pages/StartOptimisation/ScopeFieldSelect.css. */
.oc-chip {
  text-transform: capitalize;
}
.msd-wrap {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  border: var(--space-px) solid var(--color-kpigrey);
  border-radius: var(--radius-input);
  width: fit-content;
}

.msd-label {
  position: absolute;
  top: calc(var(--space-px) * -6);
  left: var(--space-sm);
  font-size: calc(var(--font-size-2xs) * var(--ohf-text-scale));
  color: var(--color-text-muted);
  background: var(--color-white);
  padding: 0 var(--space-0-8);
  white-space: nowrap;
  pointer-events: none;
}

/* ── Trigger button ──────────────────────────────────────── */
.msd-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  background: transparent;
  border: none;
  cursor: pointer;
  padding: var(--space-xs) var(--space-sm);
  font-size: calc(var(--font-size-sm) * var(--ohf-text-scale));
  font-family: var(--font-family-display);
  color: var(--color-black);
  min-width: var(--space-8);
  width: 100%;
  /* Padding must eat into the trigger's own box, not add to it — otherwise
     the chevron can get pushed past the wrap's right edge. */
  box-sizing: border-box;
  text-align: left;
}

/* Two nodes, not one string: the names truncate, the "+(n)" counter never
   does — see the comment on TRIGGER_VALUE_COUNT in MultiSelectDropdown.tsx. */
.msd-value {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  /* Guards the chevron: a long value truncates instead of growing the
     trigger and shoving the fixed-size chevron box out of view. */
  min-width: 0;
  white-space: nowrap;
}

.msd-value-names {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  /* Matches .msd-option-label — the trigger shows selected options verbatim
     ("indonesia", or "indonesia, uk"), so it has to read the same way the rows
     the user ticked did. No-op on the "All"/"Select" placeholder. */
  text-transform: capitalize;
}

/* Held out of the ellipsis above (no shrink): how many more are selected is
   the one part of the label that must never be the bit that gets cut. */
.msd-value-more {
  flex: 0 0 auto;
  /* Colour is inherited on purpose — each call site scopes .msd-value's own
     colour (see .ism-select/.rom-select), and the counter must not drift from
     the names it belongs to. */
  font-variant-numeric: tabular-nums;
}

.msd-value--placeholder {
  color: var(--color-text-muted);
}

/* Fixed-size box (not just the icon) is what actually guarantees
   containment — even if the icon's own intrinsic size were somehow wrong,
   this box clips it via overflow:hidden. */
.msd-chevron {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-lg); /* 16px */
  height: var(--space-lg); /* 16px */
  color: var(--color-dropdown-chevron);
  opacity: 0.6;
  transition: transform var(--motion-duration-fast) ease;
  flex-shrink: 0;
  overflow: hidden;
}

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

.msd-chevron-icon {
  display: block;
  width: 100%;
  height: 100%;
  flex-shrink: 0;
}

/* ── Dropdown panel ──────────────────────────────────────────
   The floating surface. It owns the positioning/border/shadow that used to sit
   on .msd-list, so the Apply/Cancel row can live below the scrolling options
   rather than scrolling away with them. */
.msd-panel {
  position: absolute;
  top: calc(100% + var(--space-0-5));
  left: calc(var(--space-px) * -1);
  right: calc(var(--space-px) * -1);
  background: var(--color-white);
  border: var(--space-px) solid var(--color-dropdown-panel-border);
  border-radius: var(--radius-md); /* 8px — crisp menu corner */
  padding: var(--space-xs); /* 4px inset so rows nearly fill the panel */
  z-index: 300;
  overflow: hidden;
  /* Soft, elevated "popover" shadow so it reads as floating above the page. */
  box-shadow: 0 var(--space-sm) var(--space-xl) var(--color-shadow-popover);
  min-width: 100%;
  width: max-content;
}

/* ── Search box (searchable panels) ───────────────────────────
   A proper ~34px field pinned at the top of the panel; the select-all + option
   rows scroll beneath it. Matches SelectDropdown's .sd-search exactly. */
.msd-search {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-height: 1.88889rem; /* ~34px */
  padding: 0 var(--space-sm);
  margin-bottom: var(--space-xs);
  background: var(--color-dropdown-hover);
  border: var(--space-px) solid var(--color-dropdown-panel-border);
  border-radius: var(--radius-input); /* 6px */
}

.msd-search-icon {
  width: 0.77778rem; /* ~14px */
  height: 0.77778rem;
  color: var(--color-dropdown-chevron);
  flex-shrink: 0;
}

.msd-search-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: "Manrope", var(--font-family-base);
  font-size: var(--font-size-base);
  color: var(--color-dropdown-option-text);
}

.msd-search-input::placeholder {
  color: var(--color-text-muted);
}

/* ── Select-all control ──────────────────────────────────────
   A lightweight first row (checkbox + "Select all" + count), aligned with the
   option rows below it and set off by a single soft hairline — not a heavy
   tinted uppercase block. The negative side margins + compensating padding
   bleed the hairline to the panel's inner edges while keeping the label
   aligned with the option labels. */
.msd-selectall {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-height: 2rem; /* 32px, matches option rows */
  padding: var(--space-0-6) calc(var(--space-sm) + var(--space-xs)); /* aligns label with options */
  margin: calc(var(--space-xs) * -1) calc(var(--space-xs) * -1) var(--space-xs);
  border-bottom: var(--space-px) solid var(--color-dropdown-panel-border);
  cursor: pointer;
  user-select: none;
  transition: background var(--motion-duration-fast) ease;
}

.msd-selectall:hover,
.msd-selectall:focus-visible {
  background: var(--color-dropdown-hover);
  outline: none;
}

.msd-selectall-label {
  font-family: "Manrope", var(--font-family-base);
  font-weight: var(--font-weight-semibold);
  font-size: var(--font-size-base); /* ~13px */
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-dropdown-option-text);
  flex: 1;
}

/* Makes "how much of this filter is active" legible at a glance. */
.msd-selectall-count {
  font-size: calc(0.66667rem * var(--ohf-text-scale, 1)); /* ~12px */
  font-family: var(--font-family-base);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}

/* ── Dropdown list ───────────────────────────────────────── */
.msd-list {
  list-style: none;
  margin: 0;
  padding: var(--space-0-5) 0;
}

/* The option list scrolls in a `DropdownScrollList` (native scroll + contained
   overscroll). Its default thumb is the app-wide light blue; every screen this
   component appears on — the Import popup, the "View all" modal, the Compare
   screen — is a new-optimiser one, where scrollers are the low-chrome soft
   variant that `index.css` gives `.or-page`/`.cmp-page` and their tables. Kept
   here rather than in DropdownScrollList.css, which SelectDropdown shares with
   the legacy screens and their light-blue thumbs. */
.msd-panel .dsl-list {
  scrollbar-color: var(--color-scrollbar-thumb-soft) transparent;
}

.msd-panel .dsl-list::-webkit-scrollbar-thumb {
  background: var(--color-scrollbar-thumb-soft);
}

.msd-panel .dsl-list::-webkit-scrollbar-thumb:hover {
  background: var(--color-scrollbar-thumb-soft-hover);
}

/* ── Empty-selection message ─────────────────────────────────
   Sits between the option rows and the footer, so the eye travels
   rows → reason → greyed Apply in one pass. Right-aligned to sit over the
   Apply button it explains. It only ever renders when nothing is ticked, so
   it needs no reserved height — the panel is a floating surface and is free
   to grow by one line. */
.msd-error {
  margin: var(--space-xs) 0 0;
  padding: 0 calc(var(--space-sm) + var(--space-xs));
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale, 1)); /* ~12px */
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-snug);
  text-align: right;
  color: var(--color-error);
}

/* ── Apply / Cancel ──────────────────────────────────────────
   Pinned under the option list: edits are staged until Apply, so the commit
   control must stay reachable no matter how far the list is scrolled.
   Negative margins bleed it back out to the panel's edges (mirrors
   .msd-selectall above) now that the panel carries its own 8px padding. */
.msd-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-sm) calc(var(--space-sm) + var(--space-xs)) var(--space-xs);
  margin: var(--space-xs) calc(var(--space-xs) * -1) 0;
  border-top: var(--space-px) solid var(--color-dropdown-panel-border);
}

/* Equal-height (~30px) buttons with real vertical presence — the previous
   ~2px vertical padding made them read as squished. Height comes from
   min-height + centered content, not padding, so both buttons match exactly. */
.msd-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 1.72222rem; /* ~31px */
  padding: 0 var(--space-md); /* 0 / 12px */
  border-radius: var(--radius-input); /* 6px */
  font-family: var(--font-family-base);
  font-size: var(--font-size-base); /* ~13px */
  font-weight: var(--font-weight-semibold);
  line-height: 1;
  cursor: pointer;
  transition: background var(--motion-duration-fast) ease, opacity var(--motion-duration-fast) ease,
    border-color var(--motion-duration-fast) ease;
}

.msd-action--cancel {
  border: var(--space-px) solid var(--color-checkbox-border);
  background: var(--color-white);
  color: var(--color-dropdown-option-text);
}

.msd-action--cancel:hover {
  background: var(--color-dropdown-hover);
}

.msd-action--apply {
  border: var(--space-px) solid var(--color-checkbox-navy);
  background: var(--color-checkbox-navy);
  color: var(--color-white);
}

.msd-action--apply:hover:not(:disabled) {
  opacity: 0.9;
}

/* A disabled Apply drops the navy entirely rather than fading it: a washed-out
   navy still reads as "primary action, try harder", whereas a flat grey chip
   reads as unavailable at a glance. Pairs with the `.msd-error` message above
   it, which supplies the reason. */
.msd-action--apply:disabled {
  background: var(--color-dropdown-hover);
  border-color: var(--color-dropdown-panel-border);
  color: var(--color-text-muted);
  cursor: not-allowed;
}

/* Padded, rounded rows rather than the plain low-padding rows before —
   hover/active highlight is what separates rows now. A compact row (8px
   vertical padding, normal line-height) reads as a light, modern menu item
   rather than a thick block; font-family falls back to the app's base font
   where "Manrope" isn't loaded (it's only self-hosted for the new-optimizer
   pages), same pattern as --ohf-body. */
.msd-option {
  display: flex;
  align-items: center;
  gap: var(--space-sm); /* 8px */
  min-height: 2rem; /* 32px compact row */
  padding: var(--space-0-6) var(--space-sm); /* ~2.4px / 8px */
  border-radius: var(--radius-input); /* 6px */
  font-family: "Manrope", var(--font-family-base);
  font-weight: var(--font-weight-medium);
  font-size: var(--font-size-base); /* ~13px */
  line-height: var(--line-height-snug);
  color: var(--color-dropdown-option-text);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--motion-duration-fast) ease;
}

.msd-option:hover {
  background: var(--color-dropdown-hover);
}

/* Checked rows are NOT tinted — the checkbox is the sole selection cue. Tinting
   every checked row turned a mostly-selected list into one solid highlighted
   block (cluttered). Only hover tints a row now. */

/* A compact 18px box with a single consistent corner radius (rather than a
   heavier 20px box with a mismatched checked/unchecked radius) reads as a
   crisp, modern checkbox instead of a thick tile. */
.msd-checkbox {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-4-5); /* 18px */
  height: var(--space-4-5); /* 18px */
  border: var(--space-px) solid var(--color-checkbox-border);
  border-radius: 0.25rem; /* 4px */
  background: var(--color-white);
  flex-shrink: 0;
  transition: background var(--motion-duration-fast) ease, border-color var(--motion-duration-fast) ease;
}

.msd-checkbox--checked {
  background: var(--color-checkbox-navy);
  border-color: var(--color-checkbox-navy);
}

/* Partial selection uses the same navy fill; the glyph (dash vs tick) is what
   distinguishes "some" from "all". */
.msd-checkbox--indeterminate {
  background: var(--color-checkbox-navy);
  border-color: var(--color-checkbox-navy);
}

/* White SVG tick — crisper and better centred than a CSS border-checkmark
   (which needed a translate nudge and read as thin/off). */
.msd-check {
  width: 0.72222rem; /* ~13px inside the 18px box */
  height: 0.72222rem;
  color: var(--color-white);
}

/* Indeterminate: a centred white dash, so "some" is distinguishable from both
   "all" (tick) and "none" (empty) at a glance. */
.msd-dash {
  width: 0.5rem; /* 9px */
  height: 0.11111rem; /* 2px */
  border-radius: var(--space-px);
  background: var(--color-white);
}

/* ── Radio (single-select panels) ────────────────────────────
   Same 18px footprint, alignment and navy as .msd-checkbox — a single-select
   panel sitting beside a multi-select one must differ ONLY in the glyph, so
   the two fields read as the same control with different arity. Round + a
   centred dot is the whole difference. */
.msd-radio {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-4-5); /* 18px */
  height: var(--space-4-5); /* 18px */
  border: var(--space-px) solid var(--color-checkbox-border);
  border-radius: 50%;
  background: var(--color-white);
  flex-shrink: 0;
  transition: border-color var(--motion-duration-fast) ease;
}

/* The ring goes navy and a navy dot fills the middle — deliberately NOT a
   solid navy disc with a white dot, which would read as a checkbox that had
   lost its corners. */
.msd-radio--checked {
  border-color: var(--color-checkbox-navy);
}

.msd-radio-dot {
  width: 0.55556rem; /* 10px inside the 18px ring */
  height: 0.55556rem;
  border-radius: 50%;
  background: var(--color-checkbox-navy);
}

.msd-option-label {
  overflow: hidden;
  text-overflow: ellipsis;
  /* Dimension values arrive lowercase from `dim_*.display_label` ("indonesia",
     "north india"). Same CSS capitalisation the scope chips and every other
     surface that renders these values already uses — see `capitaliseWords()`
     for the JS equivalent used on this component's title/aria strings, which
     CSS can't reach. */
  text-transform: capitalize;
}

.msd-empty {
  padding: var(--space-xs) var(--space-sm);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  color: var(--color-text-muted);
  text-align: center;
}

/* ── Verbatim labels (`capitaliseLabels={false}`) ─────────────
   Turns off the title-casing that dimension values want. Applied to the wrap,
   which covers both the rows and the trigger's value — a scenario NAME must
   read the same in the field as in the row the user ticked, and both must
   match what its author typed. The JS `capitaliseWords()` on the title/aria
   strings is skipped by the same prop, so no surface disagrees. */
.msd-wrap--verbatim .msd-option-label,
.msd-wrap--verbatim .msd-value-names {
  text-transform: none;
}

.msd-trigger:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
/* The × inside a search field. Absolutely positioned against the caller's own
   search wrapper (which is `position: relative` — see the component's doc
   comment), mirroring the magnifier those wrappers already place on the left. */
.search-clear {
  position: absolute;
  right: 0.44444rem;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.11111rem;
  height: 1.11111rem;
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: transparent;
  color: #838996;
  cursor: pointer;
  transition: background var(--motion-duration-fast) var(--motion-easing-standard),
    color var(--motion-duration-fast) var(--motion-easing-standard);
}

.search-clear:hover {
  background: var(--color-bg-hover-light);
  color: var(--color-text-body);
}

.search-clear:focus-visible {
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 1px;
}

.search-clear-icon {
  width: 0.5rem;
  height: 0.5rem;
}

@media (prefers-reduced-motion: reduce) {
  .search-clear {
    transition: none;
  }
}
/* NOTE: the header band, filters row and list chrome below (.rom-backdrop
   through .rom-select/.rom-search) are duplicated in
   ImportScenarioModal.css (.ism-*) — the "Import" modal shares this same
   shell but is a deliberately standalone component. Keep the two in sync;
   see the note at the top of that file. */
.rom-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--color-backdrop-overlay);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-xl) var(--space-lg);
  overflow-y: auto;
}

/* Values pulled directly from Figma node 136:15803 (the verified-correct
   "View all" modal frame). The dialog itself is a light grey-blue (#f6f6f9);
   the header and status-pill rows are separate white bands with a hairline
   bottom divider — not one flat white sheet like the rest of the app's
   modals — so this scoped palette intentionally diverges from
   --color-bg-card/--color-primary. */
.rom-dialog {
  /* Declared here as well as on .oh-page, not inherited from it: this dialog is
     portalled to document.body, so it is NOT a descendant of the page root and
     would otherwise fall back to the :root default of 1 and render a size
     larger than the screen that opened it. */
  --ohf-text-scale: 1;

  --rom-heading: #171f30;
  --rom-band-border: #cfd4df;
  --rom-pill-text: #677694;
  --rom-pill-border: rgba(0, 0, 0, 0.08);
  --rom-pill-active-bg: rgba(0, 84, 216, 0.06);
  --rom-search-placeholder: #757575;
  --rom-surface: #f6f6f9;

  background: #f6f6f9;
  border-radius: 0.88889rem;
  overflow: hidden;
  box-shadow: 0 12px 40px var(--color-shadow-modal-lg);
  width: min(65.44444rem, 100%);
  margin: auto;
  display: flex;
  flex-direction: column;
  /* Fixed shell height, NOT content-driven — same rule as .ism-dialog/.vpm-dialog.
     Sizing to the content made the dialog resize under the user's cursor every
     time a status pill, a filter or the search term changed the result count
     (22 cards -> full height, 1 card -> roughly a third of it), and a short
     dialog then clipped an open filter panel against the `overflow: hidden`
     above. The list scrolls inside a stable shell instead; the vh term only
     kicks in on short viewports, where it is the same cap the old max-height
     applied. */
  height: min(43.33333rem, calc(100vh - 2 * var(--space-xl)));
}

/* ── Header ── */
.rom-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  background: var(--color-white);
  border-bottom: 1px solid var(--rom-band-border);
  padding: 1.33333rem 1.55556rem 0.94444rem;
}

.rom-title {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(1.11111rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.366;
  color: var(--rom-heading);
}

.rom-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Figma: a 24x24 hit area around a 10x10 glyph. */
  width: 1.33333rem;
  height: 1.33333rem;
  border: none;
  background: transparent;
  /* Solid — the glyph carries Figma's 70% via fill-opacity. Setting the alpha
     here too multiplied the two (0.7 x 0.7 = 0.49) and washed the cross out. */
  color: #1c1b1f;
  border-radius: var(--radius-input);
  cursor: pointer;
}

.rom-close:hover {
  background: var(--color-bg-hover-light);
}

/* Figma's glyph is 10x10 (node 509:9473); this was rendering it at 20px. */
.rom-close-icon {
  width: 0.55556rem;
  height: 0.55556rem;
}

/* ── Status pills ── */
.rom-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.66667rem;
  background: var(--color-white);
  border-bottom: 1px solid var(--rom-band-border);
  padding: 0.80556rem 1.55556rem;
}

.rom-pill {
  border: 1px solid var(--rom-pill-border);
  background: var(--color-white);
  color: var(--rom-pill-text);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.567; /* 18.8px / 12px, per Figma */
  /* 6px/14px + the 1px border = Figma's 33px tall, 81px wide "Show All" pill. */
  padding: 0.33333rem 0.77778rem;
  border-radius: 0.88889rem;
  cursor: pointer;
  transition: all var(--motion-duration-fast) var(--motion-easing-standard);
}

.rom-pill:hover {
  background: var(--color-bg-hover-light);
}

.rom-pill--active {
  background: var(--rom-pill-active-bg);
  border-color: var(--rom-pill-border);
  color: var(--rom-pill-text);
}

/* ── Filters row ── */
/* The gap below this row has to live HERE, not as padding-top on .rom-list:
   that padding sits inside the scroll container and scrolls away with the
   content, so cards ended up clipping at the list's top edge with zero
   clearance and appeared to slide under the filters. Padding on this row is
   outside the scroller, so the clearance holds at every scroll position.
   (Figma's 14px assumes a static list; 20px here for the scrolling case.) */
.rom-filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.88889rem;
  padding: 0.66667rem 1.55556rem 1.11111rem;
  /* Opaque and above the list so scrolled cards can never bleed through, and
     so the dropdown panels still open over the results. */
  background: var(--rom-surface);
  position: relative;
  z-index: 2;
}

.rom-filter-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.88889rem;
}

.rom-select {
  flex: 0 0 7.88889rem;
  width: 7.88889rem;
}

/* Restyle this MultiSelectDropdown instance to match Figma's filter-dropdown
   look exactly: a plain label sitting in normal flow above the box (not the
   base component's notched label cutting through the border), and a box
   border on the trigger itself rather than on the whole wrapper — scoped to
   .rom-select so other MultiSelectDropdown usages elsewhere in the app are
   unaffected. */
.rom-select.msd-wrap {
  border: none;
  border-radius: 0;
  width: 100%;
  align-items: stretch;
}

.rom-select .msd-label {
  position: static;
  background: none;
  padding: 0;
  margin-bottom: 0.33333rem;
  font-family: var(--font-family-base);
  font-weight: 600;
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  line-height: 1.209; /* 13.3px / 11px, per Figma */
  color: #6b6e76;
}

.rom-select .msd-trigger {
  width: 100%;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 0.44444rem;
  background: var(--color-white);
  padding: 0.5rem;
}

.rom-select .msd-value {
  font-family: var(--font-family-base);
  font-weight: 500;
  font-size: calc(0.58333rem * var(--ohf-text-scale));
  line-height: 1.21; /* 12.7px / 10.5px, per Figma */
  color: #9a9ca2;
}

.rom-select .msd-value--placeholder {
  color: #9a9ca2;
}

.rom-select .msd-chevron {
  color: #9a9ca2;
}

.rom-select .msd-chevron-icon {
  width: 0.44444rem;
  height: 0.27778rem;
}

.rom-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 0 13.61111rem;
  margin-top: 0.88889rem;
}

.rom-search-icon {
  position: absolute;
  left: 0.61111rem;
  top: 50%;
  transform: translateY(-50%);
  width: 0.77778rem;
  height: 0.77778rem;
  color: #828a96;
  pointer-events: none;
}

.rom-search-input {
  width: 100%;
  height: 2.11111rem;
  /* Right padding clears the × (see SearchClearButton), which overlays this
     field's right edge. */
  padding: 0 1.83333rem 0 1.83333rem;
  border: 1px solid rgba(177, 184, 197, 0.4);
  border-radius: 0.44444rem;
  background: var(--color-white);
  color: var(--color-text-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  line-height: 1.369; /* 17.8px / 13px, per Figma */
  font-family: var(--ohf-body);
}

.rom-search-input::placeholder {
  color: var(--rom-search-placeholder);
}

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

/* ── Scenario list ── */
.rom-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* No padding-top: the clearance above comes from .rom-filters' padding-bottom
     so that it survives scrolling — see the note there. */
  padding: 0 1.55556rem 1.55556rem;
  transition: opacity var(--motion-duration-fast) var(--motion-easing-standard);
}

/* Refetch in progress: dim the still-valid results rather than replacing them.
   The 180ms delay is the whole point — a refetch that resolves faster than that
   (typing in search, flipping a status pill) finishes before the dim ever
   starts, so there is nothing to perceive. Slower ones fade in gently and the
   fade-out on removal is immediate (no delay on the base rule above). */
.rom-list--refreshing {
  opacity: 0.5;
  transition-delay: 180ms;
}

/* Reserves height for the loader/error states so the dialog doesn't collapse
   to spinner-height on first open and then spring out to full height. */
.rom-list-state {
  flex: 1;
  min-height: 14.22222rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

@media (prefers-reduced-motion: reduce) {
  .rom-list {
    transition: none;
  }
}

.rom-empty {
  text-align: center;
  color: var(--color-text-muted);
  font-size: calc(var(--font-size-sm) * var(--ohf-text-scale));
  padding: var(--space-xxl) 0;
  /* Top-aligned, horizontally centred: no vertical auto margin, so the message
     sits right under the filters rather than centred in the fixed-height list
     area. */
  margin: 0 auto;
}

/* ── Infinite scroll sentinel + inline loading row ──
   The sentinel is an in-flow marker at the end of the scrollable list
   (observed via IntersectionObserver rooted on .rom-list), not a pinned
   footer — it scrolls with the content and disappears once hasMore is
   false. */
.rom-sentinel {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: var(--space-xl);
  padding-top: var(--space-xs);
}

.rom-loading-more {
  color: var(--rom-pill-text);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
}

/* Persistent, silent status region — announces load-more results to screen
   readers without any visible layout footprint. */
.rom-live-region {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Keyboard/screen-reader fallback for infinite scroll: hidden off-screen by
   default (same sr-only technique as .rom-live-region), but becomes a
   normal visible, focusable button the moment it receives keyboard focus —
   unlike the live region, this one is interactive. */
.rom-load-more-fallback {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 1px solid var(--rom-pill-border);
  background: var(--color-white);
  color: var(--rom-pill-text);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
  border-radius: 0.88889rem;
  cursor: pointer;
}

.rom-load-more-fallback:focus {
  position: static;
  display: block;
  width: auto;
  height: auto;
  margin: var(--space-sm) auto 0;
  overflow: visible;
  clip: auto;
  white-space: normal;
  padding: 0.38889rem 1.11111rem;
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 2px;
}

.rom-load-more-fallback:disabled {
  cursor: not-allowed;
}
/* Values pulled from Figma node 968:40554. Same shell pattern as
   RecentOptimizationsModal.css's .rom-* (dialog bg #f6f6f9, white header band
   with a hairline bottom divider) — duplicated rather than shared, same
   "deliberately standalone component" convention noted at the top of that
   file. */
.vpm-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--color-backdrop-overlay);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-xl) var(--space-lg);
  overflow-y: auto;
}

.vpm-dialog {
  --ohf-text-scale: 1;

  /* Figma node 2358:121695 ("View portfolio" state) — the Run button's exact
     blue/cream aren't in the shared palette (see the same local-var pattern
     on .ism-card/.ism-dialog), so they get their own vars here rather than a
     hardcoded literal in the rule below. */
  --vpm-run-bg: rgba(0, 104, 211, 1); /* #0068d3 */
  --vpm-run-text: rgba(249, 245, 237, 1); /* #f9f5ed, NOT pure white */

  background: #f6f6f9;
  border-radius: 0.88889rem;
  overflow: hidden;
  box-shadow: 0 12px 40px var(--color-shadow-modal-lg);
  width: min(65.44444rem, 100%);
  margin: auto;
  display: flex;
  flex-direction: column;
  /* Fixed shell height, NOT content-driven — same rule as .rom-dialog/.ism-dialog.
     This dialog swaps a loader for a brand list of whatever length the portfolio
     has, so a content-sized shell jumped size on load and again between
     portfolios. The body scrolls inside a stable shell instead; the vh term only
     kicks in on short viewports, where it is the same cap the old max-height
     applied. */
  height: min(43.33333rem, calc(100vh - 2 * var(--space-xl)));
}

/* ── Header ── */
.vpm-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  background: var(--color-white);
  padding: 1.33333rem 1.55556rem;
}

/* Back arrow — only rendered when this popup replaced another one (see
   `onBack`). `margin-right: auto` on the title keeps the close button hard
   right whether or not this button is present. */
.vpm-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.33333rem;
  height: 1.33333rem;
  padding: 0;
  border: none;
  background: transparent;
  color: #838996; /* rgba(131,137,150,1) per Figma node 2358:121695 */
  border-radius: var(--radius-input);
  cursor: pointer;
  flex-shrink: 0;
}

.vpm-back:hover {
  background: var(--color-bg-hover-light);
  color: #171f30;
}

.vpm-back-icon {
  width: 0.88889rem;
  height: 0.88889rem;
}

.vpm-title {
  margin: 0;
  margin-right: auto;
  font-family: var(--ohf-body);
  font-size: calc(1.11111rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.366;
  color: #171f30;
}

.vpm-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.33333rem;
  height: 1.33333rem;
  border: none;
  background: transparent;
  color: #1c1b1f;
  border-radius: var(--radius-input);
  cursor: pointer;
}

.vpm-close:hover {
  background: var(--color-bg-hover-light);
}

.vpm-close-icon {
  width: 0.55556rem;
  height: 0.55556rem;
}

/* ── Meta row (scope summary · Created by · Created ago) ── */
.vpm-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.44444rem;
  background: var(--color-white);
  border-bottom: 1px solid #cfd4df;
  padding: 0.5rem 1.55556rem 0.83333rem;
  font-family: var(--ohf-body);
  font-size: 0.61111rem;
  color: #4f586a;
}

.vpm-meta-label {
  color: #838aa0;
}

/* Same pill skin as a scenario card's own first (scope) chip — see
   `.oc-chip` in OptimizationCard.css — so the portfolio-level brand summary
   reads as the same kind of value, not a differently-formatted plain string. */
.vpm-scope-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.17778rem var(--space-sm);
  border: 1px solid #d6dbe4;
  border-radius: 0.33333rem;
  background: #eff2f7;
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  line-height: 1.366;
  color: #505869;
  white-space: nowrap;
  /* Source data (dim_brand/dim_market.display_label) is lowercase — same
     `.oc-chip { text-transform: capitalize; }` rule OptimizationCard.css
     applies to its own scope chip. */
  text-transform: capitalize;
}

/* Hoverable, same as the scope chip's own `.oc-chip--detailed` — `default`
   cursor rather than a text-select `text-align` cursor, no visual change. */
.vpm-scope-chip--detailed {
  cursor: default;
}

/* Custom hover-detail box — same skin/positioning as `OptimizationCard`'s
   own `.oc-chip-tooltip` (see that file), duplicated per this component's
   own "standalone" convention noted at the top of this file. */
.vpm-scope-chip-tooltip {
  position: fixed;
  max-width: 15rem;
  background: var(--color-tooltip-bg);
  color: var(--color-tooltip-text);
  font-size: var(--font-size-xs);
  font-family: var(--font-family-base);
  font-weight: var(--font-weight-regular);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  white-space: pre-line;
  pointer-events: none;
  z-index: 9999;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-tooltip);
  line-height: 1.5;
}

.vpm-scope-chip-tooltip::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-1-5));
  left: var(--space-2-5);
  border-left: var(--space-1-5) solid transparent;
  border-right: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid var(--color-tooltip-bg);
}

.vpm-scope-chip-tooltip--above::before {
  top: auto;
  bottom: calc(-1 * var(--space-1-5));
  border-bottom: none;
  border-top: var(--space-1-5) solid var(--color-tooltip-bg);
}

/* Flipped to a side when the tooltip is too tall to fit above OR below the
   chip (e.g. a scope spanning 20+ combinations) — see the chip's
   `onMouseEnter`, which also sets `--tooltip-arrow-top` so the arrow tracks
   the chip's own vertical center rather than a fixed corner, since the box
   itself is vertically centered on the chip (then clamped to the viewport). */
.vpm-scope-chip-tooltip--right::before,
.vpm-scope-chip-tooltip--left::before {
  top: var(--tooltip-arrow-top);
  left: auto;
  border-top: var(--space-1-5) solid transparent;
  border-bottom: var(--space-1-5) solid transparent;
}

.vpm-scope-chip-tooltip--right::before {
  left: calc(-1 * var(--space-1-5));
  border-right: var(--space-1-5) solid var(--color-tooltip-bg);
  border-left: none;
}

.vpm-scope-chip-tooltip--left::before {
  right: calc(-1 * var(--space-1-5));
  border-left: var(--space-1-5) solid var(--color-tooltip-bg);
  border-right: none;
}

.vpm-meta-sep {
  color: #cfd4df;
}

/* ── Body ── */
.vpm-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  padding: 1.11111rem 1.55556rem 1.55556rem;
}

.vpm-state {
  flex: 1;
  min-height: 14.22222rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.vpm-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: 0.88889rem;
}

.vpm-section-title {
  font-family: var(--ohf-body);
  font-size: 0.88889rem;
  font-weight: 700;
  color: #171f30;
}

.vpm-run-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem; /* 8px */
  border: none;
  border-radius: 0.22222rem; /* 4px */
  background: var(--vpm-run-bg);
  color: var(--vpm-run-text);
  padding: 0.61111rem 1.33333rem; /* 11px 24px */
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale)); /* 14px */
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.vpm-run-btn:hover {
  background: var(--color-accent-hover);
}

.vpm-run-icon {
  width: 0.88889rem; /* 16px */
  height: 0.88889rem;
  /* OptimisationArrowRightIcon uses currentColor — inherits the button's own
     cream text colour rather than Figma's literal stroke fill. */
}

/* ── Scenario list ── */
.vpm-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.vpm-empty {
  text-align: center;
  color: var(--color-text-muted);
  font-size: calc(var(--font-size-sm) * var(--ohf-text-scale));
  padding: var(--space-xxl) 0;
}
/*
 * Self-hosted Fraunces + Manrope for the Optimization Home screen only.
 * The app's global font (Inter) is loaded via a <link> in index.html and
 * used everywhere else — these two are imported only from this feature's
 * page-level entry points (OptimisationHome.tsx, StartOptimisation.tsx),
 * so nothing about the rest of the app's font loading changes.
 *
 * Both are variable fonts; a single file covers the whole weight range
 * used here (Fraunces 500/600, Manrope 400/600/700), matching how Google
 * Fonts itself serves them.
 */

@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 500 600;
  font-display: swap;
  src: url("/assets/Fraunces-Variable-ukD16Tqj.woff2") format("woff2");
}

@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/Manrope-Variable-DHIcAJRg.woff2") format("woff2");
}

/* Self-hosted for the "Scope setup" screen's single "Your Scenario" heading
   (Figma node 418:26737, node "Your Scenario" TEXT) — the one node on that
   screen that isn't Fraunces or Manrope. Not variable; a single static
   weight covers the one 400-weight use. */
@font-face {
  font-family: "DM Serif Display";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/DMSerifDisplay-Regular-C5_t9oOD.woff2") format("woff2");
}

/* Self-hosted for the "Scope setup" screen's monospace figures — the target
   spend amount, and the mono-styled labels in the MAT reference sidebar
   ("55.1M", "3 found", "Annual · 3d ago"). Deliberately NOT the app's shared
   --font-family-mono token (Menlo): that's a different typeface used
   elsewhere in the app, and this Figma spec calls for IBM Plex Mono
   specifically. Two static weights (400/500) rather than a variable file,
   matching what was downloaded. */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/IBMPlexMono-Regular-DMJ8VG8y.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/IBMPlexMono-Medium-DSY6xOcd.woff2") format("woff2");
}
/* Palette scoped to the optimiser home screen (values from Figma).
   Kept local so nothing else in the app is affected. */
.oh-page {
  /* Same 5% type reduction as the "Scope setup" screen — see the matching
     comment in StartOptimisation.css. Every font-size here is its exact Figma
     pixel value x this factor, so the hierarchy is preserved and the deviation
     stays one number. 1 = exactly Figma. */
  --ohf-text-scale: 1;

  --oh-bg: #f6f6f9;
  --oh-heading: #171f30;
  --oh-subtext: #505869;
  --oh-card-border: #cfd4df;
  --oh-icon-bg: #0a1a40;
  --oh-icon-stroke: #edf2fc;
  --oh-cta-border: #b1b8c5;
  --oh-cta-text: #0a1a40;
  /* Filled hover variant (Figma component set 58:2577, "Property 1=Link") */
  --oh-cta-hover-bg: #0a1a40;
  --oh-cta-hover-text: #f9f5ed;
  --oh-disabled-card-bg: #ededed;
  --oh-disabled-icon-bg: #b8b8b8;
  --oh-disabled-icon-stroke: #7d7d7c;
  --oh-disabled-text: #7d7d7c;
  --oh-recent-border: #e1e5eb;
  --oh-pill-text: #677694;
  /* Same status pills as the "View all" modal (Figma nodes 136:15803 /
     509:9466): hairline border, and an active state that only tints the
     background rather than inverting to solid blue on white text. */
  --oh-pill-border: rgba(0, 0, 0, 0.08);
  --oh-pill-active-bg: rgba(0, 84, 216, 0.06);
  --oh-viewall: #213b6e;
  /* Figma (node 28:2535) specifies Arial/Arial-BoldMT for the type-card CTA
     label and the "View all" link, while every other text node on this
     screen is Fraunces/Manrope — likely an unrestyled component default
     left over in the design file. Implemented as-is per an explicit
     100%-match request; scoped as its own var so it's a one-line revert if
     this turns out to be a design slip. */
  --ohf-button: Arial, Helvetica, sans-serif;

  min-height: 100vh;
  padding-top: var(--space-10);
  background: var(--oh-bg);
}

.oh-loader,
.oh-error {
  padding: var(--space-xxl) var(--space-xl);
}

/* Figma (node 28:2535) lays this out on a 1440px page with 40px side padding,
   i.e. a 1360px content column — 44px above, 56px below. The old 75rem/24px
   gave a 1152px column, which is what left the dead space at the edges and
   squeezed the cards narrower (and therefore taller) than the design. */
.oh-body {
  max-width: 80rem;
  margin: 0 auto;
  padding: 2.44444rem 2.22222rem 3.11111rem;
  display: flex;
  flex-direction: column;
  /* Cards row -> Recent card */
  gap: 1.77778rem;
}

/* Heading block -> cards row */
.oh-section {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Figma groups the h1 and its subheading 8px apart; the 18px above separates
   that group from the cards, not these two lines. */
.oh-section-head {
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
}

.oh-heading {
  margin: 0;
  font-family: var(--ohf-heading);
  font-size: calc(1.55556rem * var(--ohf-text-scale));
  font-weight: 500;
  line-height: 1.486;
  letter-spacing: -0.0375rem;
  color: var(--oh-heading);
}

.oh-subheading {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.88889rem * var(--ohf-text-scale));
  line-height: 1.366;
  color: var(--oh-subtext);
}

/* ── Type cards ── */
/* Figma: three 438px cards, 24px apart, across the 1360px column
   ((1360 - 2*24) / 3 = 437.3). Fixed at 3 columns rather than auto-fit so the
   cards keep the design's proportions instead of reflowing to fill. */
.oh-types {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.33333rem;
}

@media (max-width: 53.33333rem) {
  .oh-types {
    grid-template-columns: 1fr;
  }
}

.oh-type-card {
  background: var(--color-white);
  border: 1px solid var(--oh-card-border);
  border-radius: 1.11111rem;
  /* Figma spec is 28px padding / 16px gap; --space-xl (24px) and
     --space-sm (8px) don't match, so these are hardcoded rem values. */
  padding: 1.55556rem;
  display: flex;
  flex-direction: column;
  gap: 0.88889rem;
  /* Figma card is a fixed 252px; min-height rather than height so a longer
     description wraps instead of overflowing. */
  min-height: 14rem;
}

.oh-type-card--disabled {
  background: var(--oh-disabled-card-bg);
}

.oh-type-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Figma spec is 44x44 (--space-11 is 44px too, but keep this local to the
     feature's own token block rather than reaching into the shared scale). */
  width: 2.44444rem;
  height: 2.44444rem;
  border-radius: 0.66667rem;
  background: var(--oh-icon-bg);
  color: var(--oh-icon-stroke);
}

/* Figma groups the title + description with 6px between them; the card's own
   16px gap is what separates this group from the icon and the CTA. Without
   this wrapper all four children sit a flat 16px apart. */
.oh-type-text {
  display: flex;
  flex-direction: column;
  gap: 0.33333rem;
  /* Absorbs the card's spare height so the CTA stays bottom-aligned across
     the three cards, which have unequal description lengths. */
  flex: 1;
}

.oh-type-icon-glyph {
  width: 1.22222rem;
  height: 1.22222rem;
}

.oh-type-card--disabled .oh-type-icon {
  background: var(--oh-disabled-icon-bg);
  color: var(--oh-disabled-icon-stroke);
}

.oh-type-title {
  margin: 0;
  font-family: var(--ohf-heading);
  font-size: calc(1.11111rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.233;
  color: var(--oh-heading);
}

.oh-type-card--disabled .oh-type-title {
  color: var(--oh-disabled-text);
}

.oh-type-desc {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.75rem * var(--ohf-text-scale));
  color: var(--oh-subtext);
  line-height: 1.55;
}

/* CTA — outline button, full card width, transparent bg (lets the disabled
   card's grey background show through), dark bold label */
.oh-type-cta {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.44444rem;
  border: 1px solid var(--oh-cta-border);
  background: transparent;
  color: var(--oh-cta-text);
  font-family: var(--ohf-button);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.15;
  height: 2.22222rem;
  padding: 0.61111rem var(--space-lg);
  border-radius: 0.22222rem;
  cursor: pointer;
  transition:
    background var(--motion-duration-fast) var(--motion-easing-standard),
    border-color var(--motion-duration-fast) var(--motion-easing-standard),
    color var(--motion-duration-fast) var(--motion-easing-standard),
    transform var(--motion-duration-fast) var(--motion-easing-spring),
    box-shadow var(--motion-duration-fast) var(--motion-easing-standard);
}

.oh-type-cta:hover:not(:disabled) {
  transform: translateY(-0.05556rem);
  box-shadow: 0 0.16667rem 0.44444rem var(--color-shadow-card-lg);
}

.oh-type-cta:active:not(:disabled) {
  transform: translateY(0) scale(0.98);
  box-shadow: none;
}

/* Hover = the filled "Link" variant of Figma's CTA component set (58:2577):
   solid navy, cream label, and a right arrow that only appears on hover.
   Note this variant specifies Manrope 600 while the default variant specifies
   Arial 700 — see the --ohf-button comment above; the inconsistency is the
   design file's, and the hover state is the one that looks deliberate. */
.oh-type-cta:hover:not(:disabled),
.oh-type-cta:focus-visible:not(:disabled) {
  background: var(--oh-cta-hover-bg);
  border-color: var(--oh-cta-hover-bg);
  color: var(--oh-cta-hover-text);
  font-family: var(--ohf-body);
  font-weight: 600;
}

/* Collapsed (zero width, flex gap cancelled by the negative margin) until
   hover so the resting button matches Figma's default variant, which has no
   arrow — on hover it slides in from behind the label instead of popping. */
.oh-type-cta-arrow {
  width: 0;
  height: 0.88889rem;
  flex-shrink: 0;
  opacity: 0;
  margin-left: -0.44444rem; /* cancels the flex gap while collapsed */
  transform: translateX(-0.22222rem);
  transition:
    width var(--motion-duration-fast) var(--motion-easing-standard),
    opacity var(--motion-duration-fast) var(--motion-easing-standard),
    margin-left var(--motion-duration-fast) var(--motion-easing-standard),
    transform var(--motion-duration-fast) var(--motion-easing-spring);
}

.oh-type-cta:hover:not(:disabled) .oh-type-cta-arrow,
.oh-type-cta:focus-visible:not(:disabled) .oh-type-cta-arrow {
  width: 0.88889rem;
  opacity: 1;
  margin-left: 0;
  transform: translateX(0);
}

.oh-type-cta:disabled {
  color: var(--oh-disabled-text);
  background: transparent;
  cursor: default;
}

/* ── Recent section (wrapped in its own white card) ── */
.oh-recent-card {
  background: var(--color-white);
  border: 1px solid var(--oh-recent-border);
  border-radius: 1.11111rem;
  /* Figma spec is 27px padding; --space-xl (24px) doesn't match. */
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.oh-recent-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
}

.oh-recent-title {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.88889rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.366;
  color: var(--oh-heading);
}

.oh-recent-subtitle {
  margin: 0.22222rem 0 0;
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  line-height: 1.4;
  color: var(--oh-subtext);
}

.oh-viewall {
  border: none;
  background: transparent;
  color: var(--oh-viewall);
  font-family: var(--ohf-button);
  font-size: calc(0.69444rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.15;
  cursor: pointer;
}

.oh-viewall:disabled {
  color: var(--color-text-placeholder);
  cursor: default;
}

.oh-recent-pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.oh-recent-pill {
  padding: 0.33333rem 0.77778rem;
  border-radius: 0.88889rem;
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.567; /* 18.8px / 12px, per Figma */
  border: 1px solid var(--oh-pill-border);
  background: var(--color-white);
  color: var(--oh-pill-text);
  cursor: pointer;
  transition: all var(--motion-duration-fast) var(--motion-easing-standard);
}

.oh-recent-pill:hover {
  background: var(--color-bg-hover-light);
  transform: translateY(-0.05556rem);
}

.oh-recent-pill:active {
  transform: translateY(0) scale(0.95);
}

.oh-recent-pill--active {
  background: var(--oh-pill-active-bg);
  border-color: var(--oh-pill-border);
  color: var(--oh-pill-text);
}

.oh-recent-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-top: var(--space-xs);
}

.oh-recent-empty {
  display: flex;
  flex: 1;
  align-items: flex-start;
  justify-content: center;
  color: var(--color-text-muted);
  font-size: calc(var(--font-size-sm) * var(--ohf-text-scale));
  padding: var(--space-lg) 0;
}

/* ── Reduced motion: keep state changes, drop movement ── */
@media (prefers-reduced-motion: reduce) {
  .oh-type-cta,
  .oh-type-cta-arrow,
  .oh-recent-pill {
    transition: none;
  }
  .oh-type-cta:hover:not(:disabled),
  .oh-type-cta:active:not(:disabled),
  .oh-recent-pill:hover,
  .oh-recent-pill:active {
    transform: none;
  }
  .oh-type-cta-arrow {
    transform: none;
  }
}
/* Palette scoped to the card (values from Figma node 418:26737). */
.sdc-card {
  --sdc-border: rgba(207, 212, 223, 0.4);
  --sdc-heading: #171f30;
  --sdc-label: #838996;
  --sdc-track-bg: #edf2fc;
  --sdc-track-border: #cfd4df;
  --sdc-pill-text: #505869;
  --sdc-pill-active-bg: #0a1a40;
  --sdc-pill-active-text: #f9f5ed;
  --sdc-input-border: #b1b8c5;
  --sdc-input-text: #171f30;

  background: var(--color-white);
  border: 1px solid var(--sdc-border);
  border-radius: 0.66667rem;
  padding: 1.33333rem 1.44444rem;
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
}

.sdc-heading {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.88889rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.366;
  color: var(--sdc-heading);
}

.sdc-row {
  display: flex;
  /* nowrap, not wrap: flexbox decides wrapping from each item's flex-BASIS
     sum, before any shrinking — Figma's own basis values (304 + 371 + 619 +
     2 gaps) add up to slightly MORE than this card's actual content width,
     so `wrap` bumped Description onto its own line on every normal render,
     not just genuinely squeezed viewports. All three fields can shrink
     (`min-width: 0`, `flex-shrink: 1`) to fit one row instead. */
  flex-wrap: nowrap;
  gap: 1.33333rem;
  padding-top: 0.66667rem;
}

.sdc-field-label {
  display: block;
  font-family: var(--ohf-body);
  font-size: calc(0.63889rem * var(--ohf-text-scale)); /* 11.5px */
  font-weight: 700;
  line-height: 1.367;
  letter-spacing: 0.03833rem; /* 0.69px */
  color: var(--sdc-label);
  margin-bottom: 0.44444rem;
}

/* ── Time period segmented control ── */
.sdc-time {
  flex: 0 0 16.88889rem; /* 304px */
}

.sdc-time-track {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.11111rem;
  padding: 0.16667rem;
  width: 100%;
  background: var(--sdc-track-bg);
  border: 1px solid var(--sdc-track-border);
  border-radius: 55.5rem;
}

/* The single dark pill that slides beneath whichever option is active.
   Positioned from --sdc-thumb-x/--sdc-thumb-w, measured off the real active
   button in the component (labels are unequal widths, so no CSS-only math) —
   both transform and width animate so the pill stretches while it glides.
   Hidden until the first measurement lands (vars unset -> width 0). */
.sdc-time-thumb {
  position: absolute;
  top: 0.16667rem;
  bottom: 0.16667rem;
  left: 0;
  width: var(--sdc-thumb-w, 0);
  border-radius: 55.5rem;
  background: var(--sdc-pill-active-bg);
  transform: translateX(var(--sdc-thumb-x, 0));
  transition:
    transform var(--motion-duration-slow) var(--motion-easing-spring),
    width var(--motion-duration-slow) var(--motion-easing-spring);
}

.sdc-time-pill {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 1.88889rem; /* 34px */
  padding: 0.44444rem 0.88889rem;
  border: none;
  border-radius: 55.5rem;
  background: transparent;
  color: var(--sdc-pill-text);
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.366;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--motion-duration-fast) var(--motion-easing-standard),
    color var(--motion-duration-fast) var(--motion-easing-standard),
    transform var(--motion-duration-fast) var(--motion-easing-spring);
}

/* Hover must NOT paint a background — the sliding thumb lives underneath the
   labels and an opaque hover fill overlaps it as a second, clashing pill.
   Emphasise the label instead. */
.sdc-time-pill:not(.sdc-time-pill--active):hover {
  color: var(--sdc-pill-active-bg);
}

.sdc-time-pill:active {
  transform: scale(0.96);
}

/* Background comes from the sliding .sdc-time-thumb behind this label —
   the pill itself only switches its text colour. */
.sdc-time-pill--active {
  color: var(--sdc-pill-active-text);
}

@media (prefers-reduced-motion: reduce) {
  .sdc-time-thumb,
  .sdc-time-pill {
    transition: none;
  }
  .sdc-time-pill:active {
    transform: none;
  }
}

/* ── Scenario name ──
   Figma's own 371px basis, not a plain flex:1 — the field used to just grab
   every pixel description didn't need before description moved into this
   same row, so it stretched across the ENTIRE remaining width on its own.
   flex-grow 371 (matching the basis) keeps it and Description growing in
   Figma's own ~371:619 ratio if the row has slack, rather than splitting any
   extra space 50/50. */
.sdc-name-group {
  flex: 371 1 20.61111rem; /* 371px */
  min-width: 0; /* lets it actually shrink below its basis — see .sdc-row */
  display: flex;
  flex-direction: column;
}

.sdc-name-input {
  width: 100%;
  height: 2.27778rem; /* 41px */
  border: 1px solid var(--sdc-input-border);
  border-radius: 0.22222rem;
  background: var(--color-white);
  padding: 0.55556rem 0.66667rem;
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 600;
  color: var(--sdc-input-text);
}

.sdc-name-input::placeholder {
  color: var(--color-text-placeholder);
  font-weight: 400;
}

.sdc-name-input:focus-visible {
  outline: none;
  border-color: var(--color-input-border-focus);
}

.sdc-name-input--error {
  border-color: var(--color-error, #d32f2f);
}

/* Validation message (left) + character counter (right) on one line, so the
   counter is always in the same place whether or not the field is in error. */
.sdc-field-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.66667rem;
}

.sdc-name-error {
  margin-top: 0.33333rem;
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  color: var(--color-error, #d32f2f);
}

/* Reads as a quiet annotation, not a second label — same size as the error
   text beside it but in the card's muted label colour. `margin-left: auto`
   keeps it hard right even when there is no message to push against. */
.sdc-char-count {
  margin-top: 0.33333rem;
  margin-left: auto;
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  color: var(--sdc-label);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Description — always visible, required (see ScenarioDetailsCard's
   doc comment on `descriptionError`) — third column in `.sdc-row`, same
   371px-basis reasoning as `.sdc-name-group` above, just Figma's 619px. ── */
.sdc-description-group {
  flex: 619 1 34.38889rem; /* 619px */
  min-width: 0; /* lets it actually shrink below its basis — see .sdc-row */
  display: flex;
  flex-direction: column;
}

.sdc-description-textarea {
  width: 100%;
  /* Figma's own 41px — the same height as `.sdc-name-input` beside it, not
     a taller multi-line box. `resize: vertical` still lets the user expand
     it for a longer description; this is just the box's resting size. */
  height: 2.27778rem; /* 41px */
  min-height: 2.27778rem;
  resize: vertical;
  border: 1px solid var(--sdc-input-border);
  border-radius: 0.22222rem;
  background: var(--color-white);
  padding: 0.55556rem 0.66667rem;
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  color: var(--sdc-input-text);
}

.sdc-description-textarea::placeholder {
  color: var(--color-text-placeholder);
  font-weight: 400;
}

.sdc-description-textarea:focus-visible {
  outline: none;
  border-color: var(--color-input-border-focus);
}

.sdc-description-textarea--error {
  border-color: var(--color-error, #d32f2f);
}

/* Same 1024px floor the rest of this screen degrades at (.ss-brands-row in
   StartOptimisation.css, .bp-card in BrandsPicker.css) — below it, shrinking
   alone would squeeze Name/Description uncomfortably narrow, so wrapping
   (Description first, since it's last in source order) takes over instead. */
@media (max-width: 64rem) {
  .sdc-row {
    flex-wrap: wrap;
  }
}
/* Palette scoped to the card (values from Figma node 418:26737). */
.bp-card {
  --bp-border: rgba(0, 0, 0, 0.08);
  --bp-label: #9a9ca2;
  --bp-search-border: rgba(177, 184, 197, 0.4);
  --bp-search-placeholder: #757575;
  --bp-item-border: rgba(0, 0, 0, 0.09);
  --bp-item-name: #0e0f11;
  --bp-item-available: #9a9ca2;
  --bp-item-note: #0fa870;
  --bp-add-border: rgba(0, 0, 0, 0.14);
  --bp-add-text: #0e0f11;
  --bp-remove-bg: rgba(137, 137, 137, 0.1);
  --bp-remove-border: rgba(129, 129, 129, 0.3);
  --bp-remove-text: #666b69;

  /* Figma's 280px as the basis, but it yields down to 220px on narrower screens
     so the scope row-builder to the right keeps its four selects on one line.
     Never grows past 280, so the full-width layout still matches Figma. */
  flex: 0 1 15.55556rem; /* 280px */
  min-width: 12.22222rem; /* 220px */
  /* Figma's flat ~487px (node 2580:6759), FIXED — not content-sized. This
     card used to hug its content (`height: auto` under a ceiling) to avoid
     dead white space under a short brand list; that made the panel resize
     under the user on every search keystroke, since filtering the list
     changed the card's height. A panel that jumps as you type is worse than
     one with space in it, so the height is now stable and .bp-list scrolls
     inside it. (This was 609px before — an unverified guess from before MAT
     reference moved out of being a sidebar; see StartOptimisation.css's
     `.ss-scenario-col` for the same correction and why it mattered more
     once this row stood alone.) */
  height: 27.05556rem; /* 487px */
  background: var(--color-white);
  border: 1px solid var(--bp-border);
  border-radius: 0.66667rem;
  padding: 1rem 0.88889rem;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.bp-label {
  flex-shrink: 0;
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale)); /* 10.5px */
  font-weight: 700;
  letter-spacing: 0.04667rem; /* 0.84px */
  color: var(--bp-label);
  text-transform: uppercase;
}

.bp-search {
  position: relative;
  display: flex;
  align-items: center;
  flex-shrink: 0;
  /* The 14px clearance before the list lives here (margin-bottom on a
     sibling OUTSIDE the scroll container), not as .bp-list's own top
     padding — padding on a scroll container scrolls away with its content
     the instant the user scrolls, leaving no clearance at all (same bug
     already worked around in RecentOptimizationsModal.css). */
  margin: 0.66667rem 0 0.77778rem;
}

.bp-search-icon {
  position: absolute;
  left: 0.66667rem;
  top: 50%;
  transform: translateY(-50%);
  width: 0.77778rem;
  height: 0.77778rem;
  color: #838996;
  pointer-events: none;
}

.bp-search-input {
  width: 100%;
  height: 2.11111rem; /* 38px */
  border: 1px solid var(--bp-search-border);
  border-radius: 0.44444rem;
  background: var(--color-white);
  /* Right padding clears the × (see SearchClearButton), which overlays this
     field's right edge. */
  padding: 0 1.77778rem 0 1.77778rem;
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  color: var(--color-text-body);
}

.bp-search-input::placeholder {
  color: var(--bp-search-placeholder);
}

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

.bp-list {
  list-style: none;
  margin: 0;
  /* No top padding: the clearance above the list lives on .bp-search
     instead (see its comment) so it survives scrolling. Right padding only,
     to keep cards clear of the scrollbar. */
  padding: 0 0.11111rem 0 0;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
  overflow-y: auto;
}

.bp-empty {
  color: var(--bp-item-available);
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  padding: 0.44444rem 0;
  text-align: center;
}

.bp-item {
  border: 1px solid var(--bp-item-border);
  border-radius: 0.55556rem;
  padding: 0.72222rem 0.77778rem;
}

/* An added brand's whole card is a selection control (picks the "active"
   brand the scenario panel focuses) — reset it back to plain block styling
   so it doesn't look or behave like a generic <button>. */
.bp-item-select {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.bp-item-select:focus-visible {
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 2px;
}

.bp-item--added {
  padding: 0;
  border-left: 3px solid transparent;
  transition: border-color var(--motion-duration-fast) var(--motion-easing-standard);
}

.bp-item--added .bp-item-select {
  padding: 0.72222rem calc(0.77778rem - 2px);
}

/* The active brand — same accent as the rest of the app's "currently
   selected" treatment (input focus border / primary text). */
.bp-item--active {
  border-left-color: var(--color-border-strong);
  background: var(--color-bg-hover-light);
}

.bp-item-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.55556rem;
}

.bp-item-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.bp-item-name-row {
  display: flex;
  align-items: center;
  gap: 0.44444rem;
}

.bp-item-name {
  font-family: var(--font-family-base);
  font-size: calc(0.75rem * var(--ohf-text-scale)); /* 13.5px */
  font-weight: 600;
  color: var(--bp-item-name);
}

/* "1 row" / "3 rows" — how many combinations this brand already has, so the
   left panel answers that without opening "All combinations". Same pill
   shape as `.ss-scenario-count` (StartOptimisation.css), scoped locally
   since this card doesn't share that file's custom properties. */
.bp-item-count {
  flex-shrink: 0;
  padding: 0.16667rem 0.44444rem;
  border-radius: 0.88889rem;
  background: var(--color-success-bg);
  color: var(--color-success);
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale));
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* "AVAILABLE" — separates brands not yet added from the ones above, same
   eyebrow treatment as `.bp-label` itself. */
.bp-available-label {
  margin-top: 0.22222rem;
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale));
  font-weight: 700;
  letter-spacing: 0.04667rem;
  text-transform: uppercase;
  color: var(--bp-label);
}

.bp-item-available {
  margin-top: 0.16667rem;
  font-family: var(--font-family-base);
  font-size: calc(0.63889rem * var(--ohf-text-scale)); /* 11.5px */
  color: var(--bp-item-available);
}

.bp-item-btn {
  flex-shrink: 0;
  height: 1.47222rem; /* 26.5px */
  padding: 0 0.55556rem;
  border-radius: 0.38889rem;
  background: var(--color-white);
  border: 1px solid var(--bp-add-border);
  color: var(--bp-add-text);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
  cursor: pointer;
  transition: background var(--motion-duration-fast) var(--motion-easing-standard);
}

.bp-item-btn:hover {
  background: var(--color-bg-hover-light);
}

.bp-item-btn--remove {
  background: var(--bp-remove-bg);
  border-color: var(--bp-remove-border);
  color: var(--bp-remove-text);
}

.bp-item-btn--remove:hover {
  background: rgba(137, 137, 137, 0.2);
}

.bp-item-note {
  margin: 0.33333rem 0 0;
  font-family: var(--font-family-base);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  color: var(--bp-item-note);
}

/* `.ss-brands-row` (StartOptimisation.css) stacks to a column at this same
   853px floor. `.bp-card`'s `flex: 0 1 15.55556rem` basis sizes the row's
   main axis today — a 280px WIDTH — but once the parent flips to a column
   that same basis would size the vertical main axis instead, forcing a flat
   280px HEIGHT unrelated to this card's actual (`height: auto`) content.
   Reset the basis so height is driven by content again, and take the full
   column width instead of the row's 220–280px shrink range, which no longer
   applies once `.ss-scenario-col` is stacked below rather than beside it. */
@media (max-width: 64rem) {
  .bp-card {
    flex: 0 1 auto;
    width: 100%;
    min-width: 0;
  }
}

/* Brand + market names are lowercase in the source data — see
   ScopeFieldSelect.css. `.bp-item-markets` is a span around just the market
   list so the surrounding sentence ("Available in ...") keeps its own casing. */
.bp-item-name,
.bp-item-markets {
  text-transform: capitalize;
}

/* "13 more" — the markets the line didn't spell out (see `MARKETS_SHOWN`).
   Deliberately NOT a chip: it is the tail of a sentence, so it stays inline
   text and only carries enough weight to read as hoverable. The dotted
   underline is the conventional "there is more here" affordance and is what
   makes the full-list tooltip discoverable without a badge shouting for
   attention. */
.bp-item-markets-more {
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  text-decoration: underline dotted;
  text-underline-offset: 0.11111rem;
  cursor: help;
}
/* Palette scoped to the field (values from Figma node 418:26737). */
.sfs-field {
  --sfs-label: #6b6e76;
  --sfs-border: rgba(0, 0, 0, 0.12);
  --sfs-text: #0e0f11;
  --sfs-placeholder: #9a9ca2;

  display: flex;
  flex-direction: column;
  gap: 0.33333rem;
  /* Figma's 145px as the basis, shrinking so the four dropdowns stay on one
     row on narrower screens instead of wrapping, AND growing to fill the
     row-builder's real width — this used to be grow:0 on the assumption
     that "Your Scenario" was a fixed 732px card, so 145px was already most
     of the available room; now that card is a genuine 1064px (see
     StartOptimisation.css's `.ss-scenario-group`), grow:0 left the four
     fields stranded at their narrow basis with a wide dead gap before the
     Add button. */
  flex: 1 1 8.05556rem; /* 145px */
  min-width: 0;
}

.sfs-label {
  font-family: var(--ohf-body);
  font-size: calc(0.58333rem * var(--ohf-text-scale)); /* 10.5px */
  font-weight: 600;
  line-height: 1.21;
  color: var(--sfs-label);
}

/* Shared SelectDropdown restyled as a plain bordered field: the label sits
   above (via .sfs-label), so the component's own floating label is hidden.
   Uses the component's own default chevron (KeyboardArrowDownIcon), sized
   16×16 by the base component. */
.sfs-select.sd-wrap {
  width: 100%;
  border: 1px solid var(--sfs-border);
  border-radius: 0.44444rem;
  background: var(--color-white);
  /* Belt and braces: `.sd-trigger`'s own box should never need to be clipped
     (see the `min-width: 0` override below for why it no longer tries to
     grow past this wrap), but this field sits directly beside the row
     builder's "Add" button (`.sct-builder`/`.act-builder`) with
     nothing else clipping between them — hide any residual overflow here so
     a future regression degrades into truncated text, never a trigger that
     visually and functionally overlaps the next control in the row. */
  overflow: hidden;
}

.sfs-select .sd-label {
  display: none;
}

.sfs-select .sd-trigger {
  width: 100%;
  height: 1.94444rem; /* 35px */
  padding: 0 0.55556rem;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  color: var(--sfs-text);
  /* The shared component's own default (`min-width: var(--space-8)`, 128px —
     sized for standalone filter dropdowns elsewhere) is bigger than this
     field's flex parent (`.sfs-field`, `flex: 0 1 8.05556rem; min-width: 0`)
     is ever allowed to shrink it to on this screen's tightly packed builder
     row (four selects + the "Add" button sharing one nowrap line — see
     `.sct-builder`/`.act-builder`). That floor doesn't stop the
     row from needing to shrink narrower than 128px, it just stops THIS
     button from shrinking to match: the trigger's rendered box then simply
     overflowed its own `.sfs-field`/`.sd-wrap`, painting over (and eating
     clicks meant for) whatever sits to its right — for the last field
     (Sub brand) that's the row's "Add" button. Overriding back to 0 lets the
     trigger track its flex parent's real, negotiated width exactly; `.sd-value`
     already ellipsis-truncates long option text, so nothing becomes
     unreadable, it just gets tighter. */
  min-width: 0;
}

.sfs-select .sd-value {
  color: var(--sfs-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sfs-select--placeholder .sd-value {
  color: var(--sfs-placeholder);
}

/* Market / Region / Sub-brand values arrive from `dim_*.display_label`, which is
   lowercase in the source data ("marmite", "north india"). Capitalised here for
   presentation only — the underlying strings stay untouched because they double
   as the select's option values and as scope-resolution keys server-side.
   The placeholder is excluded so "Select market" doesn't become "Select Market".
   `.sd-option-label` is reachable because SelectDropdown forwards this class to
   its portaled list; without that the open list would disagree with the closed
   field. */
.sfs-select:not(.sfs-select--placeholder) .sd-value {
  text-transform: capitalize;
}

.sfs-select .sd-option-label {
  text-transform: capitalize;
}
/* Row-builder + combinations table shared by the "This brand" tab and each
   expanded group in "All combinations" — palette carried over from the old
   per-brand card (Figma node 418:26737), now scoped to `.sct-root` since it
   no longer owns its own bordered card. */
.sct-root {
  --sct-builder-bg: #fcfbf9;
  --sct-builder-border: rgba(0, 0, 0, 0.08);
  /* Figma only ever draws this button in its disabled state (an empty row
     builder), so the greyed rgba(26,39,68,0.35) is the *disabled* fill. The
     enabled fill is this screen's established CTA navy — inferred, not
     specified by the design. */
  --sct-add-bg: rgba(26, 39, 68, 0.35);
  --sct-add-bg-enabled: #0a1a40;
  --sct-table-row-border: rgba(0, 0, 0, 0.05);
  --sct-table-text: #0e0f11;
  --sct-close-icon: #888888;

  /* Width of the trailing action strip — the Add button in the row builder,
     the remove button in the table. Both are pinned to it so the four scope
     columns either side come out at the same pitch and every column sits
     under the select that feeds it. */
  --sct-action-col: 3.55556rem; /* 64px */

  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
}

/* Same header AllCombinationsTable's own group uses (`.act-group-name`/
   `.act-group-count`) — the two tabs show the same fact (which brand, how
   many rows) so it should read as one system, not two different treatments. */
.sct-brand-header {
  display: flex;
  align-items: center;
  gap: 0.44444rem;
}

.sct-brand-name {
  font-family: var(--font-family-base);
  font-size: calc(0.75rem * var(--ohf-text-scale));
  font-weight: 600;
  color: var(--sct-table-text);
  text-transform: capitalize;
}

.sct-brand-count {
  flex-shrink: 0;
  padding: 0.16667rem 0.44444rem;
  border-radius: 0.88889rem;
  background: var(--color-success-bg);
  color: var(--color-success);
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale));
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* nowrap is load-bearing: with flex-wrap:wrap the browser packs items onto a
   line at their flex-basis and only shrinks them afterwards, so the four
   145px selects wrapped Sub brand + Add onto a second row instead of
   narrowing. With nowrap they compress via their `flex: 0 1 145px` and stay
   on one line. */
.sct-builder {
  display: flex;
  align-items: flex-end;
  flex-wrap: nowrap;
  gap: 0.66667rem;
  background: var(--sct-builder-bg);
  border: 1px solid var(--sct-builder-border);
  border-radius: 0.55556rem;
  padding: 0.83333rem;
}

.sct-add-row-btn {
  flex-shrink: 0;
  width: var(--sct-action-col);
  height: 1.83333rem; /* 33px */
  padding: 0;
  border: none;
  border-radius: 0.44444rem;
  background: var(--sct-add-bg);
  color: var(--color-white);
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale)); /* 12.5px */
  font-weight: 600;
  cursor: pointer;
}

/* Turns navy the moment the row builder holds a complete, non-duplicate
   combination — the affordance that the row is ready to add. */
.sct-add-row-btn:not(:disabled) {
  background: var(--sct-add-bg-enabled);
}

.sct-add-row-btn:not(:disabled):hover {
  opacity: 0.92;
}

.sct-add-row-btn:disabled {
  cursor: not-allowed;
}

/* ── Combinations table ──
   `table-layout: fixed` with explicit widths, because auto layout sizes each
   column from its own content — the four scope columns split the row evenly
   instead, so every table (and the builder's four selects above it) share
   one grid. `border-collapse: collapse` makes the browser ignore padding on
   the <table> itself, so the gutter lives on the wrapper. */
.sct-table-wrap {
  padding-inline: calc(0.83333rem + 1px); /* .sct-builder's padding + border */
}

.sct-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.sct-table td {
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  color: var(--sct-table-text);
  border-bottom: 1px solid var(--sct-table-row-border);
  padding: 0.72222rem 0.44444rem 0.72222rem 0.55556rem;
  /* Market, Region and Sub Brand arrive from the warehouse lowercased ("usa",
     "midwest", "axe") — the same treatment the scope selects above already
     get, so a value reads identically whether it is picked or listed. */
  text-transform: capitalize;
}

/* Fixed columns cannot grow for a long value, so clip rather than let one
   wrap and push the row taller than its neighbours. The HoverTooltip anchor
   itself must carry the clip — its `clipped-x` check compares scrollWidth
   against clientWidth on this element, not the surrounding `td`. */
.sct-data-cell {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* padding-right is the builder's inter-select gap: with border-box widths the
   cell's CONTENT box then matches a select, not just its column. */
.sct-table td:not(:last-child) {
  width: calc((100% - var(--sct-action-col)) / 4);
  padding-right: 0.66667rem;
}

.sct-table-remove-cell {
  width: var(--sct-action-col);
  padding-right: 0;
  text-align: right;
}

.sct-table-remove-btn {
  border: none;
  background: transparent;
  color: var(--sct-close-icon);
  cursor: pointer;
  padding: 0.22222rem;
  border-radius: var(--radius-full);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background var(--motion-duration-fast) var(--motion-easing-standard),
    color var(--motion-duration-fast) var(--motion-easing-standard),
    transform var(--motion-duration-fast) var(--motion-easing-spring);
}

/* Destructive affordance: the cross turns red and twists a quarter turn as
   you hover, and presses down on click. */
.sct-table-remove-btn:hover {
  background: var(--color-danger-bg);
  color: var(--color-error);
  transform: rotate(90deg) scale(1.1);
}

.sct-table-remove-btn:active {
  transform: rotate(90deg) scale(0.9);
}

.sct-table-remove-icon {
  width: 0.77778rem; /* 14px */
  height: 0.77778rem;
}

@media (prefers-reduced-motion: reduce) {
  .sct-table-remove-btn {
    transition: none;
  }
  .sct-table-remove-btn:hover,
  .sct-table-remove-btn:active {
    transform: none;
  }
}

/* Below ~1200px the row builder's four 145px-basis selects (see
   ScopeFieldSelect.css's `.sfs-field`) no longer have enough room to shrink
   to a legible width beside a fixed-size "Add" button on one nowrap line —
   rather than resurrect naive `flex-wrap: wrap` (it packs items at their full
   flex-basis before shrinking, so it wraps even when shrinking alone would
   have fit them), only wrap AT this width, and size the wrapped fields as
   fluid 2-per-row percentages instead of a fixed basis. */
@media (max-width: 75rem) {
  .sct-builder {
    flex-wrap: wrap;
  }

  .sct-builder .sfs-field {
    /* Two fields per row (basis + gap halved so 2 + 1 gap == 100%), fluid
       from here down to the narrowest supported width instead of a fixed
       145px that would force a THIRD breakpoint. */
    flex: 1 1 calc(50% - 0.33334rem);
  }
}
/* "All combinations" — one table, every added brand as a collapsible group.
   Palette matches ScopeCombinationTable.css (same source Figma card), scoped
   locally since this table doesn't share that file's custom properties. */
.act-table-wrap {
  --act-border: rgba(0, 0, 0, 0.08);
  --act-table-header: #9a9ca2;
  --act-table-row-border: rgba(0, 0, 0, 0.05);
  --act-table-text: #0e0f11;
  --act-close-icon: #888888;
  --act-builder-bg: #fcfbf9;
  --act-add-bg: rgba(26, 39, 68, 0.35);
  --act-add-bg-enabled: #0a1a40;
  --act-action-col: 3.55556rem; /* 64px */
  --act-inset: calc(0.83333rem + 1px);

  padding-inline: var(--act-inset);
}

.act-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.act-col-field {
  width: calc((100% - var(--act-action-col)) / 4);
}

.act-col-action {
  width: var(--act-action-col);
}

/* ── Group header row (brand name + count + expand/collapse) ── */
.act-group:not(:first-of-type) .act-group-header-row td {
  padding-top: 0.66667rem;
}

.act-group-header-row td {
  padding: 0.55556rem 0 0;
}

.act-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  /* Cancels `.act-table-wrap`'s inset for just this row, so the brand
     name/toggle still reaches the row's true left/right edges instead of
     sitting indented like the data columns now deliberately are. The
     divider moves here too (off the td, which the margin above doesn't
     widen) so it spans that same true full width instead of stopping short
     at the inset table's edge. */
  margin-inline: calc(-1 * var(--act-inset));
  padding-bottom: 0.55556rem;
  border-bottom: 1px solid var(--act-border);
}

.act-group-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  min-width: 0;
}

.act-group-chevron {
  width: 0.66667rem;
  height: 0.66667rem;
  flex-shrink: 0;
  color: var(--act-table-header);
  transition: transform var(--motion-duration-fast) var(--motion-easing-standard);
  transform: rotate(-90deg);
}

.act-group-chevron--expanded {
  transform: rotate(0deg);
}

.act-group-name {
  font-family: var(--font-family-base);
  font-size: calc(0.75rem * var(--ohf-text-scale));
  font-weight: 600;
  color: var(--act-table-text);
  text-transform: capitalize;
}

/* Same pill treatment as the left Brands panel's row-count badge
   (`.bp-item-count`) — the two are the same fact shown in two places, so
   they read as one system rather than two different badges. */
.act-group-count {
  flex-shrink: 0;
  padding: 0.16667rem 0.44444rem;
  border-radius: 0.88889rem;
  background: var(--color-success-bg);
  color: var(--color-success);
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale));
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Inline add-row builder (shown while a group is expanded) ── */
.act-builder-row td {
  padding: 0.55556rem 0;
}

.act-builder {
  display: flex;
  align-items: flex-end;
  flex-wrap: nowrap;
  gap: 0.66667rem;
  background: var(--act-builder-bg);
  border: 1px solid var(--act-border);
  border-radius: 0.55556rem;
  padding: 0.83333rem;
  /* Same cancellation as `.act-group-header` — without it this box would sit
     indented by `.act-table-wrap`'s inset on top of its own padding/border,
     doubling up instead of just reaching the row's true edges. */
  margin-inline: calc(-1 * var(--act-inset));
}

.act-add-row-btn {
  flex-shrink: 0;
  width: var(--act-action-col);
  height: 1.83333rem; /* 33px */
  padding: 0;
  border: none;
  border-radius: 0.22222rem; /* 4px, Figma's own radius on this button */
  background: var(--act-add-bg);
  color: var(--color-white);
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale));
  font-weight: 600;
  cursor: pointer;
}

.act-add-row-btn:not(:disabled) {
  background: var(--act-add-bg-enabled);
}

.act-add-row-btn:not(:disabled):hover {
  opacity: 0.92;
}

.act-add-row-btn:disabled {
  cursor: not-allowed;
}

@media (max-width: 75rem) {
  .act-builder {
    flex-wrap: wrap;
  }

  .act-builder .sfs-field {
    flex: 1 1 calc(50% - 0.33334rem);
  }
}

/* ── Data rows (a group's committed combinations) ── */
.act-data-row td {
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  color: var(--act-table-text);
  border-bottom: 1px solid var(--act-table-row-border);
  /* Left padding matches `.sfs-select .sd-trigger`'s own `padding: 0
     0.55556rem` — each column already lines up with the select above it
     (once its group's builder is expanded), but the select's VALUE TEXT
     sits inset from the box edge by its own padding, so the data cell's
     text needs the same inset to land under it, not the box edge. */
  padding: 0.72222rem 0.44444rem 0.72222rem 0.55556rem;
  text-transform: capitalize;
}

.act-data-cell {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.act-table-remove-cell {
  width: var(--act-action-col);
  padding-right: 0 !important;
  text-align: right;
  text-transform: none !important;
}

.act-table-remove-btn {
  border: none;
  background: transparent;
  color: var(--act-close-icon);
  cursor: pointer;
  padding: 0.22222rem;
  border-radius: var(--radius-full);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background var(--motion-duration-fast) var(--motion-easing-standard),
    color var(--motion-duration-fast) var(--motion-easing-standard),
    transform var(--motion-duration-fast) var(--motion-easing-spring);
}

.act-table-remove-btn:hover {
  background: var(--color-danger-bg);
  color: var(--color-error);
  transform: rotate(90deg) scale(1.1);
}

.act-table-remove-btn:active {
  transform: rotate(90deg) scale(0.9);
}

.act-table-remove-icon {
  width: 0.77778rem;
  height: 0.77778rem;
}

@media (prefers-reduced-motion: reduce) {
  .act-table-remove-btn,
  .act-group-chevron {
    transition: none;
  }
  .act-table-remove-btn:hover,
  .act-table-remove-btn:active {
    transform: none;
  }
}
/* Palette scoped to the card (values from Figma node 418:23991, the
   "Your Scenario" empty state). */
.ses-card {
  --ses-border: rgba(0, 0, 0, 0.08);
  --ses-heading: #0e0f11;
  --ses-diamond-stroke: #758bbc;
  --ses-diamond-fill: rgba(200, 211, 232, 0.6);
  --ses-bolt: rgba(68, 101, 162, 0.9);
  --ses-message: #9a9ca2;

  /* Fills `.ss-scenario-col`'s full width, not a stale fixed 732px (that
     figure matched the OLD fixed-width scenario column — see
     StartOptimisation.css's `.ss-scenario-group` for the same correction). */
  width: 100%;
  /* Figma's 440px is the FLOOR, not the height: the card fills its column so
     its bottom edge lines up with the Brands card beside it (see
     `.ss-brands-row`), which is taller than 440 as soon as the brand list is.
     A fixed height here left the empty state stopping short of the Brands
     card, which is what made the two columns look unrelated. */
  min-height: 24.44444rem; /* 440px */
  flex: 1 1 auto;
  background: var(--color-white);
  border: 1px solid var(--ses-border);
  border-radius: 0.66667rem;
  padding: 1.11111rem 1.22222rem;
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
}

/* Matches `.ss-scenario-heading` (StartOptimisation.css) exactly — same
   "Your Scenario" heading, shown here before the first brand is added and
   there once it has been, so a mismatched size/family read as the text
   itself changing. */
.ses-heading {
  margin: 0;
  font-family: var(--font-family-base);
  font-size: calc(0.88889rem * var(--ohf-text-scale));
  font-weight: 400;
  line-height: 1.35;
  color: var(--ses-heading);
}

.ses-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.33333rem; /* 24px */
}

.ses-diamond {
  width: 3.44444rem; /* 62px */
  height: 3.44444rem;
  flex-shrink: 0;
  border: 2px solid var(--ses-diamond-stroke);
  border-radius: 1rem; /* 18px, pre-rotation */
  transform: rotate(45deg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.ses-diamond-inner {
  width: 2.38889rem; /* 43px */
  height: 2.38889rem;
  border-radius: 0.77778rem; /* 14px */
  background: var(--ses-diamond-fill);
  /* Counter-rotate back to upright — the outer diamond's rotation would
     otherwise carry this badge (and the bolt icon inside it) around too. */
  transform: rotate(-45deg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.ses-bolt-icon {
  width: 0.88889rem; /* 16px */
  height: 0.88889rem;
  color: var(--ses-bolt);
}

.ses-message {
  margin: 0;
  font-family: var(--font-family-base);
  font-size: calc(0.88889rem * var(--ohf-text-scale));
  color: var(--ses-message);
  text-align: center;
}
/* Figma (nodes 2580:6759 / 2581:7161) — an INSET panel inside
   `.ss-scenario-group`, sitting between the header and the row-builder, not
   a separate standalone card stacked above it (which is what the old Figma
   frame, node 418:25166, showed — this used to render as its own full white/
   bordered card, matching `.ses-card`'s 732px width, when the scenario group
   was still a fixed 732px card itself; both of those are gone). Reuses the
   same off-white inset treatment the row-builder panel below it already uses
   (`--sct-builder-bg`/`--act-builder-bg`, #fcfbf9) so the two read as one
   family of "panel within the card," not a second competing card chrome. */
.ppc-card {
  --ppc-border: rgba(0, 0, 0, 0.08);
  --ppc-title: #0e0f11;
  --ppc-bookmark: #304d89;
  --ppc-description: #6b6e76;
  --ppc-input-border: rgba(0, 0, 0, 0.12);
  --ppc-input-placeholder: #757575;
  /* Figma's button fill (#afb3be) is the DISABLED state — the frame it was
     captured from has an empty name input. The enabled fill isn't specified
     anywhere in the spec; inferred as this screen's own established CTA
     navy (matches "Set Constraints"), not a new invented colour. */
  --ppc-btn-disabled-bg: #afb3be;
  --ppc-btn-enabled-bg: #0a1a40;
  --ppc-btn-text: #f9f5ed;

  width: 100%;
  background: #fcfbf9;
  border: 1px solid var(--ppc-border);
  border-radius: 0.55556rem;
  padding: 0.88889rem 1rem;
  display: flex;
  flex-direction: column;
}

.ppc-title-row {
  display: flex;
  align-items: center;
  gap: 0.5rem; /* 9px */
}

.ppc-bookmark-icon {
  width: 1.33333rem; /* 24px */
  height: 1.33333rem;
  color: var(--ppc-bookmark);
  flex-shrink: 0;
}

.ppc-title {
  font-family: var(--font-family-base);
  font-size: calc(0.75rem * var(--ohf-text-scale)); /* 13.5px */
  font-weight: 700;
  color: var(--ppc-title);
}

.ppc-description {
  margin: 0.22222rem 0 0 1.38889rem; /* padding-top 4px, padding-left 25px */
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale)); /* 12.5px */
  color: var(--ppc-description);
}

.ppc-form-row {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
  margin: 0.66667rem 0 0 1.38889rem; /* padding-top 12px, padding-left 25px */
}

.ppc-input {
  /* Grows to fill the row instead of sitting fixed at Figma's 445px — this
     panel is now full-width inside `.ss-scenario-group` (see the file-level
     comment above), so a fixed-width input left the same kind of dead gap
     before the Save button that the row-builder selects had before they
     were fixed to grow (see ScopeFieldSelect.css). */
  flex: 1 1 24.72222rem; /* 445px basis */
  min-width: 0;
  height: 2.27778rem; /* 41px */
  border: 1px solid var(--ppc-input-border);
  border-radius: 0.44444rem;
  background: var(--color-white);
  padding: 0.55556rem 0.66667rem;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  color: var(--ppc-title);
}

.ppc-input::placeholder {
  color: var(--ppc-input-placeholder);
}

.ppc-input:focus-visible {
  outline: none;
  border-color: var(--color-input-border-focus);
}

.ppc-input--error {
  border-color: var(--color-error, #d32f2f);
}

/* Sits under the input+button row, aligned with the input (same 25px inset the
   description and the form row use) — houses the letter-requirement error on
   the left and the character counter on the right, sharing one line rather
   than stacking (same arrangement `ScenarioDetailsCard`'s own name field
   uses). */
.ppc-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.66667rem;
  margin: 0.33333rem 0 0 1.38889rem;
}

.ppc-error {
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale));
  color: var(--color-error, #d32f2f);
}

.ppc-char-count {
  margin-left: auto;
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale));
  color: var(--ppc-description);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ppc-save-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.44444rem;
  width: 9.22222rem; /* 166px */
  height: 2.27778rem; /* 41px */
  border: none;
  border-radius: 0.22222rem;
  background: var(--ppc-btn-enabled-bg);
  color: var(--ppc-btn-text);
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 600;
  cursor: pointer;
}

.ppc-save-btn:not(:disabled):hover {
  opacity: 0.92;
}

.ppc-save-btn:disabled {
  background: var(--ppc-btn-disabled-bg);
  cursor: not-allowed;
}

.ppc-save-icon {
  width: 0.88889rem; /* 16px */
  height: 0.88889rem;
  flex-shrink: 0;
}
/* Figma (nodes 2355:120538 / 2297:117085 / 2580:6759 / 2581:7161) — no
   longer its own bordered card: this renders as a plain content section
   inside `.ss-mat-band` (StartOptimisation.css), which supplies the shared
   white/border/radius/padding chrome around it AND `MatReferenceSidebar`
   together. Used to be a standalone card (values from an older frame, node
   418:26737) — that layout is gone. */
.tsc-card {
  --tsc-title: #171f30;
  --tsc-comparison: #838996;
  --tsc-amount-border: rgba(0, 0, 0, 0.2);
  --tsc-track-bg: #e9ecf2;
  --tsc-gradient-start: #4d70b2;
  --tsc-gradient-end: #172b58;
  --tsc-thumb-border: rgba(0, 0, 0, 0.1);
  --tsc-baseline: #304d89;

  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.77778rem;
}

/* Target Spend, % Change, and the slider — Figma's own 300px/130px/868px
   column split (nodes 2355:120538 etc.), as a 3-column x 3-row GRID: label
   row, control row, caption row. Grid rather than flex specifically for the
   control row — a grid row's cells share that row's height and centre
   within it automatically, so the much-shorter slider bar lines up with
   the two 44px input boxes beside it with no hand-tuned offset to get
   wrong or drift later (a flex row of unevenly-tall columns needs exactly
   that kind of guess). Wider gaps than the 14px Figma literally measures —
   at that figure the columns read as cramped together rather than three
   distinct controls; this is a deliberate, judged deviation; adjust here if
   it should track Figma exactly instead. Empty label/caption cells (the
   `aria-hidden` spans in the TSX) keep the 3-per-row implicit grid flow
   intact for the slider column, which has neither a label above it nor a
   third caption below it in the same slot the other two columns fill. */
.tsc-grid {
  display: grid;
  grid-template-columns: 16.66667rem 7.22222rem 1fr; /* 300px / 130px / rest */
  grid-template-areas:
    "amount-label percent-label ."
    "amount-box percent-box slider"
    "amount-caption . scale";
  align-items: center;
  column-gap: 1.33333rem; /* 24px */
  row-gap: 0.44444rem;
}

/* Below this the fixed 300px/130px columns leave the slider column too
   narrow for its own scale row (min/zero/baseline/max labels start
   colliding — e.g. "-100%0%") well before the amount/percent fields
   themselves are cramped, since the slider is what absorbs the fixed
   columns' remainder. Same 64rem threshold every other section of this
   screen already restacks at (BrandsPicker, ScenarioDetailsCard,
   .ss-brands-row) — matching it keeps this card's collapse in step with
   the rest of the page rather than picking its own point. Amount/percent
   move to an even 1fr/1fr split (still side by side — narrow, not tiny)
   and the slider drops to its own full-width row below both, so its scale
   labels always get the whole card's width to spread across. */
@media (max-width: 64rem) {
  .tsc-grid {
    /* minmax(0, 1fr), not bare 1fr — a bare `fr` track's implicit min-width
       is `auto` (its content's min-content size), so the amount/percent
       boxes' nowrap currency+number text would force these tracks wider
       than the card and blow the grid out past the viewport instead of
       actually shrinking. minmax(0, 1fr) removes that floor. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "amount-label percent-label"
      "amount-box percent-box"
      "amount-caption ."
      "slider slider"
      "scale scale";
  }
}

.tsc-label--amount {
  grid-area: amount-label;
}

.tsc-label--percent {
  grid-area: percent-label;
}

/* Same treatment as the scope builder's own field labels (.sfs-label) so the
   two cards on this screen read as one form. */
.tsc-field-label {
  font-family: var(--ohf-body);
  font-size: calc(0.58333rem * var(--ohf-text-scale)); /* 10.5px */
  font-weight: 600;
  line-height: 1.21;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--tsc-comparison);
}


.tsc-amount-box {
  grid-area: amount-box;
  display: inline-flex;
  align-items: center;
  /* space-between keeps the currency pinned left and the amount right (the look
     the old `flex: 1` input gave) while the box itself grows with the number. */
  justify-content: space-between;
  gap: 0.33333rem;
  /* Fills its half of the card (see `.tsc-fields`) — the amount no longer sizes
     the box, because a fixed half-width already comfortably fits the largest
     portfolio sums and keeps the two fields symmetrical, as Figma has them. */
  width: 100%;
  height: 2.44444rem; /* 44px */
  padding: 0.22222rem 0.55556rem;
  border: 1px solid var(--tsc-amount-border);
  border-radius: 0.44444rem;
}

.tsc-amount-currency,
.tsc-amount-input {
  font-family: var(--ohf-mono);
  font-size: calc(1.55556rem * var(--ohf-text-scale));
  font-weight: 500;
  letter-spacing: -0.04rem; /* -0.64px */
  color: var(--tsc-title);
  white-space: nowrap;
}

.tsc-amount-input {
  /* Takes whatever the currency prefix leaves, so the figure stays pinned to
     the box's right edge at any width. */
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  text-align: right;
  padding: 0;
}

.tsc-amount-input:focus {
  outline: none;
}

.tsc-amount-input::placeholder {
  color: var(--tsc-amount-border);
}

/* Mirrors .tsc-amount-box's chrome exactly (same height, radius, border) so
   the two fields read as one control split in two — the "%" sits where the
   currency sits on the other, just on the trailing edge instead. */
.tsc-percent-box {
  grid-area: percent-box;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.33333rem;
  width: 100%;
  height: 2.44444rem; /* 44px */
  padding: 0.22222rem 0.55556rem;
  border: 1px solid var(--tsc-amount-border);
  border-radius: 0.44444rem;
}

.tsc-percent-input,
.tsc-percent-suffix {
  font-family: var(--ohf-mono);
  font-size: calc(1.55556rem * var(--ohf-text-scale));
  font-weight: 500;
  letter-spacing: -0.04rem;
  color: var(--tsc-title);
  white-space: nowrap;
}

.tsc-percent-input {
  /* Takes the space the "%" doesn't, so the caret starts at the left edge and
     the suffix stays pinned right however long the number gets. */
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  padding: 0;
}

.tsc-percent-input:focus {
  outline: none;
}

.tsc-percent-suffix {
  color: var(--tsc-comparison);
}

/* Read-only until a combination gives the card a MAT baseline to work from —
   see `noBaseline` in TargetSpendCard.tsx. Muted rather than hidden, so the
   card still shows the shape of what's coming. */
.tsc-amount-input:disabled,
.tsc-percent-input:disabled {
  color: var(--tsc-comparison);
  cursor: not-allowed;
}

.tsc-slider:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.tsc-slider:disabled::-webkit-slider-thumb {
  cursor: not-allowed;
}

.tsc-slider:disabled::-moz-range-thumb {
  cursor: not-allowed;
}

/* The drag tip can't be triggered without a working slider, but the hover
   growth on the thumb still reads as "this does something" — kill it. */
.tsc-slider-wrap--disabled .tsc-slider:hover::-webkit-slider-thumb,
.tsc-slider-wrap--disabled .tsc-slider:hover::-moz-range-thumb {
  transform: none;
  box-shadow: none;
}

/* Same inline-error treatment as ScenarioDetailsCard's `.sdc-name-error` —
   shown either the moment `commitAmount`/`commitPercent` (TargetSpendCard.tsx)
   clamps a typed value (transient, clears on blur), or persistently while the
   chosen amount is zero (`isZeroSpend`). */
.tsc-amount-warning {
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  color: var(--color-error, #d32f2f);
}

.tsc-sublabel {
  grid-area: amount-caption;
  font-family: var(--ohf-body);
  font-size: calc(0.69444rem * var(--ohf-text-scale)); /* 12.5px */
  color: var(--tsc-comparison);
}

/* The change from baseline, coloured by direction so it reads at a glance —
   the app's shared, contrast-checked delta pair (--color-delta-positive /
   --color-delta-negative), same as the MAT tiles and KPI cards use, rather
   than this card inventing its own green and red. `--flat` inherits the
   sublabel's muted body colour: chosen == baseline is neither up nor down. */
.tsc-delta {
  font-weight: var(--font-weight-semibold);
}

.tsc-delta--up {
  color: var(--color-delta-positive);
}

.tsc-delta--down {
  color: var(--color-delta-negative);
}

/* The separator dot, scaled up + bold so "€X" and "Y% of MAT" read as two
   clearly distinct figures rather than one run-on string. */
.tsc-sublabel-dot {
  display: inline-block;
  margin: 0 0.33333rem;
  font-size: 1.35em;
  font-weight: 700;
  line-height: 0;
  vertical-align: -0.05em;
  color: var(--tsc-title);
}

/* ── Slider drag tip ("leaf") ──
   A teardrop bubble that hangs above the thumb ONLY while the slider is
   being pushed/pulled, showing the current adjustment %. Two motion layers
   give it inertia: the positioner's `left` transition makes it trail the
   thumb like it's on a spring, and --tsc-tip-tilt (set from drag velocity in
   the TSX) leans it into the direction of travel before it swings back
   upright. Hidden from a11y (aria-hidden) — the slider's own value is
   already announced natively. */
.tsc-slider-wrap {
  grid-area: slider;
  position: relative;
}

.tsc-slider-tip {
  position: absolute;
  bottom: calc(100% + 0.44444rem);
  /* Track the thumb's real centre: fill fraction across (track − thumb),
     plus half the thumb. Matches the native thumb geometry (1.61111rem). */
  left: calc((100% - 1.61111rem) * var(--tsc-fill-frac, 0.5) + 0.80556rem);
  transform: translateX(-50%) rotate(var(--tsc-tip-tilt, 0deg)) scale(0.4);
  transform-origin: bottom center;
  opacity: 0;
  pointer-events: none;
  transition:
    left var(--motion-duration-normal) var(--motion-easing-spring),
    transform var(--motion-duration-normal) var(--motion-easing-spring),
    opacity var(--motion-duration-fast) var(--motion-easing-standard);
}

.tsc-slider-tip--visible {
  opacity: 1;
  transform: translateX(-50%) rotate(var(--tsc-tip-tilt, 0deg)) scale(1);
}

/* Teardrop: a rounded square with one sharp corner, rotated so that corner
   points down at the thumb. The text counter-rotates to stay level. */
.tsc-slider-tip-leaf {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.11111rem;
  height: 2.11111rem;
  background: linear-gradient(135deg, var(--tsc-gradient-start), var(--tsc-gradient-end));
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  box-shadow: 0 0.16667rem 0.44444rem var(--color-shadow-popover);
}

.tsc-slider-tip-text {
  transform: rotate(45deg);
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  font-weight: 700;
  color: var(--color-white);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .tsc-slider-tip {
    transition: opacity var(--motion-duration-fast) var(--motion-easing-standard);
    transform: translateX(-50%) scale(1);
  }
  .tsc-slider-tip--visible {
    transform: translateX(-50%) scale(1);
  }
}

/* ── Slider ──
   Native <input type="range"> for free keyboard support + a11y semantics.
   The filled portion is a gradient re-stretched across whatever the current
   value's width is (matching Figma's own gradient handles, which live on
   the filled sub-frame and resize with it), then flat track colour for the
   remainder — driven by the --tsc-fill custom property set inline from JS. */
/* The fill deliberately has NO transition. It used to sweep to a new position
   when the value arrived from outside the slider, but the thumb — a native
   range thumb, positioned by the input's own `value` — can't be animated with
   it, so the two came apart: typing in the amount / % change fields commits on
   every keystroke, and the thumb snapped ahead while the coloured bar crawled
   after it. Fill and thumb move together, always. */

.tsc-slider {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 0.88889rem;
  border-radius: 55.5rem;
  background: linear-gradient(
    to right,
    var(--tsc-gradient-start) 0%,
    var(--tsc-gradient-end) var(--tsc-fill, 0%),
    var(--tsc-track-bg) var(--tsc-fill, 0%),
    var(--tsc-track-bg) 100%
  );
  cursor: pointer;
  margin: 0.22222rem 0;
}

.tsc-slider::-moz-range-track {
  height: 0.88889rem;
  border-radius: 55.5rem;
  background: linear-gradient(
    to right,
    var(--tsc-gradient-start) 0%,
    var(--tsc-gradient-end) var(--tsc-fill, 0%),
    var(--tsc-track-bg) var(--tsc-fill, 0%),
    var(--tsc-track-bg) 100%
  );
}

.tsc-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 1.61111rem; /* 29px */
  height: 1.16667rem; /* 21px */
  margin-top: -0.15625rem; /* centers the 21px thumb on the 16px track */
  border-radius: 0.38889rem; /* 7px */
  background: var(--color-white);
  border: 1px solid var(--tsc-thumb-border);
  cursor: pointer;
  transition:
    transform var(--motion-duration-fast) var(--motion-easing-spring),
    box-shadow var(--motion-duration-fast) var(--motion-easing-standard);
}

.tsc-slider:hover::-webkit-slider-thumb {
  transform: scale(1.08);
  box-shadow: 0 0.11111rem 0.33333rem var(--color-shadow-card-lg);
}

.tsc-slider:active::-webkit-slider-thumb {
  transform: scale(1.15);
  box-shadow: 0 0.16667rem 0.44444rem var(--color-shadow-card-lg);
}

.tsc-slider::-moz-range-thumb {
  width: 1.61111rem;
  height: 1.16667rem;
  border-radius: 0.38889rem;
  background: var(--color-white);
  border: 1px solid var(--tsc-thumb-border);
  cursor: pointer;
  transition:
    transform var(--motion-duration-fast) var(--motion-easing-spring),
    box-shadow var(--motion-duration-fast) var(--motion-easing-standard);
}

.tsc-slider:hover::-moz-range-thumb {
  transform: scale(1.08);
  box-shadow: 0 0.11111rem 0.33333rem var(--color-shadow-card-lg);
}

.tsc-slider:active::-moz-range-thumb {
  transform: scale(1.15);
  box-shadow: 0 0.16667rem 0.44444rem var(--color-shadow-card-lg);
}

@media (prefers-reduced-motion: reduce) {
  .tsc-slider,
  .tsc-slider::-webkit-slider-thumb,
  .tsc-slider::-moz-range-thumb {
    transition: none;
  }
  .tsc-slider:hover::-webkit-slider-thumb,
  .tsc-slider:active::-webkit-slider-thumb,
  .tsc-slider:hover::-moz-range-thumb,
  .tsc-slider:active::-moz-range-thumb {
    transform: none;
  }
}

.tsc-slider:focus-visible {
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 2px;
}

/* ── Scale row ── */
.tsc-scale {
  grid-area: scale;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Below the 64rem breakpoint this sits under a full-width slider rather
     than a narrow leftover column, so min/zero/baseline/max always have
     the whole card's width to spread across — the collision this whole
     breakpoint exists to fix. */
  gap: 0.44444rem;
}

.tsc-scale-min,
.tsc-scale-max {
  font-family: var(--ohf-body);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  color: var(--tsc-comparison);
}

.tsc-scale-center {
  display: flex;
  align-items: center;
  gap: 0.66667rem;
}

.tsc-scale-zero {
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  color: var(--tsc-comparison);
}

.tsc-scale-baseline {
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  font-weight: 500;
  color: var(--tsc-baseline);
}
/* Palette scoped to the tile (values from Figma node 418:26737). */
.mrt-tile {
  /* Transparent, NOT #f2f2f2. Figma carries an #f2f2f2 fill on these tiles but
     it is switched OFF (`visible: false`), so the white card shows through and
     only the hairline border defines the tile. Reading the paint without its
     visible flag is what made these render grey. */
  --mrt-border: rgba(0, 0, 0, 0.1);
  --mrt-label: #6a7693;
  --mrt-value: #001f82;
  --mrt-up: #0fa870;
  /* "down" isn't in the Figma sample data (every tile shown is +8.7%) — reuse
     the app's shared danger token rather than inventing a new hardcoded hex
     for a state the design file never renders. */
  --mrt-down: var(--color-danger);

  /* No fixed width: the tile sizes to its grid column (.mrs-grid is
     repeat(2, 1fr)). Figma's 125px is (262 - 12) / 2 — half the row, not a
     width. Pinning it worked only because the sidebar is a fixed 308px; the
     same value taken literally in the Import modal made its four tiles overflow
     and wrap. */
  min-width: 0;
  height: 5rem; /* 90px */
  background: transparent;
  border: 1px solid var(--mrt-border);
  border-radius: 0.66667rem;
  padding: 0.55556rem;
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
}

.mrt-tile-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.44444rem;
}

.mrt-tile-label {
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 500;
  color: var(--mrt-label);
}

/* Scope the shared InfoButton to Figma's glyph size/colour without touching
   the component's own defaults (14px, --color-text-placeholder). */
.mrt-tile-info {
  color: var(--mrt-label);
}

.mrt-tile-info:hover {
  color: var(--mrt-value);
}

.mrt-tile-info .ib-icon {
  width: 0.73889rem; /* 13.3px */
  height: 0.73889rem;
}

.mrt-tile-value {
  font-family: var(--font-family-base);
  font-size: calc(1rem * var(--ohf-text-scale));
  font-weight: 600;
  color: var(--mrt-value);
}

.mrt-tile-trend {
  display: flex;
  align-items: center;
  gap: 0.22222rem;
}

.mrt-tile-trend-icon {
  width: 0.73889rem; /* 13.3px */
  height: 0.48333rem; /* 8.7px */
  flex-shrink: 0;
}

.mrt-tile-trend-delta {
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
}

.mrt-tile-trend--up .mrt-tile-trend-icon,
.mrt-tile-trend--up .mrt-tile-trend-delta {
  color: var(--mrt-up);
}

/* Icon is authored pointing up; flip it to point down rather than shipping a
   second glyph, and swap the shared danger colour in for both icon and text. */
.mrt-tile-trend--down .mrt-tile-trend-icon {
  transform: scaleY(-1);
}

.mrt-tile-trend--down .mrt-tile-trend-icon,
.mrt-tile-trend--down .mrt-tile-trend-delta {
  color: var(--mrt-down);
}
/* Figma (nodes 2355:120538 / 2297:117085 / 2580:6759 / 2581:7161) — no
   longer its own bordered card: this renders as a plain content section
   inside `.ss-mat-band` (StartOptimisation.css), which supplies the shared
   white/border/radius/padding chrome around it AND `TargetSpendCard`
   together. Used to be a standalone 308px right-hand sidebar card (values
   from an older frame, node 418:26737) — that layout is gone. */
.mrs-card {
  --mrs-heading: #171f30;
  --mrs-period: #838996;
  --mrs-muted: #838996;

  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.22222rem;
}

/* ── Refetch scrim ── Same "keep old data, dim it" treatment as the
   Comparison screen's `.cmp-results-scrim`, sized down for this fixed-height
   sidebar card — no sticky positioning needed since the whole card is always
   in view (unlike that screen's long, scrollable results region). */
.mrs-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  background: color-mix(in srgb, var(--color-white) 68%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
}

.mrs-scrim .chart-loader {
  height: auto;
  min-height: 0;
}

.mrs-heading {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.88889rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.366;
  color: var(--mrs-heading);
}

.mrs-period {
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  color: var(--mrs-period);
}

/* One row, not a 2-column stack (Figma's redesign lays every tile out
   horizontally — see the file-level comment above). Flexbox with each tile
   at `flex: 1 1 0`, not a fixed `repeat(6, 1fr)` grid — the backend only
   implements 4 of Figma's 6 tiles today (`_MAT_TILE_METRIC_KEYS` in
   optimisation_scope_setup.py has no mroi/market_share yet), and a 6-column
   grid with 4 real children left 2 columns' worth of dead white space on the
   right. Flexbox spreads however many tiles actually exist across the full
   width, and picks up MROI/Market Share automatically the day the backend
   adds them — no CSS change needed then. */
.mrs-grid {
  display: flex;
  gap: 0.66667rem;
  padding: 0.66667rem 0;
}

/* Each tile grows/shrinks equally to fill the row, whatever the tile count. */
.mrs-grid > * {
  flex: 1 1 0;
  min-width: 0;
}

/* Same diamond+bolt treatment as ScenarioEmptyState's "Your Scenario" empty
   state (Figma node 418:23991), scaled down (~0.71x) to fit this narrower
   sidebar card — same proportions (inner/outer, icon/outer, radius/outer
   ratios) as ScenarioEmptyState.css, just smaller. */
.mrs-mat-empty {
  margin: 0.44444rem 0;
  padding: 0.88889rem 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.66667rem;
}

.mrs-mat-empty-diamond {
  width: 2.44444rem; /* 44px */
  height: 2.44444rem;
  flex-shrink: 0;
  border: 1.5px solid var(--ses-diamond-stroke, #758bbc);
  border-radius: 0.72222rem; /* 13px, pre-rotation */
  transform: rotate(45deg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.mrs-mat-empty-diamond-inner {
  width: 1.69444rem; /* 30.5px */
  height: 1.69444rem;
  border-radius: 0.55556rem; /* 10px */
  background: var(--ses-diamond-fill, rgba(200, 211, 232, 0.6));
  transform: rotate(-45deg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.mrs-mat-empty-bolt-icon {
  width: 0.61111rem; /* 11px */
  height: 0.61111rem;
  color: var(--ses-bolt, rgba(68, 101, 162, 0.9));
}

.mrs-mat-empty-message {
  margin: 0;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale)); /* 13px */
  line-height: 1.45;
  color: var(--mrs-muted);
  text-align: center;
}
/* Card for a single importable scenario/portfolio inside ImportScenarioModal.
   Values from Figma file UhXM9FKphZVFcmOL5CeMpr — collapsed/expanded Single
   Cell row: node 2142:109719 ("All scenarios + portfolio") / 2357:121076
   ("deep dive single scenario"); Portfolio row: node 2142:109719; drill-in
   list: node 2351:119107. Relies on --ohf-body/--ohf-text-scale, already
   declared on the portalled .ism-dialog ancestor (see
   ImportScenarioModal.css). */
.ism-card {
  --ism-border: #e1e5eb;
  --ism-border-expanded: rgba(26, 39, 68, 0.3);
  --ism-name: #171f30;
  --ism-desc: #505869;
  /* Single Cell badge — rgba(19,96,190,0.2) / rgba(0,95,193,1). */
  --ism-badge-single-bg: rgba(19, 96, 190, 0.2);
  --ism-badge-single-text: #005fc1;
  /* Portfolio badge — rgba(252,235,204,1) / rgba(159,103,0,1). */
  --ism-badge-portfolio-bg: #fcebcc;
  --ism-badge-portfolio-text: #9f6700;
  --ism-chip-bg: #eff2f7;
  --ism-chip-border: #d6dbe4;
  --ism-chip-label: #838996;
  --ism-chip-value: #505869;
  --ism-kpi-border: rgba(0, 0, 0, 0.1);
  --ism-kpi-label: #6a7693;
  --ism-kpi-value: #001f82;
  --ism-kpi-up: #0fa870;
  --ism-kpi-down: var(--color-danger);
  --ism-kpi-flat: #8b8b8b;
  --ism-summary-title: #222222;
  --ism-summary-meta: #6a7693;
  --ism-toggle-text: #0068d3; /* rgba(0,104,211,1) — "Show more"/"Show less" */
  --ism-btn-border: #b1b8c5;
  --ism-btn-text: #0a1a40;

  background: var(--color-white);
  border: 1px solid var(--ism-border);
  border-radius: 0.66667rem; /* 12px */
  display: flex;
  flex-direction: column;
  /* `.ism-list` (the card list, see ImportScenarioModal.css) is itself a
     column flex container with NO explicit width on its cards — they rely on
     `align-items: stretch` to fill it. Stretch alone is not a hard cap: a
     flex item's cross-size can still be pushed past the stretched size by
     its own content's automatic minimum width, so this needs an EXPLICIT
     `width`/`max-width` (not just relying on stretch) plus `min-width: 0` to
     opt out of that automatic minimum entirely — belt-and-suspenders on top
     of the same `min-width: 0` chain below (`.ism-card-header` →
     `.ism-card-top` → `.ism-card-name-group` → `.ism-card-name`), so however
     long the scenario name is, this card's own footprint is always exactly
     `.ism-list`'s width, never wider. */
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

.ism-card--expanded {
  border-color: var(--ism-border-expanded);
}

/* ── Header (name/badge/action, description, chips, expand toggle) —
   identical content whether the card is collapsed or expanded. ── */
.ism-card-header {
  padding: 0.88889rem 1.33333rem; /* 16px 24px */
  display: flex;
  flex-direction: column;
  gap: 0.38889rem; /* 7px */
  /* Part of the same min-width chain as `.ism-card` above — a flex item of
     `.ism-card` (column), and itself a flex container for `.ism-card-top`
     (row) below. */
  min-width: 0;
}

.ism-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.55556rem; /* 10px */
  /* Without this, a long, unbreakable `.ism-card-name` can force this row —
     and with it the whole card — wider than the list/dialog, since a flex
     item's default `min-width: auto` only shrinks to fit an ancestor's
     available space up to its own content's natural size. `min-width: 0`
     here (and on `.ism-card-name-group`/`.ism-card-name` below) removes that
     floor so the name is the one that truncates instead of the card growing. */
  min-width: 0;
}

.ism-card-name-group {
  display: flex;
  align-items: center;
  gap: 0.88889rem; /* 16px */
  min-width: 0;
}

.ism-card-name {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.80556rem * var(--ohf-text-scale)); /* 14.5px */
  font-weight: 700;
  line-height: 1.366;
  color: var(--ism-name);
  /* The name text itself is the actual flex item whose intrinsic min-width
     (driven by `.ism-card-name-clip`'s `white-space: nowrap` below, i.e. it
     can never wrap to shrink) is otherwise the thing that forces
     `.ism-card-name-group`/`.ism-card-top`/`.ism-card` wider for a long
     scenario name — see `.ism-card-top`'s comment above. This is the one
     that actually matters: the badge (`.ism-badge`, `flex-shrink: 0`) and the
     action button already keep their own size, so this is the only element
     that should give up width. */
  min-width: 0;
}

/* The `HoverTooltip` anchor wrapping the name text — the clip properties live
   here rather than on `.ism-card-name` itself because `HoverTooltip` measures
   ITS OWN anchor span to decide whether the text is actually clipped
   (`showWhen="clipped-x"`); putting them one level up would let the anchor
   report its full, unclipped intrinsic width and the tooltip would never
   open. `width: 100%` fills `.ism-card-name`'s own (flex-shrunk) box so
   there is something definite to clip against. */
.ism-card-name-clip {
  display: block;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ism-badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.33333rem 0.55556rem; /* Figma's 10px on all sides reads as oversized for
                                  a 29px-tall badge at 12px text; trimmed vertically
                                  to what the box height actually allows. */
  border-radius: 0.88889rem; /* 16px */
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale)); /* 12px */
  font-weight: 500;
  line-height: 1.5625;
  white-space: nowrap;
}

.ism-badge--single-cell {
  background: var(--ism-badge-single-bg);
  color: var(--ism-badge-single-text);
}

.ism-badge--portfolio {
  background: var(--ism-badge-portfolio-bg);
  color: var(--ism-badge-portfolio-text);
}

.ism-description {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale)); /* 13px */
  color: var(--ism-desc);
  line-height: 1.5;
}

/* The `HoverTooltip` anchor wrapping the description text — same reasoning as
   `.ism-card-name-clip` above, but clamped on the vertical axis: a scenario
   description can run up to 200 chars (`SCENARIO_DESCRIPTION_MAX_LENGTH`),
   long enough to wrap well past this card's usual height. 2-line clamp
   matches `OptimizationCard`'s own `.oc-card--compact .oc-description`;
   `showWhen="clipped-y"` only opens the tooltip once `scrollHeight` actually
   exceeds `clientHeight`. */
.ism-description-clip {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Meta chips — same visual pattern as OptimizationCard's .oc-chip,
   duplicated locally per this feature's standalone-modal convention. ── */
.ism-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
}

.ism-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.22222rem;
  padding: 0.17778rem var(--space-sm);
  border: 1px solid var(--ism-chip-border);
  border-radius: 0.33333rem;
  background: var(--ism-chip-bg);
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale)); /* 11px */
  line-height: 1.366;
  white-space: nowrap;
}

/* The scope chip carries a hover tooltip listing every combination the
   scenario spans (see `scopeCellsTooltip`) — `help` marks it as having more
   behind it, since a chip is otherwise inert. */
.ism-chip--detailed {
  cursor: help;
}

.ism-chip-label {
  color: var(--ism-chip-label);
}

.ism-chip-value {
  color: var(--ism-chip-value);
}

/* The card's only expand/collapse control (Single Cell rows only) — same
   button relocates between the collapsed header (below the chips) and the
   expanded panel (end of the Scope and Constraints Summary), always
   right-aligned. Figma node 2142:109719 (collapsed, "Show more") /
   2357:121076 (expanded, "Show less"). */
.ism-toggle {
  display: inline-flex;
  align-items: center;
  align-self: flex-end;
  gap: 0.27778rem; /* 5px */
  border: none;
  background: transparent;
  padding: 0;
  margin: 0;
  color: var(--ism-toggle-text);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale)); /* 12px */
  font-weight: 500;
  line-height: 1.625;
  cursor: pointer;
}

.ism-toggle-icon {
  width: 0.55556rem; /* 10px */
  height: 0.33333rem; /* 6px */
  color: var(--ism-toggle-text);
  transition: transform var(--motion-duration-fast) var(--motion-easing-standard);
}

.ism-toggle-icon--open {
  transform: rotate(180deg);
}

/* ── Expanded panel: KPI tiles + Scope and Constraints Summary — no footer,
   no separate Import button here (Import/View Scenarios live in the header
   above, always visible). Top padding is asymmetric (28px vs 16px on the
   other 3 sides) — extra breathing room between the collapsed header band
   above and the panel's own content starting, per Figma node 2357:121076.
   No single `gap` on the panel: the KPI row needs specifically 28px before
   the summary block, a value only the KPI row's own margin can express (see
   `.ism-kpis`/`.ism-kpis-state` below). */
.ism-card-panel {
  border-top: 1px solid var(--ism-border-expanded);
  padding: 1.55556rem 0.88889rem 0.88889rem; /* 28px 16px 16px 16px */
  display: flex;
  flex-direction: column;
}

/* Four equal columns, always one row. Figma's 263.5px tile is not a fixed width
   — it is exactly (1090 - 3*12) / 4, i.e. a quarter of the row. Taken literally
   as a width, the four tiles needed 1090px inside a 1074px card, so MROI wrapped
   to a second row and left the rest of it empty. */
.ism-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.66667rem; /* 12px */
  margin-bottom: 1.55556rem; /* 28px, KPI row -> Scope and Constraints Summary */
}

/* Fetched lazily on first expand (see ImportScenarioCard's `kpis` state) —
   reserves the same height as the loaded tile row so the panel doesn't jump
   once the fetch resolves. */
.ism-kpis-state {
  min-height: 5rem; /* matches .ism-kpi-tile's own height */
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.55556rem; /* 28px, same as .ism-kpis above */
}

/* Transparent fill is deliberate — matches the MAT reference sidebar's
   .mrt-tile, which documents the same "Figma's #f2f2f2 fill is switched off"
   finding for this exact tile design. */
.ism-kpi-tile {
  /* Width comes from the grid column (see .ism-kpis) — no fixed width. */
  min-width: 0;
  height: 5rem; /* 90px */
  background: transparent;
  border: 1px solid var(--ism-kpi-border);
  border-radius: 0.66667rem; /* 12px */
  padding: 0.55556rem; /* 10px */
  display: flex;
  flex-direction: column;
  gap: 0.44444rem; /* 8px */
}

.ism-kpi-label {
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale)); /* 12px */
  font-weight: 500;
  color: var(--ism-kpi-label);
}

.ism-kpi-value {
  font-family: var(--font-family-base);
  font-size: calc(1rem * var(--ohf-text-scale)); /* 18px */
  font-weight: 600;
  color: var(--ism-kpi-value);
}

.ism-kpi-trend {
  display: flex;
  align-items: center;
  gap: 0.22222rem;
}

.ism-kpi-trend-icon {
  width: 0.73889rem; /* 13.3px */
  height: 0.48333rem; /* 8.7px */
  flex-shrink: 0;
}

.ism-kpi-trend-delta {
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale)); /* 12px */
  font-weight: 600;
}

.ism-kpi-trend--up .ism-kpi-trend-icon,
.ism-kpi-trend--up .ism-kpi-trend-delta {
  color: var(--ism-kpi-up);
}

/* Icon is authored pointing up; flip it for "down" rather than shipping a
   second glyph — same convention as .mrt-tile-trend--down. */
.ism-kpi-trend--down .ism-kpi-trend-icon {
  transform: scaleY(-1);
}

.ism-kpi-trend--down .ism-kpi-trend-icon,
.ism-kpi-trend--down .ism-kpi-trend-delta {
  color: var(--ism-kpi-down);
}

/* No MAT baseline to diff against (e.g. MROI, or a scope the MAT lookup
   couldn't resolve) — neutral grey, same "flat" convention as the Results
   screen's own .or-delta--flat. */
.ism-kpi-trend--flat .ism-kpi-trend-icon,
.ism-kpi-trend--flat .ism-kpi-trend-delta {
  color: var(--ism-kpi-flat);
}

.ism-summary {
  display: flex;
  flex-direction: column;
  gap: 0.88889rem; /* 16px */
}

.ism-summary-title {
  margin: 0;
  font-family: var(--font-family-base);
  font-size: calc(0.88889rem * var(--ohf-text-scale)); /* 16px */
  font-weight: 500;
  color: var(--ism-summary-title);
}

.ism-summary-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.44444rem; /* 8px */
  font-family: var(--font-family-base);
  font-size: calc(0.77778rem * var(--ohf-text-scale)); /* 14px */
  font-weight: 500;
  color: var(--ism-summary-meta);
}

/* Header action button — "Import" (Single Cell) or "View Scenarios"
   (Portfolio), always visible via .ism-card-top's space-between, never
   gated behind expanding the card. Auto width (not a fixed size): "View
   Scenarios" is meaningfully wider than "Import" and both need to fit their
   text without truncating. */
.ism-action-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 1.83333rem; /* 33px */
  padding: 0.38889rem 0.72222rem; /* 7px 13px */
  background: var(--color-white);
  border: 1px solid var(--ism-btn-border);
  border-radius: 0.33333rem; /* 6px */
  color: var(--ism-btn-text);
  font-family: var(--ohf-button);
  font-size: calc(0.77778rem * var(--ohf-text-scale)); /* 14px */
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}

.ism-action-btn:hover {
  background: var(--color-bg-hover-light);
}
/* The dialog shell (backdrop/header/filters/list chrome) below is
   INTENTIONALLY duplicated from RecentOptimizationsModal.css — same
   container, header band, filters row and list padding, per an explicit
   product decision to keep this modal standalone rather than refactor a
   load-bearing, already-tested component. If the shell changes, change it
   in BOTH files. */

.ism-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--color-backdrop-overlay);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-xl) var(--space-lg);
  overflow-y: auto;
}

.ism-dialog {
  /* Declared here, not inherited: this dialog is portalled to document.body,
     so it is NOT a descendant of .ss-page and would otherwise fall back to
     the :root default of 1 — see the identical trap documented on
     .rom-dialog in RecentOptimizationsModal.css. */
  --ohf-text-scale: 1;
  /* Same portal trap for the Import button's font-family — see the
     --ohf-button definition (and its own "design file's own inconsistency"
     comment) on .oh-page in OptimisationHome.css. */
  --ohf-button: Arial, Helvetica, sans-serif;

  --ism-heading: #171f30;
  --ism-band-border: #cfd4df;
  --ism-search-placeholder: #757575;
  --ism-surface: #f6f6f9;
  /* Same value as RecentOptimizationsModal's --rom-pill-border; this modal
     has no status pills of its own, but the load-more fallback button
     borrows the same hairline treatment. */
  --ism-pill-border: rgba(0, 0, 0, 0.08);
  /* Type tabs (Show All / Single cell / Portfolio) — identical text colour
     for both the active and inactive pill, only the fill differs. */
  --ism-tab-text: #677494;
  --ism-tab-active-bg: rgba(0, 84, 216, 0.06);

  background: #f6f6f9;
  border-radius: 0.88889rem;
  overflow: hidden;
  box-shadow: 0 12px 40px var(--color-shadow-modal-lg);
  width: min(65.44444rem, 100%);
  margin: auto;
  display: flex;
  flex-direction: column;
  /* Fixed shell height, NOT content-driven — same rule as .rom-dialog/.vpm-dialog.
     Sizing to the content made the dialog resize under the user's cursor every
     time the filters or the search term changed the result count (20 cards ->
     full height, 2 cards -> roughly a third of it), and a short dialog then
     clipped an open filter panel against the `overflow: hidden` above. The list
     scrolls inside a stable shell instead; the vh term only kicks in on short
     viewports, where it is the same cap the old max-height applied. */
  height: min(43.33333rem, calc(100vh - 2 * var(--space-xl)));
}

/* ── Header ── */
.ism-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  background: var(--color-white);
  border-bottom: 1px solid var(--ism-band-border);
  padding: 1.33333rem 1.55556rem 0.94444rem;
}

.ism-title {
  margin: 0;
  font-family: var(--ohf-body);
  font-size: calc(1.11111rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.366;
  color: var(--ism-heading);
}

.ism-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.33333rem;
  height: 1.33333rem;
  border: none;
  background: transparent;
  color: #1c1b1f;
  border-radius: var(--radius-input);
  cursor: pointer;
}

.ism-close:hover {
  background: var(--color-bg-hover-light);
}

.ism-close-icon {
  width: 0.55556rem;
  height: 0.55556rem;
}

/* ── Filters row ── */
.ism-filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.88889rem;
  padding: 0.66667rem 1.55556rem 1.11111rem;
  background: var(--ism-surface);
  position: relative;
  z-index: 2;
}

.ism-filter-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.88889rem;
}

.ism-select {
  flex: 0 0 7.88889rem;
  width: 7.88889rem;
}

/* Restyle this MultiSelectDropdown instance to match Figma's filter-dropdown
   look — identical override to .rom-select, scoped locally. */
.ism-select.msd-wrap {
  border: none;
  border-radius: 0;
  width: 100%;
  align-items: stretch;
}

.ism-select .msd-label {
  position: static;
  background: none;
  padding: 0;
  margin-bottom: 0.33333rem;
  font-family: var(--font-family-base);
  font-weight: 600;
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  line-height: 1.209;
  color: #6b6e76;
}

.ism-select .msd-trigger {
  width: 100%;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 0.44444rem;
  background: var(--color-white);
  padding: 0.5rem;
}

.ism-select .msd-value {
  font-family: var(--font-family-base);
  font-weight: 500;
  font-size: calc(0.58333rem * var(--ohf-text-scale));
  line-height: 1.21;
  color: #9a9ca2;
}

.ism-select .msd-value--placeholder {
  color: #9a9ca2;
}

.ism-select .msd-chevron {
  color: #9a9ca2;
}

.ism-select .msd-chevron-icon {
  width: 0.44444rem;
  height: 0.27778rem;
}

.ism-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 0 13.61111rem;
  margin-top: 0.88889rem;
}

.ism-search-icon {
  position: absolute;
  left: 0.61111rem;
  top: 50%;
  transform: translateY(-50%);
  width: 0.77778rem;
  height: 0.77778rem;
  color: #828a96;
  pointer-events: none;
}

.ism-search-input {
  width: 100%;
  height: 2.11111rem;
  /* Right padding clears the × (see SearchClearButton), which overlays this
     field's right edge. */
  padding: 0 1.83333rem 0 1.83333rem;
  border: 1px solid rgba(177, 184, 197, 0.4);
  border-radius: 0.44444rem;
  background: var(--color-white);
  color: var(--color-text-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale));
  line-height: 1.369;
  font-family: var(--ohf-body);
}

.ism-search-input::placeholder {
  color: var(--ism-search-placeholder);
}

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

/* ── Type tabs (Show All / Single cell / Portfolio) — Figma node
   2358:121695, "Frame 2043684311". Visual only for now, see `activeTab`'s
   own doc comment in ImportScenarioModal.tsx: selecting a tab highlights it
   but does not yet filter `.ism-list` below. ── */
.ism-tabs {
  display: flex;
  gap: 0.66667rem; /* 12px */
  padding: 0 1.55556rem 0.66667rem;
  background: var(--ism-surface);
}

.ism-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.33333rem 0.77778rem; /* 6px 14px */
  border: 1px solid var(--ism-pill-border);
  border-radius: 0.88889rem; /* 16px */
  background: var(--color-white);
  color: var(--ism-tab-text);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale)); /* 12px */
  font-weight: 600;
  line-height: 1.5625;
  white-space: nowrap;
  cursor: pointer;
}

/* Same text colour as the inactive pill — only the fill changes. */
.ism-tab--active {
  background: var(--ism-tab-active-bg);
}

/* ── Scenario list ── */
.ism-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  flex: 1 1 auto;
  min-height: 0;
  /* Same automatic-minimum-width concern as `.ism-card`'s own doc comment
     (ImportScenarioCard.css): this is itself a flex item of `.ism-dialog`
     (column), stretched to the dialog's fixed `width: min(65.44444rem,
     100%)` — `min-width: 0` opts it out of being pushed past that by a
     long-named card underneath, closing the last link in the chain from the
     dialog edge down to `.ism-card-name`. */
  min-width: 0;
  overflow-y: auto;
  padding: 0 1.55556rem 1.55556rem;
  transition: opacity var(--motion-duration-fast) var(--motion-easing-standard);
}

.ism-list--refreshing {
  opacity: 0.5;
  transition-delay: 180ms;
}

.ism-list-state {
  flex: 1;
  min-height: 14.22222rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

@media (prefers-reduced-motion: reduce) {
  .ism-list {
    transition: none;
  }
}

.ism-empty {
  text-align: center;
  color: var(--color-text-muted);
  font-size: calc(var(--font-size-sm) * var(--ohf-text-scale));
  padding: var(--space-xxl) 0;
  /* Centres the message in the now fixed-height list area — see the matching
     rule on .rom-empty. */
  margin: auto;
}

/* ── Infinite scroll sentinel + inline loading row — identical to
   RecentOptimizationsModal's .rom-sentinel/.rom-loading-more; the sentinel
   is an in-flow marker at the end of the scrollable list (observed via
   IntersectionObserver rooted on .ism-list), not a pinned footer. ── */
.ism-sentinel {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: var(--space-xl);
  padding-top: var(--space-xs);
}

.ism-loading-more {
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
}

/* Persistent, silent status region — announces load-more results to screen
   readers without any visible layout footprint. */
.ism-live-region {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Keyboard/screen-reader fallback for infinite scroll: hidden off-screen by
   default (same sr-only technique as .ism-live-region), but becomes a
   normal visible, focusable button the moment it receives keyboard focus. */
.ism-load-more-fallback {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 1px solid var(--ism-pill-border);
  background: var(--color-white);
  color: var(--color-text-muted);
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
  border-radius: 0.88889rem;
  cursor: pointer;
}

.ism-load-more-fallback:focus {
  position: static;
  display: block;
  width: auto;
  height: auto;
  margin: var(--space-sm) auto 0;
  overflow: visible;
  clip: auto;
  white-space: normal;
  padding: 0.38889rem 1.11111rem;
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 2px;
}

.ism-load-more-fallback:disabled {
  cursor: not-allowed;
}
/* Palette scoped to the "Scope setup" screen (values from Figma, node
   418:26737). Locally scoped custom properties, declared again here rather
   than inherited from OptimisationHome.css — this is a separate page. */
.ss-page {
  /* Uniform type scale for this whole screen. Every font-size on it is written
     as its exact Figma pixel value x this factor, so the Figma hierarchy and
     ratios are preserved and the deviation is one number, not 49 edits.
     1 = exactly Figma. 0.95 = the 5% reduction asked for; raise or lower here. */
  --ohf-text-scale: 1;

  --ss-bg: #f6f6f9;
  --ss-back-icon: #838996;
  --ss-back-text: #6b717d;
  --ss-eyebrow: #213b6e;
  --ss-heading: #171f30;
  --ss-cta-border: #b1b8c5;
  --ss-cta-text: #0a1a40;
  --ss-cta-primary-bg: #0a1a40;
  --ss-cta-primary-text: #f9f5ed;
  /* Same faded-navy disabled treatment as this screen's other primary CTA
     (`.sct-add-row-btn` in ScopeCombinationTable.css, `--sct-add-bg`) — the
     row builder's "Add" button is navy-at-35%-opacity until its combination is
     complete, so the "Set Constraints" CTA reuses that exact figure while
     it has nothing to act on (`totalRows === 0`). */
  --ss-cta-primary-bg-disabled: rgba(26, 39, 68, 0.35);

  min-height: 100vh;
  padding-top: var(--space-10);
  background: var(--ss-bg);
}

.ss-loader,
.ss-error {
  padding: var(--space-xxl) var(--space-xl);
}

/* Same 1360px content column as OptimisationHome.css (1440px page, 40px
   side padding). */
.ss-body {
  max-width: 80rem;
  margin: 0 auto;
  padding: 1.66667rem 2.22222rem 2.66667rem;
  display: flex;
  flex-direction: column;
  gap: 0.88889rem;
}

/* ── Back link ── */
.ss-back {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.33333rem;
  border: none;
  background: transparent;
  padding: 0;
  color: var(--ss-back-text);
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.366;
  cursor: pointer;
  transition: color var(--motion-duration-fast) var(--motion-easing-standard);
}

.ss-back:hover,
.ss-back:hover .ss-back-icon {
  color: var(--ss-heading);
}

.ss-back-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  color: var(--ss-back-icon);
  flex-shrink: 0;
}

/* ── Title row ── */
.ss-title-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.33333rem;
  flex-wrap: wrap;
}

.ss-title-group {
  display: flex;
  flex-direction: column;
  gap: 0.33333rem;
}

.ss-eyebrow {
  font-family: var(--ohf-body);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.366;
  letter-spacing: 0.08rem; /* 1.44px */
  color: var(--ss-eyebrow);
}

.ss-title {
  margin: 0;
  font-family: var(--ohf-heading);
  font-size: calc(1.33333rem * var(--ohf-text-scale));
  font-weight: 500;
  line-height: 1.445;
  letter-spacing: -0.031875rem; /* -0.51px */
  color: var(--ss-heading);
}

.ss-title-actions {
  display: flex;
  align-items: center;
  gap: 1.33333rem;
}

.ss-import-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.44444rem;
  width: 6.11111rem; /* 110px */
  height: 2.22222rem;
  border: 1px solid var(--ss-cta-border);
  border-radius: 0.22222rem;
  background: var(--color-white);
  color: var(--ss-cta-text);
  font-family: Arial, Helvetica, sans-serif;
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 700;
  cursor: pointer;
}

.ss-import-btn:hover {
  background: var(--color-bg-hover-light);
}

.ss-import-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  flex-shrink: 0;
}

.ss-constraints-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.44444rem;
  width: 9.88889rem; /* 178px */
  height: 2.27778rem; /* 41px */
  border: none;
  border-radius: 0.22222rem;
  background: var(--ss-cta-primary-bg);
  color: var(--ss-cta-primary-text);
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 600;
  cursor: pointer;
}

.ss-constraints-btn:not(:disabled):hover {
  opacity: 0.92;
}

.ss-constraints-btn:disabled {
  background: var(--ss-cta-primary-bg-disabled);
  cursor: not-allowed;
}

.ss-constraints-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  flex-shrink: 0;
}

/* ── Body stack: scenario details, MAT reference + target spend, then
   Brands/Your Scenario — all full-width, one column (Figma nodes
   2355:120538 / 2297:117085 / 2580:6759 / 2581:7161). MAT reference used to
   be a 308px right-hand sidebar beside a narrower main column (that layout
   came from an older Figma frame, 418:26737) — the redesign drops the
   sidebar entirely, so every section here gets the full 1360px row width. */
.ss-row {
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
  padding-top: 0.44444rem;
}

/* MAT reference + Target spend are two separate components/data sources,
   but Figma renders them as ONE card (2580:6759 etc.) — this wrapper
   supplies the shared white/border/radius/padding chrome; both children
   drop their own (see MatReferenceSidebar.css / TargetSpendCard.css). */
.ss-mat-band {
  background: var(--color-white);
  border: 1px solid var(--color-scenario-group-border);
  border-radius: 0.66667rem;
  padding: 1.11111rem 1.22222rem;
  display: flex;
  flex-direction: column;
  gap: 0.88889rem;
}

/* `stretch`, not `flex-start`: the two columns are one visual row and their
   bottoms have to line up. Whichever side is taller sets the height — the
   Brands card grows with however many brands it holds (up to the shared 487px
   ceiling), and "Your Scenario" fills that same height rather than stopping
   short, including in its empty state. Previously each sized itself
   independently, so the Brands list ran well past the bottom of the scenario
   card whenever the brand list was long or the scenario empty. */
.ss-brands-row {
  display: flex;
  align-items: stretch;
  gap: 0.88889rem;
}

/* Fixed at Figma's own ~487px column height (node 2580:6759: Brands
   280x487, "Your Scenario" 1064x469 — close enough to treat as one shared
   figure, since `align-items: stretch` on `.ss-brands-row` forces both to
   match anyway) so adding combinations scrolls inside the column instead of
   growing the page — see BrandsPicker.css for the matching treatment on the
   Brands card. Any gap the column needs above its own content must live
   OUTSIDE this element (e.g. as margin/padding on a sibling), never as this
   element's own top padding: padding on a scroll container scrolls away
   with the content the moment the user scrolls past it, leaving zero
   clearance — the exact bug already fixed once in BrandsPicker.css.

   This used to be a flat 609px, guessed before MAT reference moved out of
   being a sidebar (see `.ss-mat-band`) — nothing ever confirmed that number
   against Figma's real data, and it was noticeably taller than the actual
   frames: harmless-looking when a tall sidebar sat next to it, but a
   conspicuously oversized void around the empty-state icon once this row
   stood alone. 487px is what Figma's own frame actually measures. */
.ss-scenario-col {
  /* Basis 0, not auto: with auto, this item's "fair share" of the row was
     computed from its CONTENT's natural width (the row-builder's 4 selects
     etc.) rather than the space actually available, so it over-claimed room
     and shrank `.bp-card` down to its 220px floor even at the full 1360px
     row width where everything should fit exactly (280 + 16 gap + 1064).
     Basis 0 makes it purely "grow to fill whatever's left after Brands'
     fixed basis," which is what Figma's fixed 280/1064 split actually is. */
  flex: 1 1 0;
  min-width: 0;
  height: 27.05556rem; /* 487px */
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.88889rem;
}

/* The scenario/portfolio as ONE object: heading plus every brand card in it.
   The brand cards themselves are unchanged — still separate white cards; this
   is purely the box around them. Previously there was no such box: the heading
   rendered inside the FIRST brand's card, so that card's own border closed
   after brand 1 and a 3-brand portfolio read as "portfolio = brand 1" followed
   by two unrelated cards.

   White, like every other panel on this screen (user decision — it was briefly
   transparent so the page surface separated the cards). The cards inside stay
   legible against it on their own hairline borders, exactly as the row-builder
   panel already does inside each card.

   Fills `.ss-scenario-col`'s full width rather than a fixed figure — with
   MAT reference no longer eating 308px as a sidebar (see `.ss-mat-band`),
   this column now gets the room Figma actually gives it (~1064px at the
   1360px content width), not the older, narrower 732px this used to be
   hardcoded to. */
.ss-scenario-group {
  width: 100%;
  /* Matches `.ses-card`'s own `flex: 1 1 auto` (ScenarioEmptyState.css) —
     without it, this card only ever hugged its own content inside
     `.ss-scenario-col`'s fixed-height column, so a short "This brand" table
     (few rows) left a visible gap of bare page background below the card
     instead of the card itself extending down to match the Brands card
     beside it — exactly the min-height `.ses-card` already solves for the
     empty state, just missing here for the populated one. `auto` basis (not
     `0`) means it still grows to its own natural content size and scrolls
     within the column's `overflow-y: auto` if that content is ever taller
     than the column, rather than being clipped at a hard 0 basis. */
  flex: 1 1 auto;
  background: var(--color-white);
  border: 1px solid var(--color-scenario-group-border);
  border-radius: 0.66667rem;
  /* Matches `.ses-card` (ScenarioEmptyState.css, Figma node 418:23991) — same
     card, before vs. after the first brand is added, so mismatched padding
     read as the card itself resizing. */
  padding: 1.11111rem 1.22222rem;
  display: flex;
  flex-direction: column;
  gap: 0.88889rem;
}

/* Shown in place of the brand cards when the shared brand search matches none
   of the ADDED brands — see `visibleAddedBrands`. */
.ss-scenario-no-matches {
  margin: 0;
  padding: var(--space-sm) 0;
  font-family: var(--font-family-base);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  color: var(--color-text-muted);
  text-align: center;
}

/* Eyebrow + name + count, sitting above every brand card in the group. The
   name alone ("uiac") gave no clue what it was; the eyebrow says so, using the
   SAME eyebrow-over-title pattern as this screen's own "SPEND BASED / Scope
   setup" page header rather than inventing a second one. */
.ss-scenario-group-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-sm);
  /* A rule under the header separates the group's identity from its contents
     without adding another box — the table below already carries its own. */
  padding-bottom: 0.66667rem;
  border-bottom: 1px solid var(--color-scenario-group-border);
}

.ss-scenario-header-actions {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.44444rem;
}

/* "This brand" / "All combinations (N)" — same segmented-pill shape as the
   Time period control (`.sdc-time-track`/`.sdc-time-pill` in
   ScenarioDetailsCard.css), simplified to a direct active-state fill rather
   than a measured sliding thumb: with just two fixed labels here, there's no
   unequal-width case that needs a real transform to glide between. */
.ss-scenario-tabs {
  display: inline-flex;
  align-items: center;
  gap: 0.11111rem;
  padding: 0.16667rem;
  background: var(--color-lightgrey);
  border: 1px solid var(--color-border);
  border-radius: 55.5rem;
}

.ss-scenario-tab {
  border: none;
  border-radius: 55.5rem;
  background: transparent;
  padding: 0.38889rem 0.77778rem;
  color: var(--ss-back-text);
  font-family: var(--ohf-body);
  font-size: calc(0.66667rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.366;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--motion-duration-fast) var(--motion-easing-standard),
    color var(--motion-duration-fast) var(--motion-easing-standard);
}

.ss-scenario-tab:not(.ss-scenario-tab--active):hover {
  color: var(--ss-cta-primary-bg);
}

.ss-scenario-tab--active {
  background: var(--ss-cta-primary-bg);
  color: var(--ss-cta-primary-text);
}

@media (prefers-reduced-motion: reduce) {
  .ss-scenario-tab {
    transition: none;
  }
}

.ss-scenario-title-group {
  display: flex;
  flex-direction: column;
  gap: 0.11111rem;
  min-width: 0;
}

.ss-scenario-eyebrow {
  font-family: var(--ohf-body);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  font-weight: 700;
  line-height: 1.366;
  letter-spacing: 0.06rem;
  text-transform: uppercase;
  color: var(--ss-eyebrow);
}

/* Matches `.ses-heading` (ScenarioEmptyState's pre-brand "Your Scenario")
   exactly — same heading, shown before vs. after the first brand is added,
   so a mismatched size/family read as the text changing. 16px = 0.88889rem
   at this page's 18px root. */
.ss-scenario-heading {
  margin: 0;
  font-family: var(--font-family-base);
  font-size: calc(0.88889rem * var(--ohf-text-scale));
  font-weight: 400;
  line-height: 1.35;
  color: var(--color-scenario-group-heading);
  overflow-wrap: anywhere;
}

/* "2 combinations" — what the portfolio actually consists of, which the user
   otherwise counts by eye across the cards below. */
.ss-scenario-count {
  flex-shrink: 0;
  margin-top: 0.16667rem;
  padding: 0.16667rem 0.44444rem;
  border-radius: 0.88889rem;
  background: var(--color-dropdown-active-bg);
  color: var(--ss-eyebrow);
  font-family: var(--font-family-base);
  font-size: calc(0.61111rem * var(--ohf-text-scale));
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* `.ss-row` is already a single column at every width (see above) now that
   MAT reference isn't a sidebar — the only thing left to stack at a narrow
   viewport is `.ss-brands-row` itself (Brands panel beside "Your Scenario").
   1024px is where that side-by-side layout stops genuinely fitting — matched
   by `.bp-card`'s own reset at the same width in BrandsPicker.css, so
   there's one number, not several, for "this is now a narrow layout." */
@media (max-width: 64rem) {
  .ss-brands-row {
    flex-direction: column;
    align-items: stretch;
  }

  /* `.ss-scenario-col`'s `flex: 1 1 0` (see that rule's own comment) sizes
     the row's main axis today — WIDTH, so it correctly fills whatever's
     left after `.bp-card`'s fixed basis. Once the parent flips to a column
     here, that same flex-basis:0 sizes the vertical main axis instead:
     HEIGHT, with no defined parent height for flex-grow to fill, so the
     panel collapsed to 0 and "Your Scenario" disappeared entirely below
     this breakpoint. Exact same bug `.bp-card` already has this identical
     fix for (see BrandsPicker.css) — reset the basis so the panel's own
     explicit `height: 27.05556rem` applies again instead. */
  .ss-scenario-col {
    flex: 0 1 auto;
    width: 100%;
  }
}
.scb-strip {
  --scb-label: #6b6e76;
  --scb-value: #0e0f11;
  --scb-sep: rgba(0, 0, 0, 0.24);
  --scb-border: rgba(0, 0, 0, 0.08);

  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  overflow: hidden;
  gap: 0.44444rem;
  padding: 0.61111rem 1.77778rem; /* 11px 32px */
  border-bottom: 1px solid var(--scb-border);
  background: var(--color-white);
  /* Stays put under the app chrome while the page scrolls — which scope you
     are editing has to remain readable next to the rows it applies to, and it
     used to scroll away with them. `top` is the fixed Navbar + AppTabs stack
     (see --app-header-stack-h); the z-index sits under AppTabs' own 101.
     `min-height` is what it already measured — pinned to the token so the
     app-level scrollbar's matching inset (index.css) can't drift from it. */
  position: sticky;
  top: var(--app-header-stack-h);
  z-index: 100;
  min-height: var(--app-scope-strip-h);
}

/* One line, always: every segment keeps its natural width, and only the typed-name
   segments (Scenario / Portfolio — `.scb-item--fluid`) give way when the bar runs out of room,
   ellipsizing their value rather than wrapping the bar onto a second line. With room
   to spare the name is shown in full; the full name is on hover only once clipped. */
.scb-item {
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem;
  flex: 0 0 auto;
  white-space: nowrap;
}
.scb-item--fluid {
  flex-shrink: 1;
  min-width: 0;
}
.scb-item--fluid .scb-sep,
.scb-item--fluid .scb-label {
  flex-shrink: 0;
}
.scb-item--fluid .scb-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.scb-sep {
  color: var(--scb-sep);
  padding: 0 0.33333rem;
  font-weight: 300;
}

.scb-label {
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  font-weight: 400;
  color: var(--scb-label);
}

.scb-value {
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  font-weight: 600;
  color: var(--scb-value);
  /* Scope dimensions ("usa, uk", "midwest, london") arrive from the warehouse
     lowercased — presentational only, exactly as in the scope selects that
     produced them. */
  text-transform: capitalize;
}

/* Scenario and Portfolio names were typed by a user; show them as typed. */
.scb-value--verbatim {
  text-transform: none;
}

/* "+(8)" counter after the two spelled-out values. Lighter than the values it
   trails so the segment still reads as "Brand: Axe, Bango" at a glance, with
   the counter as the aside it is. */
.scb-more {
  margin-left: 0.22222rem;
  font-weight: 500;
  color: var(--scb-label);
  font-variant-numeric: tabular-nums;
  /* The counter is generated, not a scope value — exempt from the
     capitalisation above (a no-op on digits, but it keeps the intent clear). */
  text-transform: none;
}
/* Palette scoped to the constraints toolbar card (values from Figma file
   UhXM9FKphZVFcmOL5CeMpr, node 194:9787). */
.sctb-card {
  --sctb-border: rgba(0, 0, 0, 0.08);
  --sctb-eyebrow: #9a9ca2;
  --sctb-radio-active: #0e0f11;
  --sctb-radio-inactive: #6b6e76;
  --sctb-radio-dot-active: #0a1a40;
  --sctb-radio-dot-inactive: #c7c7c7;
  --sctb-search-border: rgba(177, 184, 197, 0.4);
  --sctb-search-placeholder: #757575;
  --sctb-search-icon: #838996;
  --sctb-segmented-bg: #f1efea;
  --sctb-segmented-selected: #ffffff;
  --sctb-segmented-text: #6b6e76;
  --sctb-segmented-text-active: #0e0f11;
  --sctb-percent-border: rgba(0, 0, 0, 0.16);
  --sctb-percent-text: #0e0f11;
  --sctb-percent-suffix: #9a9ca2;
  --sctb-divider: rgba(0, 0, 0, 0.1);
  --sctb-apply-disabled-bg: #f4f3f0;
  --sctb-apply-disabled-border: rgba(0, 0, 0, 0.1);
  --sctb-apply-disabled-text: #b7b8bc;
  /* Figma only ever renders the disabled state (nothing checked). Enabled
     colours are inferred from this screen's own CTA navy (`Run Scenario`,
     `#0a1a40`) rather than invented — see ConstraintsToolbar.tsx. */
  --sctb-apply-enabled-bg: #0a1a40;
  --sctb-apply-enabled-text: #f9f5ed;
  --sctb-refresh-icon: #787a7f;
  --sctb-target-bg: #faf9f6;
  --sctb-target-amount: #171f30;
  --sctb-target-edit: #444444;

  background: var(--color-white);
  border: 1px solid var(--sctb-border);
  border-radius: 0.66667rem;
  padding: 0 0 0.66667rem;
  display: flex;
  flex-direction: column;
}

.sctb-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.88889rem;
}

.sctb-row--top {
  justify-content: space-between;
  padding: 0.88889rem 1.11111rem 0.77778rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.sctb-row--values {
  /* Never wrap this row — Reference mode's dropdown + Apply + scope segment
     take up noticeably more width than Bulk %'s two percent inputs, and
     wrapping was dropping the TARGET SPEND chip onto its own line below.
     `.sctb-values-group` shrinks first instead (`min-width: 0` below); the
     chip itself stays pinned right via `margin-left: auto`. Confirmed in
     both modes against the rendered app, not just Reference. */
  flex-wrap: nowrap;
  padding: 0.88889rem 1.11111rem 0;
}

.sctb-eyebrow {
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale, 1)); /* 10.5px */
  font-weight: 700;
  letter-spacing: 0.04111rem; /* 0.74px */
  text-transform: uppercase;
  color: var(--sctb-eyebrow);
  white-space: nowrap;
}

/* "Set values" info glyph — sits right after the eyebrow, riding the
   `.sctb-values-group` gap rather than its own margin. Content is the two
   `setValues.modes` (Bulk % / Reference Scenario) explained, since the tab
   labels alone don't say what either one actually does. */
.sctb-values-info-btn {
  margin: 0 0.11111rem 0 -0.22222rem; /* pulls it back toward the eyebrow text */
}

.sctb-values-tooltip {
  /* Two stacked sections read better a bit wider than the 288px default —
     matches the design's chip width without cramping the divider. */
  max-width: 15rem;
}

.sctb-values-tooltip-heading {
  display: block;
  font-weight: var(--font-weight-semibold);
  margin-bottom: var(--space-xs);
}

.sctb-values-tooltip-body {
  margin: 0;
}

.sctb-values-tooltip-divider {
  border: none;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  margin: var(--space-sm) 0;
}

.sctb-granularity-group,
.sctb-values-group {
  display: flex;
  align-items: center;
  /* 9px, matching Figma's Set-values row: 987px wide with children summing
     931, i.e. ~9px gaps. At 14px our row measured ~1122 — its fixed-width
     children spilled out of the group and rendered underneath the
     target-spend chip. */
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Overrides the shared rule above for this row specifically — see the note
   on `.sctb-row--values`. `min-width: 0` is what actually lets a flex child
   shrink below its content size instead of forcing the row wider than its
   container (the flexbox default is `min-width: auto`, i.e. "never smaller
   than my content"). */
.sctb-values-group {
  flex-wrap: nowrap;
  min-width: 0;
  flex: 1 1 auto;
}

/* ── Granularity radios — ◉ Channel ○ Platform ○ Campaign, confirmed against
   the rendered Figma frame (a single mutually-exclusive choice, not tabs). ── */
.sctb-radio-group {
  display: flex;
  align-items: center;
  gap: 0.88889rem;
}

/* No sliding pill here, unlike the segmented controls below: a radio group is
   a list of independent choices, not one surface with a moving selection, and
   a background gliding between them read as a control these are not. The
   motion lives in the dot itself. */
.sctb-radio {
  display: inline-flex;
  align-items: center;
  gap: 0.38889rem;
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 500;
  color: var(--sctb-radio-inactive);
  transition: color var(--motion-duration-normal) var(--motion-easing-standard);
}

.sctb-radio--active {
  font-weight: 700;
  color: var(--sctb-radio-active);
}

.sctb-radio-dot {
  width: 0.94444rem; /* 17px */
  height: 0.94444rem;
  border-radius: 50%;
  border: 1.5px solid var(--sctb-radio-dot-inactive);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: border-color var(--motion-duration-normal)
    var(--motion-easing-standard);
}

.sctb-radio:hover .sctb-radio-dot {
  border-color: var(--sctb-radio-dot-active);
}

.sctb-radio--active .sctb-radio-dot {
  border-color: var(--sctb-radio-dot-active);
}

/* The inner dot is always in the DOM and scales in on selection, so it springs
   out of the ring rather than appearing fully formed. */
.sctb-radio-dot::after {
  content: "";
  width: 0.5rem; /* 9px */
  height: 0.5rem;
  border-radius: 50%;
  background: var(--sctb-radio-dot-active);
  transform: scale(0);
  transition: transform var(--motion-duration-slow) var(--motion-easing-spring);
}

.sctb-radio--active .sctb-radio-dot::after {
  transform: scale(1);
}

/* ── Search ── */
.sctb-search {
  position: relative;
  width: 13.66667rem; /* 246px */
  height: 2.11111rem; /* 38px */
}

.sctb-search-icon {
  position: absolute;
  left: 0.66667rem;
  top: 50%;
  transform: translateY(-50%);
  width: 0.77778rem;
  height: 0.77778rem;
  color: var(--sctb-search-icon);
}

.sctb-search-input {
  width: 100%;
  height: 100%;
  border: 1px solid var(--sctb-search-border);
  border-radius: 0.44444rem;
  /* Right padding clears the × (see SearchClearButton), which overlays this
     field's right edge. */
  padding: 0 1.77778rem 0 1.77778rem;
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  color: var(--sctb-percent-text);
}

.sctb-search-input::placeholder {
  color: var(--sctb-search-placeholder);
}

/* ── Segmented controls ── */
.sctb-segmented {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.11111rem;
  background: var(--sctb-segmented-bg);
  border-radius: 0.5rem;
  padding: 0.16667rem;
}

/* The selected pill is ONE element sliding under the labels rather than a
   background switched on and off — matching the Scope Setup screen's Time
   Period control. Placed from --sctb-seg-thumb-x/-w, measured off the real
   selected button (see `useSegmentedThumb`); both transform and width animate,
   so the pill stretches as it glides between labels of unequal width. The
   width fallback of 0 keeps it invisible until that first measurement. */
.sctb-segmented-thumb {
  position: absolute;
  top: 0.16667rem;
  bottom: 0.16667rem;
  left: 0;
  width: var(--sctb-seg-thumb-w, 0);
  border-radius: 0.38889rem;
  background: var(--sctb-segmented-selected);
  transform: translateX(var(--sctb-seg-thumb-x, 0));
  transition:
    transform var(--motion-duration-slow) var(--motion-easing-spring),
    width var(--motion-duration-slow) var(--motion-easing-spring);
}

.sctb-segmented-btn {
  position: relative;
  z-index: 1;
  border: none;
  background: transparent;
  border-radius: 0.38889rem;
  padding: 0.38889rem 0.83333rem;
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  font-weight: 600;
  color: var(--sctb-segmented-text);
  cursor: pointer;
  white-space: nowrap;
  transition:
    color var(--motion-duration-fast) var(--motion-easing-standard),
    transform var(--motion-duration-fast) var(--motion-easing-spring);
}

/* Hover must NOT paint a background: the pill slides underneath these labels,
   and an opaque hover fill reads as a second, clashing pill. Darken the label
   instead. */
.sctb-segmented-btn:not(.sctb-segmented-btn--active):hover {
  color: var(--sctb-segmented-text-active);
}

.sctb-segmented-btn:active {
  transform: scale(0.96);
}

.sctb-segmented-btn--sm {
  font-size: calc(0.66667rem * var(--ohf-text-scale, 1)); /* 12px */
  padding: 0.33333rem 0.66667rem;
}

/* Background comes from the sliding thumb behind it — the button itself only
   switches its text colour. */
.sctb-segmented-btn--active {
  color: var(--sctb-segmented-text-active);
}

.sctb-divider {
  width: 1px;
  height: 1.55556rem;
  background: var(--sctb-divider);
  flex-shrink: 0;
}

/* ── Bulk % inputs ── */
.sctb-bulk-inputs {
  display: flex;
  align-items: center;
  gap: 0.66667rem;
}

.sctb-percent-field {
  display: flex;
  align-items: center;
  gap: 0.33333rem;
}

.sctb-percent-label {
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  color: var(--sctb-radio-inactive);
}

.sctb-percent-input {
  width: 3.22222rem; /* 58px */
  height: 1.72222rem; /* 31px */
  border: 1px solid var(--sctb-percent-border);
  border-radius: 0.33333rem;
  padding: 0 0.44444rem;
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1));
  color: var(--sctb-percent-text);
  text-align: right;
}

.sctb-percent-suffix {
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1));
  color: var(--sctb-percent-suffix);
}

/* ── Reference scenario picker ── */
.sctb-reference-picker {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
}

/* Restyled to match Figma's lighter, thinner select look (same as every
   other dropdown on this feature) rather than `SelectDropdown`'s own default
   — a heavier border plus a bold filled-triangle chevron (`TriggerChevronIcon`,
   built for the app's other, chunkier dropdowns). Scoped to
   `.sctb-reference-dropdown` only, same precedent as `.rom-select` in
   RecentOptimizationsModal.css, so no other `SelectDropdown` call site is
   affected. The chevron itself now uses `SelectDropdown`'s own default
   (`KeyboardArrowDownIcon`), sized 16×16 by the base component. */
.sctb-reference-dropdown.sd-wrap {
  border: 1px solid var(--sctb-percent-border);
  border-radius: 0.44444rem;
  /* Figma's dropdown is ~173px: its Set-values "Apply" container is 459px wide
     and holds the dropdown + the Apply label + the scope segment + gaps. At
     190px ours pushed the group's content 19px past the target-spend chip and
     the two overlapped. 160px leaves the row genuine slack at 1440. */
  min-width: 8.88889rem; /* 160px */
}

/* The rendered Figma frame shows a bare dropdown (chevron only, no visible
   placeholder/label above it) — `SelectDropdown`'s own floating label is
   still set (`label="Reference scenario"`) for its `aria-label`, just
   visually hidden here to match. */
.sctb-reference-dropdown .sd-label {
  display: none;
}

.sctb-reference-dropdown .sd-trigger {
  min-width: 0;
  height: 1.83333rem; /* 33px — between the 31px percent inputs and 36px Apply button, matching the row's other controls */
  padding: 0 0.55556rem;
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px, matching sctb-percent-label/-input */
}

.sctb-reference-dropdown .sd-value {
  font-family: var(--font-family-base);
  font-weight: 500;
  color: var(--sctb-percent-text);
}

.sctb-reference-dropdown .sd-chevron {
  color: var(--sctb-refresh-icon);
}

.sctb-reference-dropdown .sd-list {
  font-family: var(--font-family-base);
}

.sctb-reference-dropdown .sd-option {
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1));
  color: var(--sctb-percent-text);
}

.sctb-apply-label {
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  font-weight: 400;
  color: var(--sctb-radio-inactive);
  white-space: nowrap;
}

/* ── Apply / refresh ── */
.sctb-apply-wrap {
  display: inline-flex;
  flex-shrink: 0;
}

.sctb-apply-btn {
  height: 2rem; /* 36px */
  border-radius: 0.44444rem;
  padding: 0 0.94444rem;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 600;
  cursor: pointer;
  background: var(--sctb-apply-enabled-bg);
  border: 1px solid var(--sctb-apply-enabled-bg);
  color: var(--sctb-apply-enabled-text);
  white-space: nowrap;
}

.sctb-apply-btn:disabled {
  background: var(--sctb-apply-disabled-bg);
  border-color: var(--sctb-apply-disabled-border);
  color: var(--sctb-apply-disabled-text);
  cursor: not-allowed;
}

.sctb-refresh-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.44444rem;
  height: 1.44444rem;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0;
}

.sctb-refresh-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  color: var(--sctb-refresh-icon);
}

/* ── Target spend chip — a single line (label, amount, edit glyph), not a
   stacked card; confirmed against the rendered Figma frame. */
.sctb-target-spend {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
  height: 2.5rem; /* 45px */
  background: var(--sctb-target-bg);
  border-radius: 0.44444rem;
  padding: 0.44444rem 0.77778rem;
  /* Pinned to the row's right edge regardless of how much/little space
     `.sctb-values-group` ends up needing — see the note on
     `.sctb-row--values`. */
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
}

.sctb-target-amount {
  font-family: var(--font-family-base);
  font-size: calc(0.77778rem * var(--ohf-text-scale, 1)); /* 14px */
  font-weight: 600;
  letter-spacing: -0.04rem;
  color: var(--sctb-target-amount);
  white-space: nowrap;
}

/* Pencil-edit state — currency prefix + `NumberInput`, same pairing
   `TargetSpendCard`'s `.tsc-amount-currency`/`.tsc-amount-input` use. */
.sctb-target-amount-edit {
  display: inline-flex;
  align-items: baseline;
  gap: 0.22222rem;
}

.sctb-target-amount-currency {
  font-family: var(--font-family-base);
  font-size: calc(0.77778rem * var(--ohf-text-scale, 1)); /* 14px */
  font-weight: 600;
  color: var(--sctb-target-amount);
  white-space: nowrap;
}

/* Same type scale/colour as the resting `.sctb-target-amount` span it
   replaces, plus a bottom rule so it still reads as editable. */
.sctb-target-amount-input {
  font-family: var(--font-family-base);
  font-size: calc(0.77778rem * var(--ohf-text-scale, 1)); /* 14px */
  font-weight: 600;
  letter-spacing: -0.04rem;
  color: var(--sctb-target-amount);
  white-space: nowrap;
  width: 4.44444rem; /* 80px */
  border: none;
  border-bottom: 1px solid var(--sctb-target-edit);
  background: transparent;
  padding: 0 0 0.11111rem;
}

.sctb-target-amount-input:focus-visible {
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 2px;
}

.sctb-target-edit-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  color: var(--sctb-target-edit);
  flex-shrink: 0;
}

/* Wraps the edit glyph in a real button (was a bare decorative icon) —
   reset to look identical to the old inline icon. */
.sctb-target-edit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
}

.sctb-target-edit-btn:focus-visible {
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ── Narrow viewports ──
   `.sctb-row--values`/`.sctb-values-group` are deliberately `nowrap` above
   (see their own comments) because there's real slack at 1440. Below the
   root-font-scale's design width (`utils/viewportScale.ts` freezes 1rem at
   16px under 1280px, i.e. nothing here shrinks any further), that slack is
   gone and the same fixed-width controls (search box, percent inputs, Apply/
   Refresh, the Target spend chip) would instead overflow past the page edge —
   clipped by `html`/`body`'s `overflow-x: hidden` (src/index.css) rather than
   forcing page scroll, but either way inaccessible. Below this breakpoint the
   row reflows onto multiple lines instead; 1440 rendering is untouched. */
@media (max-width: 80rem) {
  .sctb-row--values {
    flex-wrap: wrap;
  }
  .sctb-values-group {
    flex-wrap: wrap;
  }
}

/* Honour the OS setting: the pills and the halo jump straight to the selected
   option rather than gliding, and the radio dot simply appears. */
@media (prefers-reduced-motion: reduce) {
  .sctb-segmented-thumb,
  .sctb-segmented-btn,
  .sctb-radio,
  .sctb-radio-dot,
  .sctb-radio-dot::after {
    transition: none;
  }

  .sctb-segmented-btn:active {
    transform: none;
  }
}
/* Run Scenario popup — ONE card: status, milestone progress, and where to go
   next. Restrained on purpose: brand navy, a single accent, motion that only
   ever reports real state. Every colour is a design token. */

.rsm-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
  background: var(--color-backdrop-overlay);
  animation: rsm-fade var(--motion-duration-normal) var(--motion-easing-enter)
    both;
}

.rsm-modal {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: min(var(--space-37-5), 100%);
  max-height: 90vh;
  overflow-y: auto;
  /* Reserve the scrollbar track: without it, content crossing the 90vh
     threshold as stages arrive snaps the card narrower for one frame. */
  scrollbar-gutter: stable;
  padding: var(--space-xxl) var(--space-xl) var(--space-lg);
  text-align: center;
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 var(--space-md) var(--space-xxl) var(--color-shadow-modal-lg);
  animation: rsm-rise var(--motion-duration-slow) var(--motion-easing-enter)
    both;
}

.rsm-close {
  position: absolute;
  top: var(--space-md);
  right: var(--space-md);
  display: flex;
  padding: var(--space-xs);
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-text-placeholder);
  cursor: pointer;
  transition: color var(--motion-duration-fast) ease;
}

.rsm-close:hover {
  color: var(--color-text-body);
}

.rsm-close:focus-visible {
  outline: var(--space-0-5) solid var(--color-primary);
  outline-offset: var(--space-0-4);
}

/* ── Glyph: a ring that draws, then a tick or cross ───── */

.rsm-glyph {
  width: var(--space-15);
  height: var(--space-15);
  margin-bottom: var(--space-lg);
}

.rsm-glyph-svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rsm-glyph-track {
  stroke: var(--color-circleblue);
  stroke-width: 4;
}

/* The arc is one dash chased around the ring while work is in flight, then
   closed into a full circle the moment the run settles. */
.rsm-glyph-arc {
  stroke: var(--color-primary);
  stroke-width: 4;
  stroke-dasharray: 48 140;
  transform-origin: center;
  animation: rsm-orbit 1.5s linear infinite;
}

.rsm-glyph--queued .rsm-glyph-arc {
  animation-duration: 2.6s;
  stroke: var(--color-text-placeholder);
}

.rsm-glyph--completed .rsm-glyph-arc,
.rsm-glyph--failed .rsm-glyph-arc {
  stroke-dasharray: 189;
  stroke-dashoffset: 0;
  animation: rsm-close-ring var(--motion-duration-slow)
    var(--motion-easing-enter) both;
}

.rsm-glyph--completed .rsm-glyph-arc {
  stroke: var(--color-success);
}

.rsm-glyph--failed .rsm-glyph-arc {
  stroke: var(--color-error);
}

/* Bars inside the ring, each rising on its own beat so the group reads as
   spend being redistributed rather than one pulsing block. */
.rsm-glyph-bars .rsm-bar {
  fill: var(--color-primary);
  stroke: none;
  transform-box: fill-box;
  transform-origin: bottom;
  animation: rsm-bar-rise 1.5s var(--motion-easing-ease-in-out) infinite;
}

.rsm-glyph-bars .rsm-bar--2 {
  animation-delay: 0.18s;
}

.rsm-glyph-bars .rsm-bar--3 {
  animation-delay: 0.36s;
}

.rsm-glyph--queued .rsm-glyph-bars .rsm-bar {
  fill: var(--color-text-placeholder);
}

.rsm-glyph-tick,
.rsm-glyph-cross path {
  stroke-width: 5;
  stroke-dasharray: 40;
  stroke-dashoffset: 40;
  animation: rsm-draw var(--motion-duration-slow) var(--motion-easing-enter)
    forwards;
  animation-delay: var(--motion-duration-normal);
}

.rsm-glyph-tick {
  stroke: var(--color-success);
}

.rsm-glyph-cross path {
  stroke: var(--color-error);
}

.rsm-glyph-cross path:last-child {
  animation-delay: calc(var(--motion-duration-normal) + 90ms);
}

/* ── Headline ─────────────────────────────────────────── */

.rsm-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0 0 var(--space-sm);
  font-family: var(--font-family-base);
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-primary);
}

.rsm-eyebrow--completed {
  color: var(--color-success);
}

.rsm-eyebrow--failed {
  color: var(--color-error);
}

.rsm-eyebrow--queued {
  color: var(--color-text-muted);
}

.rsm-eyebrow-dot {
  width: var(--space-0-45);
  height: var(--space-0-45);
  border-radius: var(--radius-full);
  background: currentColor;
}

.rsm-eyebrow--running .rsm-eyebrow-dot,
.rsm-eyebrow--queued .rsm-eyebrow-dot {
  animation: rsm-blink 1.6s var(--motion-easing-ease-in-out) infinite;
}

.rsm-title {
  /* Explicit width overrides `.rsm-modal`'s `align-items: center` fit-content
     sizing along the cross axis, so this stretches to the modal's full
     content width instead of hugging its own text — `.rsm-title-clip` below
     needs that definite width to have something to clip against. The modal's
     own `padding-inline` (`--space-xl`) already keeps this clear of the
     corner close button, whose inset (`--space-md`) is smaller. */
  width: 100%;
  margin: 0 0 var(--space-sm);
  font-size: var(--font-size-4xl);
  font-weight: var(--font-weight-bold);
  color: var(--color-text-body);
  line-height: var(--line-height-normal);
}

/* Ellipsis for a scenario name up to 50 chars (`SCENARIO_NAME_MAX_LENGTH` in
   `ScenarioDetailsCard.tsx`) — long enough to overflow this centered heading
   without it. Full name still reachable via `HoverTooltip`, same convention
   as `RecapConstraintsModal`'s `dimRender`. */
.rsm-title-clip {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rsm-desc {
  max-width: 28rem;
  margin: 0 0 var(--space-xl);
  font-family: var(--font-family-base);
  font-size: var(--font-size-md);
  color: var(--color-text-muted);
  line-height: 1.6;
}

/* ── Progress ─────────────────────────────────────────── */

.rsm-progress-block {
  width: 100%;
  margin-bottom: var(--space-lg);
}

.rsm-progress-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-sm);
  font-family: var(--font-family-base);
}

.rsm-progress-label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-body);
}

.rsm-progress-pct {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  color: var(--color-primary);
  font-variant-numeric: tabular-nums;
}

.rsm-progress {
  position: relative;
  width: 100%;
  height: var(--space-sm);
  border-radius: var(--radius-pill);
  background: var(--color-run-progress-track);
  overflow: hidden;
}

/* The width is driven frame-by-frame from JS (see `useSmoothProgress`), so it
   carries NO transition of its own — a CSS transition on top of a per-frame
   value fights it and lands the bar behind where the run actually is. */
.rsm-progress-fill {
  display: block;
  position: relative;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--color-run-progress-fill);
}

/* Bloom just behind the leading edge, so the head of the bar reads as the live
   end rather than a flat cut. */
.rsm-progress-fill--live::before {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: var(--space-lg);
  height: var(--space-lg);
  border-radius: var(--radius-full);
  background: var(--color-run-progress-glow);
  filter: blur(var(--space-1-5));
  transform: translateY(-50%);
  animation: rsm-glow 1.8s var(--motion-easing-ease-in-out) infinite;
}

/* A sheen travelling the filled portion: the run is alive between milestones
   even though the percentage is barely moving. */
.rsm-progress-fill--live::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline: 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--color-overlay-white-faint) 50%,
    transparent 100%
  );
  background-size: 40% 100%;
  background-repeat: no-repeat;
  animation: rsm-sheen 1.8s var(--motion-easing-ease-in-out) infinite;
}

/* ── Milestone stepper ────────────────────────────────────
   Each step owns the two connector halves that meet at its node: `::before` is
   the half arriving from the previous node, `::after` the half leaving towards
   the next. Both are suppressed at the ends of the row, so the rail can never
   overhang the first or last node — which is exactly what the single
   full-width rail used to do.

   A half fills by growing its gradient from 0% to 100% width, left to right,
   so completing a milestone visibly draws the line onward instead of switching
   a colour. `::before` fills as soon as its own step goes active (the run has
   arrived at this node), `::after` only once the step is done. */

.rsm-steps {
  --rsm-node: var(--space-7);
  --rsm-rail: var(--space-0-5);

  display: flex;
  width: 100%;
  /* Height is reserved before the first poll answers, so the card is the same
     size empty as it is once the milestones arrive — no resize, no flicker. */
  min-height: calc(var(--space-10) + var(--space-sm));
  margin: 0 0 var(--space-xl);
  padding: 0;
  list-style: none;
}

.rsm-step {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  animation: rsm-rise var(--motion-duration-normal) var(--motion-easing-enter)
    both;
}

.rsm-step::before,
.rsm-step::after {
  content: "";
  position: absolute;
  top: calc(var(--rsm-node) / 2);
  width: 50%;
  height: var(--rsm-rail);
  background-color: var(--color-run-step-rail);
  /* Flat fill expressed as a gradient purely so `background-size` can animate
     it — a plain background-color cannot be wiped in from the left. Square
     ends, so the two halves of a connector butt together without a seam. */
  background-image: linear-gradient(
    var(--color-primary),
    var(--color-primary)
  );
  background-repeat: no-repeat;
  background-size: 0% 100%;
  transform: translateY(-50%);
  transition: background-size var(--motion-duration-slow)
    var(--motion-easing-standard);
}

.rsm-step::before {
  left: 0;
}

.rsm-step::after {
  left: 50%;
}

/* No rail before the first node or after the last — the row ends at a node. */
.rsm-step:first-child::before,
.rsm-step:last-child::after {
  content: none;
}

.rsm-step--active::before,
.rsm-step--done::before,
.rsm-step--failed::before,
.rsm-step--done::after {
  background-size: 100% 100%;
}

.rsm-step-node {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--rsm-node);
  height: var(--rsm-node);
  border: var(--space-0-5) solid var(--color-run-step-rail);
  border-radius: var(--radius-full);
  background: var(--color-bg-card);
  color: var(--color-text-placeholder);
  z-index: 1;
  transition:
    border-color var(--motion-duration-normal) ease,
    background var(--motion-duration-normal) ease,
    color var(--motion-duration-normal) ease,
    box-shadow var(--motion-duration-normal) ease;
}

/* Halo — a ring that breathes outward from the node the run is currently on,
   the one piece of motion in the stepper that says "this is where it is". */
.rsm-step--active .rsm-step-node {
  border-color: var(--color-primary);
  color: var(--color-primary);
  box-shadow: 0 0 0 var(--space-0-5) var(--color-run-step-halo);
}

.rsm-step--active .rsm-step-node::after {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--space-0-5));
  border-radius: var(--radius-full);
  border: var(--space-0-5) solid var(--color-primary);
  animation: rsm-halo 1.8s var(--motion-easing-ease-in-out) infinite;
}

.rsm-step--done .rsm-step-node {
  border-color: transparent;
  background: var(--color-run-step-node-done);
  color: var(--color-white);
  box-shadow: 0 var(--space-0-5) var(--space-1-5)
    var(--color-run-step-node-shadow);
}

.rsm-step--failed .rsm-step-node {
  border-color: var(--color-error);
  background: var(--color-warning-bg-tint);
  color: var(--color-error);
}

.rsm-step-dot {
  width: var(--space-0-45);
  height: var(--space-0-45);
  border-radius: var(--radius-full);
  background: currentColor;
}

.rsm-step--active .rsm-step-dot {
  animation: rsm-pulse 1.4s var(--motion-easing-ease-in-out) infinite;
}

.rsm-step-mark {
  width: var(--space-3-5);
  height: var(--space-3-5);
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rsm-step-tick,
.rsm-step-cross {
  stroke-dasharray: 24;
  stroke-dashoffset: 24;
  animation: rsm-draw var(--motion-duration-draw) var(--motion-easing-enter)
    forwards;
}

.rsm-step-label {
  padding-inline: var(--space-xs);
  font-family: var(--font-family-base);
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-placeholder);
  line-height: 1.35;
  max-width: 9rem;
  transition: color var(--motion-duration-normal) ease;
}

.rsm-step--active .rsm-step-label,
.rsm-step--done .rsm-step-label {
  color: var(--color-text-body);
}

/* ── Next steps ───────────────────────────────────────── */

.rsm-next {
  width: 100%;
  padding-top: var(--space-lg);
  border-top: 1px solid var(--color-border);
}

.rsm-next-desc {
  margin: 0 0 var(--space-md);
  font-family: var(--font-family-base);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  line-height: 1.6;
}

.rsm-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
}

.rsm-btn {
  font-family: var(--font-family-base);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  padding: var(--space-sm) var(--space-lg);
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  cursor: pointer;
  transition:
    background var(--motion-duration-fast) ease,
    transform var(--motion-duration-fast) ease;
}

.rsm-btn:active {
  transform: translateY(1px);
}

.rsm-btn:focus-visible {
  outline: var(--space-0-5) solid var(--color-primary);
  outline-offset: var(--space-0-4);
}

.rsm-btn--primary {
  background: var(--color-primary);
  color: var(--color-white);
}

.rsm-btn--primary:hover {
  background: var(--color-primary-hover);
}

.rsm-btn--secondary {
  background: var(--color-white);
  border-color: var(--color-input-border);
  color: var(--color-text-body);
}

.rsm-btn--secondary:hover {
  background: var(--color-bg-hover-light);
}

/* ── Motion ───────────────────────────────────────────── */

@keyframes rsm-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes rsm-rise {
  from {
    opacity: 0;
    transform: translateY(0.5rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes rsm-orbit {
  to {
    transform: rotate(360deg);
  }
}

@keyframes rsm-close-ring {
  from {
    stroke-dashoffset: 189;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes rsm-draw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes rsm-blink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

@keyframes rsm-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.5);
    opacity: 0.5;
  }
}

@keyframes rsm-bar-rise {
  0%,
  100% {
    transform: scaleY(0.68);
  }
  50% {
    transform: scaleY(1);
  }
}

@keyframes rsm-sheen {
  0% {
    background-position-x: -60%;
  }
  100% {
    background-position-x: 160%;
  }
}

@keyframes rsm-glow {
  0%,
  100% {
    opacity: 0.55;
  }
  50% {
    opacity: 1;
  }
}

/* The active node's halo expands and fades, then restarts — a ring leaving the
   node rather than a border that merely blinks. */
@keyframes rsm-halo {
  0% {
    opacity: 0.55;
    transform: scale(1);
  }
  70%,
  100% {
    opacity: 0;
    transform: scale(1.55);
  }
}

/* Honour the OS setting: no loops, no entrance, and the drawn marks simply
   present rather than animating in. */
@media (prefers-reduced-motion: reduce) {
  .rsm-overlay,
  .rsm-modal,
  .rsm-step,
  .rsm-glyph-arc,
  .rsm-glyph-bars .rsm-bar,
  .rsm-eyebrow-dot,
  .rsm-step-dot,
  .rsm-step--active .rsm-step-node::after,
  .rsm-progress-fill--live::before,
  .rsm-progress-fill--live::after {
    animation: none;
  }

  .rsm-glyph-tick,
  .rsm-glyph-cross path,
  .rsm-step-tick,
  .rsm-step-cross {
    animation: none;
    stroke-dashoffset: 0;
  }

  .rsm-step::before,
  .rsm-step::after {
    transition: none;
  }
}
/* Portfolio scope's BRANDS sidebar (Figma file UhXM9FKphZVFcmOL5CeMpr, node
   250:8509). Scoped custom properties only — values pulled straight from
   that node tree, not shared design tokens, same convention as
   SetConstraints.css/ConstraintsTable.css on this same screen. */
.cbt-sidebar {
  --cbt-border: rgba(0, 0, 0, 0.08);
  --cbt-search-border: rgba(177, 184, 197, 0.4);
  --cbt-search-placeholder: #757575;
  --cbt-search-icon: #838996;
  --cbt-label: #9a9ca2;
  --cbt-chevron: #838996;
  --cbt-brand-name: #0e0f11;
  --cbt-count-bg: #f1efea;
  --cbt-count-text: #9a9ca2;
  --cbt-dot: #c7c7c7;
  --cbt-combo-text: #3b3d42;
  --cbt-combo-selected-bg: #e1e7f4;
  --cbt-empty-text: #6b6e76;

  flex: 0 0 12.05556rem; /* 217px */
  width: 12.05556rem;
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  gap: 0.66667rem;
  background: var(--color-white);
  border: 1px solid var(--cbt-border);
  border-radius: 0.66667rem; /* 12px */
  padding: 0.88889rem 0.77778rem; /* 16px 14px */
}

.cbt-label {
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale, 1)); /* 10.5px */
  font-weight: 700;
  text-transform: uppercase;
  color: var(--cbt-label);
}

/* ── Search ── */
.cbt-search {
  position: relative;
  display: flex;
  align-items: center;
  width: 10.38889rem; /* 187px */
  height: 2.11111rem; /* 38px */
  border: 1px solid var(--cbt-search-border);
  border-radius: 0.44444rem; /* 8px */
  background: var(--color-white);
}

.cbt-search-icon {
  position: absolute;
  left: 0.55556rem;
  width: 0.77778rem; /* 14px */
  height: 0.77778rem;
  color: var(--cbt-search-icon);
  flex-shrink: 0;
  pointer-events: none;
}

.cbt-search-input {
  width: 100%;
  height: 100%;
  border: none;
  background: transparent;
  padding-left: 1.77778rem; /* 32px */
  /* Right padding clears the × (see SearchClearButton), which overlays this
     field's right edge. */
  padding-right: 1.77778rem;
  font-family: var(--ohf-body);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 400;
  color: var(--cbt-brand-name);
}

.cbt-search-input::placeholder {
  color: var(--cbt-search-placeholder);
}

.cbt-search-input:focus {
  outline: none;
}

/* ── Brand list ── */
.cbt-brands {
  display: flex;
  flex-direction: column;
  gap: 0.22222rem;
  /* This is the sidebar's own vertical scroller — a Portfolio scope's brand
     count is unbounded, and the sidebar must never grow taller than (or
     push down) the table beside it. `flex: 1` + `min-height: 0` makes it fill
     whatever's left of `.cbt-sidebar`'s height once the label/search above it
     are laid out — sizing the CARD (not just this list) is what actually
     pins the sidebar to the table's height; see `maxHeight` on
     `ConstraintsBrandTreeProps`. `max-height` here stays only as a fallback
     ceiling for contexts with no pinned card height (undefined `maxHeight`),
     where a flex child of an auto-height column otherwise renders at its
     full, unclipped content size. */
  flex: 1;
  min-height: 0;
  max-height: 24.88889rem;
  overflow-y: auto;
}

.cbt-empty {
  margin: 0;
  padding: 0.44444rem 0.38889rem;
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  color: var(--cbt-empty-text);
  text-align: center;
}

.cbt-brand {
  display: flex;
  flex-direction: column;
}

.cbt-brand-toggle {
  display: flex;
  align-items: center;
  gap: 0.38889rem; /* 7px */
  height: 2rem; /* 36px */
  padding: 0.44444rem 0.38889rem; /* 8px 7px */
  border: none;
  background: transparent;
  border-radius: 0.38889rem; /* 7px */
  cursor: pointer;
  text-align: left;
}

.cbt-brand-toggle:hover {
  background: var(--color-bg-hover-light);
}

.cbt-chevron {
  width: 0.83333rem; /* 15px */
  height: 0.83333rem;
  color: var(--cbt-chevron);
  flex-shrink: 0;
}

.cbt-chevron--collapsed {
  transform: rotate(-90deg);
}

.cbt-dot {
  width: 0.38889rem; /* 7px */
  height: 0.38889rem;
  border-radius: 0.19444rem; /* 3.5px */
  background: var(--cbt-dot);
  flex-shrink: 0;
}

.cbt-brand-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 700;
  color: var(--cbt-brand-name);
}

.cbt-count {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.27778rem; /* 23px */
  height: 0.94444rem; /* 17px */
  padding: 0.11111rem 0.44444rem; /* 2px 8px */
  border-radius: var(--radius-pill);
  background: var(--cbt-count-bg);
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale, 1)); /* 10.5px */
  font-weight: 600;
  color: var(--cbt-count-text);
}

/* ── Combination rows ── */
.cbt-combos {
  display: flex;
  flex-direction: column;
  gap: 0.05556rem; /* 1px */
  padding-left: 1.11111rem; /* 20px */
}

.cbt-combo {
  width: 9.33333rem; /* 168px */
  height: 1.61111rem; /* 29px */
  padding: 0.38889rem 0.5rem; /* 7px 9px */
  border: none;
  border-radius: 0.33333rem; /* 6px */
  background: transparent;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  font-weight: 500;
  color: var(--cbt-combo-text);
}

.cbt-combo:hover {
  background: var(--color-bg-hover-light);
}

.cbt-combo--selected,
.cbt-combo--selected:hover {
  background: var(--cbt-combo-selected-bg);
}
/* Performance Recap modal — Set Constraints screen (Figma 194-13008).
   Rendered inside `.sc-page`, so the screen's `--sc-*` palette and `--ohf-*`
   fonts are inherited. */

.prm-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: var(--color-backdrop-overlay, rgba(10, 26, 64, 0.45));
}

.prm-modal {
  display: flex;
  flex-direction: column;
  width: min(76rem, 96vw);
  /* Fixed shell height, NOT content-driven: the body swaps a loader for a table
     whose row count changes with the page (and the last page is usually short),
     so a content-sized modal resized on load and on every page step. The table
     already fills and scrolls inside the body (see .prm-body .dt-* below), so a
     stable shell just holds it still. Sized to a full 10-row page — the default
     "Rows per page" — so a full table leaves no dead space and a short one
     simply doesn't shrink it. */
  height: min(36.5rem, 90vh);
  overflow: hidden;
  background: var(--color-white, #ffffff);
  border-radius: 0.88889rem;
  box-shadow: var(--color-shadow-modal, 0 1.11111rem 3.33333rem rgba(10, 26, 64, 0.25));
}

.prm-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-shrink: 0;
  padding: 1.33333rem 1.66667rem;
}

.prm-heading-group {
  display: flex;
  flex-direction: column;
  gap: 0.55556rem;
}

.prm-title {
  margin: 0;
  font-family: "Inter", var(--ohf-body), sans-serif;
  font-size: calc(1.33333rem * var(--ohf-text-scale, 1));
  font-weight: 400;
  color: var(--sc-heading, #171f30);
  letter-spacing: -0.01em;
}

/* "Time Period" + the scenario's MAT window (e.g. "Aug 2025 - Jul 2026",
   "Rest of Year"), directly under the title. A key/value pair styled after
   the Recap Constraints modal's own info row (`.rcc-info-label`/
   `.rcc-info-value` in RecapConstraintsModal.css) — same colors/sizing, so
   this popup's header reads as the same family as that one. Indented
   slightly off the title's own left edge to read as a secondary line, not a
   second heading stacked flush beneath it. */
.prm-subtitle {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
  margin: 0 0 0 0.13333rem;
  font-family: var(--font-family-base);
}

.prm-subtitle-label {
  color: #838996;
  font-size: calc(0.78125rem * var(--ohf-text-scale, 1)); /* 12.5px */
}

.prm-subtitle-value {
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 600;
  color: #505869;
}

.prm-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: none;
  background: none;
  color: var(--sc-heading, #171f30);
  cursor: pointer;
  border-radius: 0.22222rem;
  transition: background 0.15s;
}

.prm-close:hover {
  background: var(--color-bg-hover-light, #f0f2f6);
}

.prm-close-icon {
  width: 1.22222rem;
  height: 1.22222rem;
}

.prm-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 0 1.66667rem 1.11111rem;
}

/* Portfolio only (`brandTree` non-null) — sidebar + table, laid out to fill
   the modal's fixed-height body (unlike the main screen's own
   `.sc-content-row`, which just grows with the page document). */
.prm-content-row {
  display: flex;
  align-items: stretch;
  flex: 1;
  min-height: 0;
}

.prm-table-col {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* `ConstraintsBrandTree` renders as its own rounded/shadowed-off card on the
   main constraints table (see `.cbt-sidebar` in ConstraintsBrandTree.css) —
   here it should instead read as an extension of the table itself: a plain,
   square-cornered bordered box flush against the table, not a distinct
   rounded panel beside it. Scoped to `.prm-content-row` so the main screen's
   own sidebar is untouched. */
.prm-content-row .cbt-sidebar {
  background: none;
  border: 1px solid var(--cbt-border, rgba(0, 0, 0, 0.08));
  border-radius: 0;
  /* Figma's own 217px sidebar fits its 187px search box exactly (217 - 1px
     border - 14px*2 padding = 187) — zero slack, so this modal's own copy is
     widened a touch past that exact fit for breathing room. `.cbt-search`
     below is widened by the SAME amount so the fit relationship (and its
     zero-slack margin) is preserved, not just the outer box. */
  width: 13.05556rem; /* 235px, was 12.05556rem/217px */
  flex-basis: 13.05556rem;
  /* The base rule opts out of stretching (`align-self: flex-start`, so the
     card hugs its own content on the main table) — here the border should
     run the full row height alongside the table, so that opt-out is reversed
     just for this usage. */
  align-self: stretch;
}

.prm-content-row .cbt-search {
  width: 11.38889rem; /* 205px, was 10.38889rem/187px — see .cbt-sidebar above */
}

/* Typed-text styling matched to the Recap Constraints modal's own search box
   (`.or-side-search-input` in OptimisationResults.css): same font stack/size,
   and its lighter `#757575` in place of `.cbt-search-input`'s own near-black
   `--cbt-brand-name`, which read noticeably darker/heavier side by side. Box
   shape (fixed height, icon-overlay padding) is left as `.cbt-search`'s own —
   only the text's own look is being matched here, not the input's layout. */
.prm-content-row .cbt-search-input {
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.72222rem;
  font-weight: 400;
  color: #757575;
}

/* `emptyMessage="No match found"` (passed from PerformanceRecapModal.tsx)
   already matches the Recap Constraints modal's own copy — this matches its
   STYLING too (`.or-tree-no-match` in OptimisationResults.css): centered,
   medium-weight, `--or-faint` grey, with more breathing-room padding, instead
   of the base `.cbt-empty` rule's left-aligned/regular-weight/darker look. */
.prm-content-row .cbt-empty {
  font-weight: 500;
  text-align: center;
  color: var(--or-faint, #9a9ca2);
  padding: 0.66667rem 0.22222rem;
}

/* The base rule renders the backend's own copy verbatim ("Brands ", title
   case — see `ConstraintsBrandTree`'s own doc comment on why it doesn't
   transform this label). This modal's reference design shows it all-caps
   ("BRANDS"), so that's applied here only, not on the main table's sidebar. */
.prm-content-row .cbt-label {
  text-transform: uppercase;
}

/* `chevronIcon={ChevronOutlineIcon}` (passed from PerformanceRecapModal.tsx)
   swaps the glyph itself to match the Recap Constraints modal's own Brands
   tree (`.or-tree-chevron` in OptimisationResults.css) — this adds that same
   rule's smooth rotation on top, which the base `.cbt-chevron` doesn't have
   (the main table's own dropdown-style chevron never animated). */
.prm-content-row .cbt-chevron {
  transition: transform 0.15s ease;
}

/* The modal shell keeps its fixed height, but the table inside it sizes to its ROWS: a
   short page (6 rows) ends right above the pagination instead of stretching to fill the
   body and leaving a blank band between the last row and the footer — any spare height
   collects below the pagination instead. Once the rows outgrow the body, every level
   below shrinks (`flex: 0 1 auto` + `min-height: 0`) and the scroll area scrolls, so
   the pagination is never pushed out of the modal. `max-height: 100%` can't be used for
   that: against a parent with auto height it resolves to `none`, and the rows would be
   clipped rather than scrolled. */
.prm-body .dt-wrapper {
  flex: 0 1 auto;
  min-height: 0;
}

.prm-body .dt-body {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.prm-body .dt-inner-wrap {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.prm-body .dt-pagination {
  flex-shrink: 0;
}

.prm-body .dt-inner-h {
  flex: 0 1 auto;
  min-height: 0;
  max-height: none;
  /* Pulling past an edge (touchpad / touch) must not elastic-bounce the table and open a
     blank band above the header or beside the first column: the page behind this modal is
     scroll-locked, so there is nothing for the gesture to chain to and the browser would
     rubber-band the table itself. `none` keeps the header and cells fixed at every edge. */
  overscroll-behavior: none;
  scrollbar-width: thin;
  scrollbar-color: var(--color-scrollbar-thumb-soft) transparent;
}
.prm-body .dt-inner-h::-webkit-scrollbar {
  display: block;
  width: 0.66667rem;
  height: 0.66667rem;
}
.prm-body .dt-inner-h::-webkit-scrollbar-track {
  background: transparent;
  border: 0;
}
.prm-body .dt-inner-h::-webkit-scrollbar-thumb {
  background-color: var(--color-scrollbar-thumb-soft);
  background-clip: content-box;
  border: 0.16667rem solid transparent;
  border-radius: var(--radius-pill);
}
.prm-body .dt-inner-h::-webkit-scrollbar-thumb:hover {
  background-color: var(--color-scrollbar-thumb-soft-hover);
}
.prm-body .dt-htrack,
.prm-body .dt-vtrack {
  display: none;
}
/* The native bars above replace BOTH of the component's custom tracks — hiding only the
   horizontal one left its vertical thumb drawn beside the native vertical bar (two
   scrollers). Drop the gutter and header strip the component reserves for that thumb too. */
.prm-body .dt-inner-wrap--vscroll .dt-inner-h {
  margin-right: 0;
}
.prm-body .dt-inner-wrap--vscroll::before {
  content: none;
}

.prm-body .dt-table tbody tr:hover td {
  background: var(--color-white, #ffffff);
}

.prm-body .dt-th-btn:hover {
  background: none;
}

.prm-body .dt-filter-wrap .dt-th-btn:hover svg path {
  fill: var(--or-navy, #0a1a40);
}

.prm-modal .prm-cell {
  color: var(--sc-heading, #171f30);
}

/* Only the text/dimension columns (Channel / Platform) are bold and
   left-aligned under their header — matches `.rcc-dim` in
   RecapConstraintsModal.css (itself matching the Portfolio Breakdown table).*/
.prm-modal .prm-dim {
  font-weight: 700;
  font-size: 0.75rem;
  text-align: left;
}

/* Ellipsis for an overflowing Channel/Platform name — the full value is
   still reachable via `HoverTooltip` (see `dimRender` in
   PerformanceRecapModal.tsx). `display: block` is required for a `<span>`
   (an inline element otherwise ignores `overflow`/`text-overflow`) inside the
   fixed-width `<td>` the `tableLayout="fixed"` DataTable now renders.
   Matches `.rcc-dim-text` in RecapConstraintsModal.css. */
.prm-modal .prm-dim-text {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Numeric columns right-align and stay at regular weight. */
.prm-modal .prm-num {
  text-align: center;
  white-space: nowrap;
  font-weight: 400;
  font-size: 0.72222rem;
}

/* ── Header: match the Recap Constraints modal / Portfolio Breakdown table ──
   Copied from `.rcc-body .dt-table th` etc. in RecapConstraintsModal.css, so
   this popup's table reads as the same family as the other "recap" modals
   instead of the shared DataTable's own plain grey/black default header. The
   `--or-*` vars those rules read normally come from `.or-page` (which THIS
   modal, rendered inside `.sc-page`, never gets) — the literal fallbacks are
   exactly what make the block self-contained here too, same as that file's
   own doc comment notes. Scoped to `.prm-body` so every other DataTable is
   untouched. */
.prm-body .dt-table thead tr,
.prm-body .dt-table th {
  background: var(--or-channel-tint, #faf9f6);
}

.prm-body .dt-table th {
  font-size: 0.58333rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #7e7e7e;
  padding: 0.55556rem 0.55556rem 0.44444rem 0.83333rem;
  border-bottom: 1px solid var(--or-border, #e9eaf0);
  border-right: 1px solid var(--or-border, #e9eaf0);
}

.prm-body .dt-table thead tr th:last-child {
  border-right: none;
}

.prm-body .dt-table td {
  border-right: 1px solid var(--or-border, #e9eaf0);
}

.prm-body .dt-table tr td:last-child {
  border-right: none;
}

/* Dimension headers sit left over their text column; the numeric headers stay
   centred over theirs — same split `.rcc-body`/`.or-table` make. */
.prm-body .dt-table th[data-col-key="channel"],
.prm-body .dt-table th[data-col-key="platform"] {
  text-align: center;
}

.prm-body .dt-table th[data-col-key="channel"] .dt-th-inner,
.prm-body .dt-table th[data-col-key="platform"] .dt-th-inner {
  justify-content: center;
}

.prm-body .dt-pagination {
  border: none;
  border-top: 1px solid var(--or-border, #e9eaf0);
  border-radius: 0;
  background: none;
  font-size: 0.69444rem;
  color: var(--or-muted, #6b6e76);
}

.prm-body .dt-rows-label {
  white-space: nowrap;
}

.prm-body .dt-rpp-trigger {
  border: 1px solid var(--or-border, #e9eaf0);
  border-radius: 0.33333rem;
  padding: 0.22222rem 0.55556rem;
  background: var(--or-card, #ffffff);
  font-size: 0.69444rem;
  color: var(--or-ink, #0e0f11);
  min-width: 2.77778rem;
}

.prm-body .dt-rpp-chevron {
  width: 0.55556rem;
  height: 0.55556rem;
  color: var(--or-axis, #838996);
}

.prm-body .dt-rpp-dropdown {
  background: var(--or-card, #ffffff);
  border: 1px solid var(--or-border, #e9eaf0);
  border-radius: 0.33333rem;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-popover);
}

.prm-body .dt-rpp-option {
  font-size: 0.69444rem;
  color: var(--or-ink, #0e0f11);
}

.prm-body .dt-rpp-option:hover {
  background: var(--or-bg, #f6f6f9);
}

.prm-body .dt-rpp-option--selected {
  background: var(--or-combo-sel, #e1e7f4);
  font-weight: 700;
  color: var(--or-ink, #0e0f11);
}

.prm-body .dt-page-info {
  min-width: 5rem;
  font-variant-numeric: tabular-nums;
}

.prm-body .dt-nav-btn {
  color: var(--or-ink, #0e0f11);
  font-size: 1.11111rem;
}

.prm-body .dt-nav-btn:disabled {
  color: var(--or-faint, #9a9ca2);
}
/* Faithful replica of the old optimizer's `DataTable` multi-select column
   filter (`.dt-filter-dropdown.dt-filter-multi` in DataTable.css) — same
   tokens, same values — kept as its own stylesheet (rather than importing
   DataTable.css) so DataTable itself stays untouched and this component has
   no bundling dependency on it. */
.cf-popover {
  position: fixed;
  z-index: 9999;
  background: var(--color-white);
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-popover);
  padding: var(--space-sm) 0;
  min-width: var(--space-56);
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  overflow: hidden;
}

.cf-search {
  border: var(--space-px) solid var(--color-input-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-2) var(--space-sm);
  font-size: var(--font-size-xs);
  color: var(--color-primary);
  outline: none;
  font-family: var(--font-family-base);
  margin: 0 var(--space-sm) var(--space-1-5);
  width: calc(100% - var(--space-lg));
}

.cf-search:focus {
  border-color: var(--color-border-strong);
}

.cf-select-all {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-1-4) var(--space-md);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  cursor: pointer;
  user-select: none;
  border-bottom: var(--space-px) solid var(--color-border);
  margin-bottom: var(--space-xs);
  padding-bottom: var(--space-sm);
}

.cf-select-all em {
  font-style: normal;
  font-weight: var(--font-weight-semibold);
  color: var(--color-primary);
}

.cf-count {
  margin-left: auto;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Prevent flex from compressing the scroll area — csb-content height must
   match csb-root, and push the native scrollbar outside csb-root's
   overflow:hidden clip — cross-browser (same fix DataTable.css applies). */
.cf-popover .csb-root {
  flex-shrink: 0;
}

.cf-popover .csb-content {
  width: calc(100% + 20px);
  padding-right: 20px;
  box-sizing: content-box;
}

.cf-list {
  padding-bottom: var(--space-md);
}

.cf-option {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-1-4) var(--space-md);
  font-size: var(--font-size-sm);
  color: var(--color-text-body);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cf-option:hover {
  background: var(--color-bg-hover-light);
}

.cf-checkbox {
  accent-color: var(--color-primary);
  width: var(--space-3-5);
  height: var(--space-3-5);
  flex-shrink: 0;
  cursor: pointer;
}

.cf-option-empty {
  color: var(--color-text-placeholder);
  font-style: italic;
}

.cf-no-results {
  margin: 0;
  padding: var(--space-xs) var(--space-md);
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
  text-align: center;
}

.cf-highlight {
  background: var(--color-subtleblue);
  color: var(--color-primary);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--space-0-5);
  padding: 0 var(--space-px);
}

.cf-error {
  margin: 0 var(--space-md) var(--space-xs);
  font-size: var(--font-size-xs);
  color: var(--color-error);
  text-align: right;
}

.cf-actions {
  display: flex;
  gap: var(--space-1-5);
  justify-content: flex-end;
  padding: var(--space-sm) var(--space-sm) 0;
  border-top: var(--space-px) solid var(--color-border);
  margin-top: var(--space-1-5);
}

.cf-cancel-btn {
  background: none;
  border: var(--space-px) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-5);
  font-size: var(--font-size-base);
  color: var(--color-primary);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: border-color var(--motion-duration-fast) ease;
}

.cf-cancel-btn:hover {
  border-color: var(--color-border-strong);
}

.cf-apply-btn {
  background: var(--color-primary);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-1-5) var(--space-xl);
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  font-family: var(--font-family-display);
  transition: background var(--motion-duration-fast) ease;
}

.cf-apply-btn:hover:not(:disabled) {
  background: var(--color-primary-hover);
}

.cf-apply-btn:disabled {
  background: var(--color-border);
  color: var(--color-text-placeholder);
  cursor: not-allowed;
  opacity: 0.6;
}
/* Palette scoped to the slider (values from the rendered Figma frames — file
   UhXM9FKphZVFcmOL5CeMpr, node 194:9787, "Slider" column). Figma renders two
   distinct colour schemes depending on the row's LOCK state, not one fixed
   style: an unlocked row's slider is blue with a small reference tick (the
   "TV"/"Search"/"Influencer" rows), a locked row's slider is grey (the
   "Ooh"/"Other Display" rows — confirmed against the render, where nothing
   is ever checked but those two rows are still grey). `.rgs-wrap--locked`/
   `--unlocked` switch between the two var sets below — see ConstraintsRow.tsx. */
.rgs-wrap {
  --rgs-track-bg: #d7e2f5;
  --rgs-fill: #304d89;
  --rgs-tick: #96acd1;
  --rgs-handle-fill: #fdfcf8;
  --rgs-handle-stroke: #304d89;
  --rgs-label: #838996;

  display: flex;
  flex-direction: column;
  gap: 0.27778rem; /* 5px */
  width: 100%;
}

.rgs-wrap--locked {
  --rgs-track-bg: #dedede;
  --rgs-fill: #999999;
  --rgs-handle-stroke: #999999;
}

/* No opacity fade — the grey tone above already reads as "locked" in the
   render, a locked slider isn't additionally dimmed. Just non-interactive. */
.rgs-wrap--disabled {
  pointer-events: none;
}

.rgs-track {
  position: relative;
  width: 100%;
  height: 0.44444rem; /* 8px */
  border-radius: 999px;
  background: var(--rgs-track-bg);
  /* NOT overflow: hidden. The handles (12px) and the tick (14px) are both
     deliberately taller than the track (8px) and overhang it top/bottom —
     confirmed by sampling the rendered Figma frame pixel-by-pixel: its
     handles are full, unclipped circles, not flattened at the track edge.
     `.rgs-fill` still gets fully rounded ends on its own via its own
     `border-radius`, so nothing needed clipping in the first place. */
}

.rgs-tick {
  position: absolute;
  top: 50%;
  width: 0.05556rem; /* ~0.4px in Figma, floored to a renderable 1px */
  height: 0.77778rem; /* 14px — overhangs the 8px track like the handles do */
  background: var(--rgs-tick);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.rgs-fill {
  position: absolute;
  top: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--rgs-fill);
  pointer-events: none;
}

.rgs-handle {
  position: absolute;
  top: 50%;
  width: 0.66667rem; /* 12px */
  height: 0.66667rem;
  border-radius: 50%;
  background: var(--rgs-handle-fill);
  border: 2px solid var(--rgs-handle-stroke);
  transform: translate(-50%, -50%);
  padding: 0;
  cursor: grab;
  touch-action: none;
}

.rgs-handle:active {
  cursor: grabbing;
}

.rgs-handle:focus-visible {
  outline: 2px solid var(--color-input-border-focus);
  outline-offset: 2px;
}

.rgs-labels {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.44444rem;
}

.rgs-label {
  font-family: var(--ohf-mono);
  font-weight: 400;
  font-size: calc(0.55556rem * var(--ohf-text-scale, 1));
  line-height: 1.3;
  color: var(--rgs-label);
  white-space: nowrap;
}
/* Palette scoped to a constraints table row (values from the rendered Figma
   frames — file UhXM9FKphZVFcmOL5CeMpr, nodes 194:9787/194:10844/194:11559).
   Cell widths are fixed px, set inline per-cell from `CELL_WIDTH_PX`
   (constraintsColumns.ts) — sized for the widest realistic content, not
   Figma's literal (frame-width-dependent) px, so the row never truncates;
   the table scrolls horizontally instead (`.sct-scroll` in
   ConstraintsTable.css) when a row is wider than its container.

   Figma renders a genuinely different look depending on the row's LOCK
   state, not its checkbox state (confirmed against the render: nothing is
   ever checked in any of the three captures, yet the "Ooh"/"Other Display"
   rows are still grey/borderless/grey-slider — because they're locked):
     unlocked (white bg): "TV"/"Search"/"Influencer"/... — white row,
       #222222 numbers, bordered/filled CPM+Min+Max inputs, blue slider.
     locked (grey bg, navy padlock): "Ooh"/"Other Display" — #f2f2f2 row,
       #6e6e6e numbers, borderless CPM+Min+Max inputs, grey slider.
   `.sct-row--unlocked`/`.sct-row--locked` switch the vars below; the default
   on `.sct-row` itself is the *unlocked* look, since that's every row's
   starting state. */
.sct-row {
  --sct-row-bg: #ffffff;
  --sct-row-border: rgba(0, 0, 0, 0.1);
  --sct-name: #0e0f11;
  --sct-number: #222222;
  --sct-input-border: #b1b8c5;
  --sct-input-bg: #fdfcf8;
  --sct-input-text: #222222;
  --sct-checkbox-selected-bg: #0a1a40;
  --sct-checkbox-check: #f9f5ed;
  --sct-checkbox-border: #767676;
  --sct-lock-border: #b1b8c5;
  --sct-lock-active-icon: #f9f5ed;
  --sct-lock-inactive-icon: #838996;
  /* Same amber pair as OptimizationCard.css's `--oc-portfolio-bg`/
     `--oc-portfolio-text` and the Import modal's portfolio badge — not
     shared/imported (no shared-token edits per this feature's constraints),
     just the same literal values re-declared in this row's own scope. */
  --sct-reference-bg: #fcebcc;
  --sct-reference-text: #9f6700;

  display: flex;
  align-items: center;
  width: max-content;
  min-width: 100%;
  background: var(--sct-row-bg);
  border-bottom: 1px solid var(--sct-row-border);
}

.sct-row--locked {
  --sct-row-bg: #f2f2f2;
  --sct-number: #6e6e6e;
  --sct-input-border: transparent;
  --sct-input-bg: transparent;
  --sct-input-text: #6e6e6e;
}

.sct-row--locked .sct-input:disabled {
  cursor: not-allowed;
}

.sct-checkbox:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.sct-cell {
  display: flex;
  align-items: center;
  padding: 0 0.55556rem; /* 10px */
  min-height: 2.77778rem; /* 50px */
  border-right: 1px solid var(--sct-row-border);
  overflow: hidden;
  box-sizing: border-box;
}

.sct-cell--lock,
.sct-cell--checkbox {
  justify-content: center;
}

/* ── Lock (Cell 1) — 26x26 rounded box, radius 7. Unlocked: grey outline
   with a grey padlock. Locked: filled navy (`--sct-checkbox-selected-bg`)
   with a cream padlock — confirmed against the rendered Figma frame. */
.sct-lock-wrap {
  display: inline-flex;
  flex-shrink: 0;
}

.sct-lock-btn {
  width: 1.44444rem; /* 26px */
  height: 1.44444rem;
  border-radius: 0.38889rem; /* 7px */
  border: 1px solid var(--sct-lock-border);
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}

.sct-lock-btn--locked {
  background: var(--sct-checkbox-selected-bg);
  border-color: var(--sct-checkbox-selected-bg);
}

.sct-lock-icon {
  width: 0.77778rem;
  height: 0.77778rem;
}

/* ── Checkbox (Cell 2) — plain 17x17 square, radius 2.5. The one "Apply to
   checked" reads. */
.sct-checkbox {
  width: 0.94444rem; /* 17px */
  height: 0.94444rem;
  border-radius: 0.13889rem; /* 2.5px */
  border: 1px solid var(--sct-checkbox-border);
  background: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}

.sct-checkbox--checked {
  background: var(--sct-checkbox-selected-bg);
  border-color: var(--sct-checkbox-selected-bg);
}

.sct-checkbox-icon {
  width: 0.44444rem;
  height: 0.33333rem;
  color: var(--sct-checkbox-check);
}

.sct-name {
  font-family: var(--font-family-base);
  font-size: calc(0.75rem * var(--ohf-text-scale, 1)); /* 13.5px */
  font-weight: 600;
  color: var(--sct-name);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sct-cell--number {
  justify-content: flex-end;
}

.sct-number {
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 500;
  color: var(--sct-number);
  text-align: right;
}

.sct-cell--cpm {
  justify-content: center;
}

.sct-input {
  border: 1px solid var(--sct-input-border);
  border-radius: 0.22222rem;
  background: var(--sct-input-bg);
  color: var(--sct-input-text);
  font-family: var(--ohf-body);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1)); /* 12.5px */
  font-weight: 400;
  text-align: right;
  padding: 0.33333rem 0.44444rem;
  min-width: 0;
}

.sct-input--cpm {
  width: 2.88889rem; /* 52px */
}

.sct-cell--bound {
  gap: 0.44444rem;
  justify-content: flex-end;
}

.sct-input--value {
  width: 5rem; /* 90px */
  flex: 1 1 auto;
}

.sct-input--percent {
  width: 2.88889rem; /* 52px */
  flex-shrink: 0;
}

.sct-cell--slider {
  justify-content: center;
}

.sct-cell--reference {
  justify-content: center;
  /* "Both" scope renders two badges side by side (see ConstraintsRow.tsx) —
     this gap only takes effect then; a single badge (min/max scope) is
     unaffected by a gap with nothing to space it from. */
  gap: 0.33333rem; /* 6px */
}

.sct-reference-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: var(--sct-reference-bg);
  color: var(--sct-reference-text);
  font-family: var(--font-family-base);
  font-size: calc(0.61111rem * var(--ohf-text-scale, 1)); /* 11px */
  font-weight: 600;
  padding: 0.16667rem 0.5rem; /* 3px 9px */
  white-space: nowrap;
}
/* Palette scoped to the constraints table (values from the rendered Figma
   frames — file UhXM9FKphZVFcmOL5CeMpr, nodes 194:9787/194:10844/194:11559).

   Column widths are fixed px per column id (`CELL_WIDTH_PX` in
   constraintsColumns.ts), not Figma's literal px — the frame's own column
   widths are a computed consequence of it being exactly 1440px wide, and
   porting them literally is what produced the truncated "MAT SPEND (..."
   header and clipped slider under-labels in an earlier pass. Each column is
   sized for its widest realistic content instead, and `.sct-scroll` is the
   one place on this screen that scrolls horizontally when the row is wider
   than its container — never the page body itself (src/index.css: "Layout
   containers ... own their own horizontal scroll via overflow-x: auto"). */
.sct-table {
  --sct-border: #cfd4df;
  --sct-cell-border: rgba(0, 0, 0, 0.1);
  --sct-header-bg: #faf9f6;
  --sct-header-text: #7e7e7e;
  --sct-header-text-muted: #9a9ca2;
  --sct-empty-text: #6b6e76;
  --sct-page-icon: rgba(28, 27, 31, 0.4);
  --sct-page-icon-active: #1c1b1f;
  --sct-range-text: #3b3d42;

  background: var(--color-white);
  border: 1px solid var(--sct-border);
  border-radius: 0.66667rem;
  overflow: hidden;
}

.sct-scroll {
  overflow-x: auto;
  /* No sideways rubber-band (blank strip beside the first column) or swipe-back gesture
     when a horizontal scroll hits its edge; vertical scrolling still passes to the page. */
  overscroll-behavior-x: none;
}

.sct-row--header {
  background: var(--sct-header-bg);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.sct-row--header .sct-cell {
  min-height: 2.22222rem; /* 40px */
  gap: 0.33333rem;
}

/* Figma renders every header label UPPERCASE — applied here rather than
   shipping uppercased strings, since the dynamic dimension-column labels
   ("Channel"/"Platform"/"Campaign") come from the backend in title case. */
.sct-header-label {
  font-family: var(--font-family-base);
  font-size: calc(0.58333rem * var(--ohf-text-scale, 1)); /* 10.5px */
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--sct-header-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sct-header-label--muted {
  color: var(--sct-header-text-muted);
}

/* Dimension header cells host the pin toggle + drag handle; the label must be
   allowed to shrink and ellipsize so the controls always stay visible even at
   the narrow end of the resize range. */
.sct-cell--dimension {
  position: relative; /* containing block for the absolute resize handle */
}

.sct-row--header .sct-cell--dimension {
  justify-content: center;
}
.sct-cell--dimension .sct-header-label {
  flex: 0 1 auto;
  min-width: 0;
}
/* Header dimension cells must let the filter dropdown escape the cell box (the
   cell is otherwise overflow:hidden). The label keeps its own ellipsis and the
   resize handle stays inside, so nothing else spills. */
.sct-row--header .sct-cell--dimension {
  overflow: visible;
}

.sct-header-controls {
  display: inline-flex;
  align-items: center;
  gap: 0.16667rem;
  flex-shrink: 0;
}

/* ── Column pin ("fix in place") toggle — one per dimension header. Same
   tilted-thumbtack glyph the Scenario Results table uses, so "fix this column"
   looks identical across the app. Muted when unpinned, navy + upright-feel
   when pinned (the `filled` PinIcon variant). Styling matches that table's own
   `.or-th-pin-btn`/`.or-th-pin-icon` exactly (OptimisationResults.css) — a
   color-only hover/active (no background swap) and a tighter border-radius,
   rather than this table's previous, slightly different treatment. */
.sct-pin-wrap {
  display: inline-flex;
}

.sct-select-all-wrap {
  display: inline-flex;
}
.sct-pin-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0.11111rem;
  cursor: pointer;
  color: var(--sct-header-text-muted);
  border-radius: 0.16667rem;
  text-transform: none;
  letter-spacing: normal;
}
.sct-pin-btn:hover,
.sct-pin-btn--active {
  color: #0a1a40;
}
.sct-pin-btn:focus-visible {
  outline: 2px solid #0a1a40;
  outline-offset: 1px;
}
.sct-pin-icon {
  width: 0.83333rem; /* 15px */
  height: 0.83333rem;
}

/* ── Column resize handle — a thin grab strip on the right edge of each
   dimension header. Absolutely positioned so it never consumes flex width;
   the faint divider only shows on hover / while dragging. */
.sct-col-resize {
  position: absolute;
  top: 0;
  right: 0;
  width: 0.44444rem; /* 8px hit area */
  height: 100%;
  cursor: col-resize;
  touch-action: none;
  z-index: 3;
}
.sct-col-resize::after {
  content: "";
  position: absolute;
  top: 20%;
  right: 0.16667rem;
  width: 2px;
  height: 60%;
  border-radius: 1px;
  background: transparent;
}
.sct-col-resize:hover::after,
body.sct-col-resizing .sct-col-resize::after {
  background: var(--sct-header-text-muted);
}

/* Rightmost frozen dimension column — a single clean 1px divider marking the
   freeze/scroll boundary, so the pinned block reads as a distinct pane without
   any heavy shadow. Applies to header and body cells alike. */
.sct-cell--frozen-edge {
  border-right: 1px solid var(--sct-border);
}

/* While a resize drag is in flight, keep the col-resize cursor everywhere and
   suppress text selection so dragging over labels doesn't highlight them. */
body.sct-col-resizing {
  cursor: col-resize !important;
  user-select: none;
}

/* Column filter — funnel button anchoring the shared `ColumnFilter` popover
   (`src/components/ColumnFilter`), which portals itself to `document.body`
   and clamps its own position, so it's never clipped by `.sct-scroll`'s
   horizontal overflow. Icon size (0.83333rem, set on `ColFilterIcon` in the
   TSX) and this padding both match `.sct-pin-btn`/`.sct-pin-icon` beside it —
   the shared `DataTable`'s own filter glyph is smaller (0.625rem default),
   which read as noticeably tinier next to the pin icon sharing this header
   row; hover/radius otherwise still follow that button's chrome. */
.sct-filter-wrap {
  position: relative;
  display: inline-flex;
}
.sct-filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0.11111rem;
  cursor: pointer;
  border-radius: 0.16667rem;
}
.sct-filter-btn:hover svg path {
  fill: #0a1a40;
}

/* ── Numeric-column sort toggle — one per read-only metric header
   (MAT Spend/ROI/EFF/CPM). Same transparent, minimal look as the pin/filter
   header buttons; the caret direction/emphasis comes from `SortIcon` itself.
   `flex-shrink: 0` so it never collapses when the label ellipsizes. */
.sct-sort-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
}

.sct-checkbox--indeterminate {
  background: var(--color-white);
  border-style: dashed;
}

.sct-empty {
  margin: 0;
  padding: 1.77778rem 0.88889rem;
  text-align: center;
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1));
  color: var(--sct-empty-text);
}

/* ── Pagination footer ── */
.sct-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1.33333rem;
  padding: 0.77778rem 1.55556rem; /* 14px 28px */
  border-top: 1px solid var(--sct-border);
}

.sct-rows-per-page {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
}

.sct-rows-per-page-label {
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 400;
  color: var(--sct-empty-text);
  white-space: nowrap;
}

.sct-rpp-wrap {
  position: relative;
}

.sct-rpp-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  min-width: 2.77778rem;
  border: 1px solid var(--color-table-pagination-border);
  border-radius: 0.33333rem;
  background: var(--color-white);
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1));
  color: var(--color-table-pagination-ink);
  padding: 0.22222rem 0.55556rem;
  cursor: pointer;
}

.sct-rpp-chevron {
  width: 0.55556rem;
  height: 0.55556rem;
  flex-shrink: 0;
  color: var(--color-table-pagination-axis);
  transition: transform 0.15s ease;
}

.sct-rpp-chevron.is-open {
  transform: rotate(180deg);
}

.sct-rpp-dropdown {
  /* fixed + inline top/left/width from getBoundingClientRect() — a portal
     escaping the table's own clipping, not swappable for `absolute`. */
  position: fixed;
  transform: translateY(calc(-100% - 0.22222rem));
  background: var(--color-white);
  border: 1px solid var(--color-table-pagination-border);
  border-radius: 0.33333rem;
  box-shadow: 0 0.22222rem 0.66667rem var(--color-shadow-popover);
  overflow: hidden;
  z-index: 1000;
}

.sct-rpp-option {
  display: block;
  width: 100%;
  padding: 0.33333rem;
  background: none;
  border: none;
  font-family: var(--font-family-base);
  font-size: calc(0.69444rem * var(--ohf-text-scale, 1));
  color: var(--color-table-pagination-ink);
  cursor: pointer;
  text-align: center;
}

.sct-rpp-option:hover {
  background: var(--color-table-pagination-hover-bg);
}

.sct-rpp-option.is-selected {
  background: var(--color-table-pagination-selected-bg);
  font-weight: 700;
}

.sct-range {
  font-family: var(--font-family-base);
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1)); /* 13px */
  font-weight: 400;
  color: var(--sct-empty-text);
  white-space: nowrap;
}

.sct-page-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.33333rem;
  height: 1.33333rem;
  border: none;
  background: transparent;
  color: var(--sct-page-icon-active);
  cursor: pointer;
  padding: 0;
}

.sct-page-btn:disabled {
  color: var(--sct-page-icon);
  cursor: not-allowed;
}

.sct-page-icon {
  width: 0.83333rem;
  height: 0.83333rem;
  transform: rotate(-90deg);
}

.sct-page-icon--prev {
  transform: rotate(90deg);
}
/* Palette scoped to the "Set constraints" screen (values from Figma file
   UhXM9FKphZVFcmOL5CeMpr, node 194:9787). Declared locally rather than
   inherited from StartOptimisation.css/OptimisationHome.css — a separate
   page, same convention as those two. */
.sc-page {
  --ohf-text-scale: 1;

  --sc-bg: #f6f6f9;
  --sc-back-icon: #838996;
  --sc-back-text: #6b717d;
  --sc-eyebrow: #213b6e;
  --sc-badge-bg: #d7e2f5;
  --sc-badge-text: #213b6e;
  --sc-heading: #171f30;
  --sc-cta-border: #b1b8c5;
  --sc-cta-text: #0a1a40;
  --sc-cta-primary-bg: #0a1a40;
  --sc-cta-primary-text: #f9f5ed;

  min-height: 100vh;
  /* Clears the fixed Navbar + AppTabs, exactly as .ss-page does. Without it the
     breadcrumb strip renders at y=38 — underneath the navbar — and is invisible
     even though it is in the DOM and marked visible. */
  padding-top: var(--space-10);
  background: var(--sc-bg);
}

.sc-loader,
.sc-error {
  padding: var(--space-xxl) var(--space-xl);
}

.sc-body {
  max-width: 80rem;
  margin: 0 auto;
  padding: 1.66667rem 2.22222rem 2.66667rem;
  display: flex;
  flex-direction: column;
  gap: 0.77778rem;
}

/* ── Back link ── */
.sc-back {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.33333rem;
  border: none;
  background: transparent;
  padding: 0;
  color: var(--sc-back-text);
  font-family: var(--ohf-body);
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  font-weight: 600;
  line-height: 1.366;
  cursor: pointer;
}

.sc-back-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  color: var(--sc-back-icon);
  flex-shrink: 0;
}

/* ── Title row ── */
.sc-title-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.33333rem;
  flex-wrap: wrap;
  padding-top: 0.44444rem;
}

.sc-title-group {
  display: flex;
  flex-direction: column;
  gap: 0.33333rem;
}

.sc-title-meta {
  display: flex;
  align-items: center;
  gap: 0.66667rem;
}

.sc-eyebrow {
  font-family: var(--font-family-base);
  font-size: calc(0.66667rem * var(--ohf-text-scale)); /* 12px */
  font-weight: 700;
  letter-spacing: 0.08rem; /* 1.44px */
  color: var(--sc-eyebrow);
}

.sc-kind-badge {
  display: inline-flex;
  align-items: center;
  background: var(--sc-badge-bg);
  color: var(--sc-badge-text);
  border-radius: 0.33333rem;
  padding: 0.16667rem 0.5rem; /* 3px 9px */
  font-family: var(--font-family-base);
  font-size: calc(0.61111rem * var(--ohf-text-scale)); /* 11px */
  font-weight: 700;
}

.sc-title {
  margin: 0;
  font-family: var(--ohf-heading);
  font-size: calc(1.33333rem * var(--ohf-text-scale));
  font-weight: 500;
  line-height: 1.445;
  letter-spacing: -0.031875rem; /* -0.51px */
  color: var(--sc-heading);
}

.sc-title-actions {
  display: flex;
  align-items: center;
  gap: 1.33333rem;
}

.sc-action-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.44444rem;
  height: 2.22222rem;
  padding: 0 1.11111rem;
  border: 1px solid var(--sc-cta-border);
  border-radius: 0.22222rem;
  background: var(--color-white);
  color: var(--sc-cta-text);
  font-family: var(--ohf-body);
  font-weight: 600;
  font-size: calc(0.77778rem * var(--ohf-text-scale));
  cursor: pointer;
}

.sc-action-btn:hover:not(:disabled) {
  background: var(--color-bg-hover-light);
}

.sc-action-btn--primary {
  height: 2.27778rem; /* 41px */
  padding: 0 1.33333rem;
  border: none;
  background: var(--sc-cta-primary-bg);
  color: var(--sc-cta-primary-text);
  font-family: var(--ohf-body);
  font-weight: 600;
}

.sc-action-btn--primary:hover:not(:disabled) {
  /* Keep the primary's own dark background — otherwise the base
     `.sc-action-btn:hover` light background wins (same specificity, earlier in
     source) and the cream text disappears against it. `opacity` alone is the
     hover feedback. */
  background: var(--sc-cta-primary-bg);
  opacity: 0.92;
}

.sc-action-btn--primary:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.sc-action-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  flex-shrink: 0;
}

/* ── Portfolio scope: BRANDS sidebar + table row ── */
/* Only mounted when `data.brandTree` is non-null (see SetConstraints.tsx) —
   the sidebar (fixed 217px, ConstraintsBrandTree.css) sits to the left of
   the table column, 16px gap, matching Figma frame 250:8509. `min-width: 0`
   on the table column is required so its own `.sct-scroll` horizontal
   scroller (ConstraintsTable.css) absorbs overflow instead of the flex item
   refusing to shrink and pushing the page body into horizontal scroll
   (forbidden — src/index.css). */
.sc-content-row {
  display: flex;
  align-items: flex-start;
  gap: 0.88889rem; /* 16px */
}

.sc-table-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
}

/* Brand + combination labels are lowercase in the source data — see
   StartOptimisation/ScopeFieldSelect.css for why this is presentational only. */
.cbt-brand-name,
.cbt-combo {
  text-transform: capitalize;
}
.rcm-overlay {
  position: fixed;
  inset: 0;
  background: rgba(14, 15, 17, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
}
.rcm-modal {
  background: #fff;
  border-radius: 0.66667rem;
  width: min(42rem, 95vw);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 12px 40px rgba(16, 24, 40, 0.22);
  font-family: "Inter", var(--ohf-body), sans-serif;
  color: #0e0f11;
  overflow: hidden;
}
.rcm-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 1.11111rem 1.33333rem 0.66667rem;
}
.rcm-title {
  display: block;
  font-family: var(--ohf-display), serif;
  font-size: 1rem;
  color: #0e0f11;
}
.rcm-sub {
  display: block;
  margin-top: 0.11111rem;
  font-size: 0.72222rem;
  color: #6b6e76;
  text-transform: capitalize;
}
.rcm-close {
  border: none;
  background: transparent;
  font-size: 0.88889rem;
  color: #6b6e76;
  cursor: pointer;
  line-height: 1;
  padding: 0.22222rem;
}
.rcm-body {
  padding: 0.44444rem 1.33333rem 1.33333rem;
  overflow-y: auto;
}
.rcm-state {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 20rem;
  text-align: center;
  color: #6b6e76;
  font-size: 0.83333rem;
}
.rcm-chart-label {
  margin: 0.44444rem 0 0.11111rem;
  font-size: 0.72222rem;
  font-weight: 600;
  color: #3b3d42;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.rcm-chart-label--roi {
  margin-top: 0.88889rem;
}
.rcm-chart {
  width: 100%;
  height: auto;
}
.rcm-axis {
  stroke: #e6e8ee;
  stroke-width: 1;
}
.rcm-tick {
  fill: #9a9ca2;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}
.rcm-area {
  fill: rgba(26, 39, 68, 0.08);
  stroke: none;
}
.rcm-line {
  fill: none;
  stroke: #1a2744;
  stroke-width: 2;
}
.rcm-cur {
  stroke: #1e293b;
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
}
.rcm-rec {
  stroke: #0054d8;
  stroke-width: 1.5;
  stroke-dasharray: 2 3;
}
.rcm-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1.11111rem;
  margin-top: 0.66667rem;
  font-size: 0.72222rem;
  color: #3b3d42;
  font-variant-numeric: tabular-nums;
}
.rcm-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.33333rem;
}
.rcm-swatch {
  width: 0.88889rem;
  height: 0;
  border-top-width: 2px;
  border-top-style: dashed;
}
.rcm-swatch--cur {
  border-top-color: #1e293b;
}
.rcm-swatch--rec {
  border-top-color: #0054d8;
}
.rcm-roi-line {
  fill: none;
  stroke: #e05a2b;
  stroke-width: 2;
}
/* Recap Constraints modal — new optimizer Results screen (Figma 121-14592).
   Rendered inside `.or-page`, so the screen's `--ohf-*` fonts and theme CSS
   variables are inherited. */

.rcc-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: var(--color-backdrop-overlay, rgba(10, 26, 64, 0.45));
}

.rcc-modal {
  display: flex;
  flex-direction: column;
  width: min(76rem, 96vw);
  /* Fixed shell height, NOT content-driven: the body swaps a loader for a table
     whose row count changes with the page (and the last page is usually short),
     so a content-sized modal resized on load and on every page step. The table
     already fills and scrolls inside the body (see .rcc-body .dt-* below), so a
     stable shell just holds it still. 700px is sized to a full 10-row page —
     the default "Rows per page" — so a full table leaves no dead space and a
     short one (or another tab's shorter table) simply doesn't shrink it. */
  height: min(36.5rem, 90vh);
  overflow: hidden;
  background: var(--color-white, #ffffff);
  border-radius: 0.88889rem;
  box-shadow: var(--color-shadow-modal, 0 1.11111rem 3.33333rem rgba(10, 26, 64, 0.25));
}

/* ── Header ── */
.rcc-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  padding: 1.33333rem 1.66667rem 0.88889rem;
}

.rcc-title {
  margin: 0;
  font-family: "Inter", var(--ohf-body), sans-serif;
  font-size: calc(1.33333rem * var(--ohf-text-scale, 1));
  font-weight: 400;
  color: var(--sc-heading, #171f30);
  letter-spacing: -0.01em;
}

.rcc-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: none;
  background: none;
  color: var(--sc-heading, #171f30);
  cursor: pointer;
  border-radius: 0.22222rem;
  transition: background 0.15s;
}

.rcc-close:hover {
  background: var(--color-bg-hover-light, #f0f2f6);
}

.rcc-close-icon {
  width: 1.22222rem;
  height: 1.22222rem;
}

/* ── Info summary (two columns) ──*/
.rcc-info {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 0.66667rem 2.22222rem;
  padding: 0.44444rem 1.66667rem 1.11111rem;
  /* Chip diameter, shared with `.rcc-info-row`'s min-height below — see there. */
  --rcc-chip-size: 1.55556rem;
}

.rcc-info-col {
  display: flex;
  flex-direction: column;
  gap: 0.56667rem;
  min-width: max-content;
}

.rcc-info-col:last-child {
  min-width: 0;
}

.rcc-info-row {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
  /* Values inherit the row; the labels step down (`.rcc-info-label`). Kept as
     rem * --ohf-text-scale, the idiom the rest of this file uses, so the app's
     text-size preference still scales them — 14px at the default scale of 1. */
  font-size: calc(0.875rem * var(--ohf-text-scale, 1));
  /* Every row is chip-tall, whether or not it HAS a chip. The two columns share
     one `gap`, so without this the chipped rows (Target spend / Granularity) sat
     a chip-height further apart than the plain ones (Scenario name /
     description) — same gap, taller boxes. Equal heights make the pitch equal. */
  min-height: var(--rcc-chip-size);
}

.rcc-info-col:first-child .rcc-info-row {
  white-space: nowrap;
  flex-shrink: 0;
}

.rcc-info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--rcc-chip-size);
  height: var(--rcc-chip-size);
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--sc-badge-bg, #d7e2f5);
  color: var(--sc-eyebrow, #213b6e);
}

.rcc-info-icon-svg {
  width: 1.11111rem;
  height: 1.11111rem;
  display: block;
}

/* The chip used to hold a hardcoded `$` icon, which contradicted the scenario's
   own currency (the value beside it and the table's column units both come from
   `meta.currency`). It now renders that symbol as text, centred in the chip.
   Rendered only when a symbol is present. */
.rcc-info-currency {
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1));
  font-weight: 700;
  line-height: 1;
  /* Padding instead of `.rcc-info-icon`'s fixed box, with that box's size kept
     as the minimum: a one-character symbol still renders the same circle as
     before, just with more air around a smaller glyph, while a wider symbol
     (`R$`, `kr`, `zl`) grows the chip into a pill rather than being clipped —
     hence `border-radius` by length, which stays a circle while square. */
  box-sizing: border-box;
  width: auto;
  height: auto;
  min-width: var(--rcc-chip-size);
  min-height: var(--rcc-chip-size);
  padding: 0.22222rem 0.33333rem;
  border-radius: 62.5rem;
}

/* Same muted grey the table headers use (`.rcc-body .dt-table th` below, itself
   taken from the Portfolio Breakdown table) so the header's captions and the
   column captions read as one family. The values beside them keep `--sc-heading`. */
.rcc-info-label {
  color: #838996;
  font-size: calc(0.78125rem * var(--ohf-text-scale, 1)); /* 12.5px */
  white-space: nowrap;
  flex-shrink: 0;
}

/* Divider between the Granularity and Period pairs sharing one row. Faint
   enough to read as punctuation rather than as a value of its own; hidden from
   screen readers, which get the two label/value pairs as separate spans. */
.rcc-info-sep {
  color: var(--or-faint, #9a9ca2);
}

.rcc-info-value {
  color: #505869;
  font-size: calc(0.72222rem * var(--ohf-text-scale, 1));
}

.rcc-info-strong {
  font-weight: 600;
}

/* Ellipsis for an overflowing Scenario name / description value (up to 50 /
   200 chars — see `ScenarioDetailsCard.tsx`'s max lengths). `.rcc-info-row` is
   a flex row, whose items default to `min-width: auto`, so without this
   override the value would grow past the row instead of clipping — `min-width:
   0` lets it shrink down to the ellipsis. Full value still reachable via
   `HoverTooltip`, same convention as `.rcc-dim-text` for the table columns. */
.rcc-info-row .rcc-info-clip {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Tabs ── */
.rcc-tabs {
  display: flex;
  align-items: flex-end;
  gap: 0.44444rem;
  flex-shrink: 0;
  padding: 0 1.66667rem;
  border-bottom: 1px solid var(--color-border, #e3e6ee);
}

.rcc-tab {
  padding: 0.5rem 0.61111rem;
  border: none;
  background: none;
  font-family: var(--ohf-body, Arial, Helvetica, sans-serif);
  /* Sized into the modal's own type scale rather than above it: between the info row's
     values (0.72222rem) and labels (0.78125rem), and level with the table's dimension
     names (`.rcc-dim`, 0.75rem) — so the tabs read as navigation for the table without
     out-sizing everything but the title. Padding trimmed in proportion. */
  font-size: calc(0.75rem * var(--ohf-text-scale, 1));
  font-weight: 500;
  color: var(--color-text-muted, #6b7280);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.rcc-tab:hover {
  color: var(--sc-heading, #171f30);
}

.rcc-tab--active {
  color: var(--sc-eyebrow, #213b6e);
  border-bottom-color: var(--sc-eyebrow, #213b6e);
  font-weight: 700;
}

/* ── Body / table ── */
.rcc-body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  padding: 1.11111rem 1.66667rem 1.11111rem;
}

/* The modal shell keeps its fixed height, but the table inside it sizes to its ROWS: a
   short page (6 rows) ends right above the pagination instead of stretching to fill the
   body and leaving a blank band between the last row and the footer — any spare height
   collects below the pagination instead. Once the rows outgrow the body, every level
   below shrinks (`flex: 0 1 auto` + `min-height: 0`) and the scroll area scrolls, so
   the pagination is never pushed out of the modal. `max-height: 100%` can't be used for
   that: against a parent with auto height it resolves to `none`, and the rows would be
   clipped rather than scrolled. */
.rcc-body .dt-wrapper {
  flex: 0 1 auto;
  min-height: 0;
}

.rcc-body .dt-body {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.rcc-body .dt-inner-wrap {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.rcc-body .dt-pagination {
  flex-shrink: 0;
}

.rcc-body .dt-inner-h {
  flex: 0 1 auto;
  min-height: 0;
  max-height: none;
  /* Pulling past an edge (touchpad / touch) must not elastic-bounce the table and open a
     blank band above the header or beside the first column: the page behind this modal is
     scroll-locked, so there is nothing for the gesture to chain to and the browser would
     rubber-band the table itself. `none` keeps the header and cells fixed at every edge. */
  overscroll-behavior: none;
  scrollbar-width: thin;
  scrollbar-color: var(--color-scrollbar-thumb-soft) transparent;
}
.rcc-body .dt-inner-h::-webkit-scrollbar {
  display: block;
  width: 0.66667rem;
  height: 0.66667rem;
}
.rcc-body .dt-inner-h::-webkit-scrollbar-track {
  background: transparent;
  border: 0;
}
.rcc-body .dt-inner-h::-webkit-scrollbar-thumb {
  background-color: var(--color-scrollbar-thumb-soft);
  background-clip: content-box;
  border: 0.16667rem solid transparent;
  border-radius: var(--radius-pill);
}
.rcc-body .dt-inner-h::-webkit-scrollbar-thumb:hover {
  background-color: var(--color-scrollbar-thumb-soft-hover);
}
.rcc-body .dt-htrack,
.rcc-body .dt-vtrack {
  display: none;
}
/* The native bars above replace BOTH of the component's custom tracks — hiding only the
   horizontal one left its vertical thumb drawn beside the native vertical bar (two
   scrollers). Drop the gutter and header strip the component reserves for that thumb too. */
.rcc-body .dt-inner-wrap--vscroll .dt-inner-h {
  margin-right: 0;
}
.rcc-body .dt-inner-wrap--vscroll::before {
  content: none;
}

.rcc-body .dt-table tbody tr:hover td {
  background: var(--color-white, #ffffff);
}

.rcc-body .dt-th-btn:hover {
  background: none;
}

.rcc-body .dt-filter-wrap .dt-th-btn:hover svg path {
  fill: var(--or-navy, #0a1a40);
}

.rcc-state {
  padding: 3.33333rem 1.66667rem;
  text-align: center;
  color: var(--color-text-muted, #6b7280);
  font-size: calc(0.88889rem * var(--ohf-text-scale, 1));
}

.rcc-modal .rcc-cell {
  color: var(--sc-heading, #171f30);
}

/* Only the text/dimension columns (Channel / Platform / Campaign) are bold,
   and — as on the Portfolio Breakdown table — left-aligned under their header. */
.rcc-modal .rcc-dim {
  font-weight: 700;
  font-size: 0.75rem;
  text-align: left;
}

/* Ellipsis for an overflowing Channel/Platform/Campaign name — the full value
   is still reachable via `HoverTooltip` (see `dimRender` in
   RecapConstraintsModal.tsx). `display: block` is required for a `<span>`
   (an inline element otherwise ignores `overflow`/`text-overflow`) inside the
   fixed-width `<td>` the `tableLayout="fixed"` DataTable now renders. */
.rcc-modal .rcc-dim-text {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Numeric columns right-align and stay at regular weight. Font-size matches */
.rcc-modal .rcc-num {
  text-align: center;
  white-space: nowrap;
  font-weight: 400;
  font-size: 0.72222rem;
}

/* ── Header: match the Portfolio Breakdown table ─────────────────────────
   The breakdown card's hand-rolled `.or-table thead th` (OptimisationResults.css)
   and the shared `DataTable`'s `.dt-table th` had drifted apart — grey/black vs
   the card's warm tint + muted uppercase labels. These override the DataTable
   defaults with the breakdown table's values so the popup reads as part of the
   same screen. Scoped to `.rcc-body` so every other DataTable is untouched.
   The `--or-*` vars come from `.or-page`, which both recap modals render inside;
   literal fallbacks keep this block self-contained if that ever changes. */
.rcc-body .dt-table thead tr,
.rcc-body .dt-table th {
  background: var(--or-channel-tint, #faf9f6);
}

.rcc-body .dt-table th {
  font-size: 0.58333rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #7e7e7e;
  padding: 0.55556rem 0.55556rem 0.44444rem 0.83333rem;
  border-bottom: 1px solid var(--or-border, #e9eaf0);
  /* Full grid lines, dropped on the last column — as on `.or-table`. */
  border-right: 1px solid var(--or-border, #e9eaf0);
}

.rcc-body .dt-table thead tr th:last-child {
  border-right: none;
}

.rcc-body .dt-table td {
  border-right: 1px solid var(--or-border, #e9eaf0);
}

.rcc-body .dt-table tr td:last-child {
  border-right: none;
}

/* Dimension headers sit left over their text column; the numeric headers stay
   centred over theirs — the same split `.or-table` makes with `.or-th-metric`. */
.rcc-body .dt-table th[data-col-key="channel"],
.rcc-body .dt-table th[data-col-key="platform"],
.rcc-body .dt-table th[data-col-key="campaign"] {
  text-align: center;
}

.rcc-body .dt-table th[data-col-key="channel"] .dt-th-inner,
.rcc-body .dt-table th[data-col-key="platform"] .dt-th-inner,
.rcc-body .dt-table th[data-col-key="campaign"] .dt-th-inner {
  justify-content: center;
}

.rcc-body .dt-pagination {
  border: none;
  border-top: 1px solid var(--or-border, #e9eaf0);
  border-radius: 0;
  background: none;
  font-size: 0.69444rem;
  color: var(--or-muted, #6b6e76);
}

.rcc-body .dt-rows-label {
  white-space: nowrap;
}

.rcc-body .dt-rpp-trigger {
  border: 1px solid var(--or-border, #e9eaf0);
  border-radius: 0.33333rem;
  padding: 0.22222rem 0.55556rem;
  background: var(--or-card, #ffffff);
  font-size: 0.69444rem;
  color: var(--or-ink, #0e0f11);
  min-width: 2.77778rem;
}

.rcc-body .dt-rpp-chevron {
  width: 0.55556rem;
  height: 0.55556rem;
  color: var(--or-axis, #838996);
}

.rcc-body .dt-rpp-dropdown {
  background: var(--or-card, #ffffff);
  border: 1px solid var(--or-border, #e9eaf0);
  border-radius: 0.33333rem;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-popover);
}

.rcc-body .dt-rpp-option {
  font-size: 0.69444rem;
  color: var(--or-ink, #0e0f11);
}

.rcc-body .dt-rpp-option:hover {
  background: var(--or-bg, #f6f6f9);
}

.rcc-body .dt-rpp-option--selected {
  background: var(--or-combo-sel, #e1e7f4);
  font-weight: 700;
  color: var(--or-ink, #0e0f11);
}

.rcc-body .dt-page-info {
  min-width: 5rem;
  font-variant-numeric: tabular-nums;
}

.rcc-body .dt-nav-btn {
  color: var(--or-ink, #0e0f11);
  font-size: 1.11111rem;
}

.rcc-body .dt-nav-btn:disabled {
  color: var(--or-faint, #9a9ca2);
}
/* Portfolio Breakdown card's own "Recap Constraints" modal — reuses
   `.rcc-*` (shell/header/info) from RecapConstraintsModal.css and
   `.or-portfolio--split` / `.or-side` / `.or-tree*` (BRANDS sidebar) from
   OptimisationResults.css, already loaded by the page this modal only ever
   renders inside of. This file only fills the gaps those two leave for a
   fixed-height modal body: the split grid and sidebar need to fill/scroll
   within `.rcc-body` instead of growing with content like they do on the
   page's own card. */

.prc-modal {
  /* Wider than the tab-less single-cell modal to make room for the sidebar
     column without starving the table. */
  width: min(76rem, 96vw);
}

.prc-body {
  overflow: hidden;
}

/* `.or-portfolio--split` (OptimisationResults.css) sets `align-items: start`
   so the page's own sidebar/table size to their own content — there, a JS
   measurement caps the tree's scroll region to the table's height instead.
   This modal has no such measurement: the sidebar must stretch to match the
   table's height exactly. `.prc-split` and `.or-portfolio--split` are both
   single-class selectors of equal specificity, so which one wins would
   otherwise depend on CSS import/bundle order rather than intent — combining
   both classes in one selector forces this override to win regardless. */
.prc-split.or-portfolio--split {
  flex: 1;
  min-height: 0;
  align-items: stretch;
  /* One row pinned to the body's height. The table inside now sizes to its rows
     (RecapConstraintsModal.css's `.rcc-body .dt-*`), so an implicit `auto` row would
     grow with a long table and push the pagination out of the modal; `minmax(0, 1fr)`
     keeps the row at the body's height so the table shrinks and scrolls instead. */
  grid-template-rows: minmax(0, 1fr);
}

.prc-side {
  min-height: 0;
  overflow: hidden;
  /* Boxed as one panel instead of `.or-side`'s single right-edge divider — on
     the page that divider separates the sidebar from the table inside a shared
     card, but here the modal has no card ground to sit on, so the panel needs
     its own frame. `border-right: none` isn't enough to undo the divider: it
     would erase this border's own right edge, hence the full `border` reset. */
  border: 1px solid var(--or-border, #e9eaf0);
  padding: 0.66667rem;
}

/* Only the brand/combo list scrolls once it outgrows the table's height —
   the "Brands" title and search box above it (siblings inside `.prc-side`)
   stay fixed in place instead of scrolling away with it. */
.prc-side .prc-tree {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.prc-table.or-portfolio-table {
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-self: stretch;
}

.prc-table .rcc-state {
  flex: 1;
}

/* Adds the shared `SearchClearButton` (×) to this modal's own Brands search —
   matching the Performance Recap modal's own Brands search on the Set
   Constraints screen, which already has one. `SearchClearButton` positions
   itself absolutely against its wrapper (see that component's own doc
   comment), so `.or-side-search` needs `position: relative` and the input
   needs right padding to clear it — neither of which the shared `.or-side-*`
   rules in OptimisationResults.css set, since the page's own Portfolio
   Breakdown sidebar (which reuses those same classes) has no clear button.
   Scoped to `.prc-side` so that page search box is unaffected. */
.prc-side .or-side-search {
  position: relative;
}

.prc-side .or-side-search-input {
  padding-right: 1.55556rem;
}
/* "Scenario Results" screen — pixel-matched to Figma frame 56:4831.
   Colours, fonts and sizes are the frame's own values; sizes are Figma px ÷ 18
   -> rem, the scale the other optimiser screens use. Fonts: Fraunces
   (--ohf-heading), DM Serif Display (--ohf-display), Manrope (--ohf-body), and
   the app-global Inter. */
.or-page {
  --or-bg: #f6f6f9;
  --or-card: #ffffff;
  --or-border: #e9eaf0;
  --or-crumb-label: #6b6e76;
  --or-crumb-value: #0e0f11;
  --or-crumb-sep: #b9bcc4;
  --or-eyebrow: #213b6e;
  --or-ink: #0e0f11;
  --or-heading: #171f30;
  --or-muted: #6b6e76;
  --or-faint: #9a9ca2;
  --or-axis: #838996;
  --or-navy: #0a1a40;

  --or-st: #1a2744; /* short term */
  --or-lt: #7fa8e0; /* long term */
  --or-plain: #c4c4c4; /* plain optimized bar (spend / mroi) */
  --or-mat: #c5c5c5; /* muted MAT bar */
  --or-combo-sel: #e1e7f4; /* selected combination bg */
  --or-toggle-bg: #f1efea; /* view-by toggle container */
  --or-badge-bg: #fcebcc;
  --or-badge-fg: #9f6700;
  /* Row-label column tint on `.or-table` — same values as the Comparison
     screen's `--cmp-channel-tint` / `--cmp-group-cell`, for visual parity
     between the two screens' breakdown tables. */
  --or-channel-tint: #faf9f6;
  --or-group-cell: #fbfaf7;

  --or-up: #0fa870;
  --or-down: #e15552;
  --or-flat: #8b8b8b;

  min-height: 100vh;
  /* Clear the fixed Navbar (height var(--space-10)) — same convention as
     .oh-page / .ss-page. Without it the breadcrumb bar hides under the Navbar. */
  padding-top: var(--space-10);
  background: var(--or-bg);
  font-family: "Inter", var(--ohf-body), sans-serif;
  color: var(--or-ink);
}

.or-loader,
.or-error {
  padding: var(--space-xxl) var(--space-xl);
}

/* ── Download-in-progress overlay ──────────────────────────────────────────
   A PNG download clones the card and runs html2canvas over it, which can
   take a visible moment on a large Portfolio Breakdown — this blurs/dims the
   page and blocks input for that stretch so the click doesn't look dead.
   z-index above ResponseCurveModal (2000, the highest on this page) since a
   download can be triggered from underneath an open modal. */
.or-download-overlay {
  position: fixed;
  inset: 0;
  z-index: 2100;
  background: rgba(14, 15, 17, 0.15);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

/* ── Top breadcrumb bar ── */
.or-crumbbar {
  background: var(--or-card);
  border-bottom: 1px solid var(--or-border);
  /* Pinned under the app chrome while the page scrolls — same rule, offset and
     min-height as Set Constraints' .scb-strip; see its comment. */
  position: sticky;
  top: var(--app-header-stack-h);
  z-index: 100;
  min-height: var(--app-scope-strip-h);
}
.or-crumbbar-inner {
  max-width: 80rem;
  margin: 0 auto;
  padding: 0.72222rem 2.22222rem;
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.44444rem;
  font-size: 0.69444rem;
  min-width: 0;
  overflow: hidden;
}
/* One line, always: every segment keeps its natural width, and only the typed-name
   segments (Scenario / Portfolio — `.or-crumb--fluid`) give way when the bar runs out of room,
   ellipsizing their value rather than wrapping the bar onto a second line. With room
   to spare the name is shown in full; the full name is on hover only once clipped. */
.or-crumbbar-inner > * {
  flex: 0 0 auto;
  white-space: nowrap;
}
.or-crumb {
  display: inline-flex;
  gap: 0.33333rem;
}
.or-crumbbar-inner > .or-crumb--fluid {
  flex-shrink: 1;
  min-width: 0;
}
.or-crumb--fluid .or-crumb-label {
  flex-shrink: 0;
}
.or-crumb--fluid .or-crumb-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.or-crumb-label {
  color: var(--or-crumb-label);
}
.or-crumb-value {
  color: var(--or-crumb-value);
  font-weight: 600;
}
/* "+(8)" counter trailing the two spelled-out scope values (see summariseCrumb).
   Carries the label's lighter colour so the segment still reads as
   "Brand Axe, Bango" first and the count as the aside it is. */
.or-crumb-more {
  margin-left: 0.22222rem;
  font-weight: 500;
  color: var(--or-crumb-label);
  font-variant-numeric: tabular-nums;
}
.or-crumb-sep {
  color: var(--or-crumb-sep);
}

/* ── Body ── */
.or-body {
  max-width: 80rem;
  margin: 0 auto;
  padding: 1.33333rem 2.22222rem 2.66667rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.or-back {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem;
  border: none;
  background: transparent;
  padding: 0;
  color: var(--or-muted);
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.77778rem;
  font-weight: 600;
  cursor: pointer;
}
.or-back-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  color: var(--or-axis);
}

/* ── Head (eyebrow + title + compare) ── */
.or-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.or-eyebrow-row {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
  margin-bottom: 0.22222rem;
}
.or-eyebrow {
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.66667rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--or-eyebrow);
}
.or-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.11111rem 0.5rem;
  border-radius: 0.33333rem;
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.61111rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}
.or-badge--portfolio {
  background: var(--or-badge-bg);
  color: var(--or-badge-fg);
}
.or-badge--single_cell {
  background: var(--or-combo-sel);
  color: var(--or-eyebrow);
}
.or-title {
  margin: 0;
  font-family: var(--ohf-heading), serif;
  font-size: 1.33333rem;
  font-weight: 500;
  color: var(--or-heading);
}
.or-compare {
  display: inline-flex;
  align-items: center;
  gap: 0.55556rem;
  background: var(--or-navy);
  color: #fff;
  border: none;
  border-radius: 0.44444rem;
  padding: 0.61111rem 1.11111rem;
  font-family: var(--ohf-body);
  font-size: 0.72222rem;
  font-weight: 600;
  cursor: pointer;
}
.or-compare-icon {
  width: 1rem;
  height: 1rem;
  color: #fff;
}

/* ── Pending ── */
.or-pending {
  background: var(--or-card);
  border: 1px solid var(--or-border);
  border-radius: 0.66667rem;
  padding: 2rem;
  text-align: center;
}
.or-pending-title {
  margin: 0 0 0.44444rem;
  font-family: var(--ohf-display), serif;
  font-size: 1.11111rem;
  color: var(--or-heading);
}
.or-pending-text {
  margin: 0 auto;
  max-width: 30rem;
  font-size: 0.83333rem;
  color: var(--or-muted);
}

/* ── KPI card (single connected, divided) ── */
.or-kpis {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  background: var(--or-card);
  border: 1px solid var(--or-border);
  border-radius: 0.55556rem;
  overflow: hidden;
}
.or-kpi {
  padding: 1rem 1.22222rem;
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
  border-left: 1px solid var(--or-border);
}
.or-kpi:first-child {
  border-left: none;
}
.or-kpi-label {
  display: inline-flex;
  align-items: center;
  gap: 0.27778rem;
  font-size: 0.58333rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--or-faint);
}
.or-kpi-value {
  font-family: var(--ohf-body), sans-serif;
  font-size: 1.27778rem;
  font-weight: 600;
  color: var(--or-ink);
  font-variant-numeric: tabular-nums;
}
/* Matches the KPI info icon size on the Scenario Comparison page
   (`.cmp-kpi-info-btn .ib-icon` in OptimisationComparison.css) — this page's
   default `.ib-icon` size (14px, from InfoButton.css) read visibly larger
   next to it. */
.or-kpi-info-btn .ib-icon {
  width: 0.72222rem;
  height: 0.72222rem;
}

/* ── Delta ── */
.or-delta {
  display: inline-flex;
  align-items: center;
  gap: 0.22222rem;
  font-size: 0.66667rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.or-delta--up {
  color: var(--or-up);
}
.or-delta--down {
  color: var(--or-down);
}
.or-delta--flat {
  color: var(--or-flat);
}
.or-delta-icon {
  width: 0.72222rem;
  height: 0.5rem;
}

/* ── Card ── */
.or-card {
  background: var(--or-card);
  border: 1px solid var(--or-border);
  border-radius: 0.66667rem;
  padding: 1.22222rem 1.44444rem 1.55556rem;
  display: flex;
  flex-direction: column;
  gap: 1.33333rem;
}
.or-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}
.or-card-head--wrap {
  flex-wrap: wrap;
}
.or-card-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 400;
  color: var(--or-ink);
}
.or-card-sub {
  margin: 0.16667rem 0 0;
  font-size: 0.66667rem;
  color: var(--or-muted);
}

/* ── Legend ── */
.or-legend {
  display: flex;
  align-items: center;
  gap: 0.88889rem;
}
.or-legend--wide {
  flex-wrap: wrap;
  gap: 0.77778rem;
}
.or-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.33333rem;
  font-size: 0.63889rem;
  color: var(--or-muted);
}
/* Legend swatches — sizes/colours from Figma node 228:31065 (legend row):
   the two term chips are 10×10 @ 2px radius; the Optimized/MAT chips are
   20×10 @ 3px radius. */
.or-swatch {
  width: 0.55556rem; /* 10px */
  height: 0.55556rem;
  border-radius: 0.11111rem; /* 2px */
  flex-shrink: 0;
}
.or-swatch--st {
  background: var(--or-st);
}
.or-swatch--lt {
  background: var(--or-lt);
}
.or-swatch--opt2 {
  width: 1.11111rem; /* 20px */
  border-radius: 0.16667rem; /* 3px */
  background: linear-gradient(90deg, var(--or-st) 55%, var(--or-lt) 55%);
}
/* MAT chip: the SAME navy+blue split as Optimized, muted to 40% opacity
   (Figma swatch frame 350:34437 has opacity 0.4) — deliberately NOT a flat
   grey block, matching how the design conveys "muted". */
.or-swatch--mat {
  width: 1.11111rem; /* 20px */
  border-radius: 0.16667rem; /* 3px */
  background: linear-gradient(90deg, var(--or-st) 55%, var(--or-lt) 55%);
  opacity: 0.4;
}
.or-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.44444rem;
  height: 1.44444rem;
  border: none;
  background: transparent;
  color: var(--or-navy);
  cursor: pointer;
  border-radius: 0.22222rem;
}
.or-icon-btn:hover {
  background: #f2f3f7;
}

/* ── Results Breakdown ── */
/* Brand search box atop the portfolio "Results Breakdown" chart — same
   bordered pill as the Portfolio Breakdown table's `.or-side-search`, sized
   to sit comfortably in a card header rather than a narrow sidebar. */
.or-bcol-searchbar {
  display: flex;
  align-items: center;
  gap: 0.44444rem;
  max-width: 16rem;
  border: 1px solid var(--or-border);
  border-radius: 0.44444rem;
  padding: 0.44444rem 0.55556rem;
}
.or-bcol-search-icon {
  width: 0.77778rem;
  height: 0.77778rem;
  color: var(--or-axis);
  flex-shrink: 0;
}
.or-bcol-search-input {
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.72222rem;
  color: #757575;
  width: 100%;
}
.or-breakdown {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.55556rem;
}
/* Overlaid on the (now all-hidden-row) grid when a search matches nothing —
   the grid itself stays mounted underneath, unhidden rows and all, so the
   download image is unaffected by the search (see `PAGE_HIDDEN_SELECTOR`);
   `data-html2canvas-ignore` keeps this banner itself out of that capture. */
.or-bcol-no-match {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 0.72222rem;
  font-size: 0.77778rem;
  font-weight: 500;
  color: var(--or-faint);
}
.or-bcol {
  display: flex;
  flex-direction: column;
  gap: 0.66667rem;
}
.or-bcol-title {
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.77778rem;
  font-weight: 700;
  color: var(--or-ink);
}
.or-bcol-rows {
  display: flex;
  flex-direction: column;
  gap: 0.72222rem;
}
/* Reserve a full page's worth of rows (the currently-selected brands-per-page,
   via `--bcol-page-size` set inline in the TSX) so the visible row count
   shrinking — a shorter last page, or a search match filtering rows down —
   doesn't shrink the card and pull its controls up with it. Only applied once
   the row count can actually vary (see `BrandColumn`'s `stableHeight` prop):
   a portfolio with brands <= one page and no active search has nothing that
   varies, so it shouldn't get padded with blank space it doesn't need.
   1.44444rem = `.or-bar--breakdown`'s fixed bar height, the tallest thing in a
   row; 0.72222rem = this container's own row gap above. */
.or-bcol-rows--stable-height {
  min-height: calc(
    var(--bcol-page-size) * 1.44444rem + (var(--bcol-page-size) - 1) * 0.72222rem
  );
}
.or-bcol-row {
  display: grid;
  /* brand · bar track (1fr) · value (fixed). The bar track lines up with the
     axis ticks below (same 3 tracks), so bar length == axis position. */
  grid-template-columns: 2.66667rem 1fr 5rem;
  align-items: center;
  gap: 0.44444rem;
}
.or-bcol-brand {
  font-size: 0.69444rem;
  font-weight: 500;
  color: #3b3d42;
  text-transform: capitalize;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.or-bcol-barwrap {
  min-width: 0;
  display: flex;
}
.or-bcol-val {
  text-align: right;
  font-family: var(--ohf-display), serif;
  font-size: 0.94444rem;
  color: var(--or-ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.or-bcol-axis {
  display: grid;
  /* Same 3 tracks AND the same column gap as .or-bcol-row so the ticks (middle)
     span exactly the bar track; the value pad (right) keeps the last tick off
     the value column. */
  grid-template-columns: 2.66667rem 1fr 5rem;
  gap: 0.44444rem;
  margin-top: 0.16667rem;
  border-top: 1px solid #e6e8ee;
  padding-top: 0.27778rem;
}
.or-bcol-ticks {
  display: flex;
  justify-content: space-between;
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.61111rem;
  color: var(--or-axis);
}
.or-bcol-unit {
  text-align: center;
  /* Match the axis's left (brand) and right (value) pads so the unit label
     centres under the ticks/bar track, not the whole row. */
  padding-left: 2.66667rem;
  padding-right: 5rem;
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.61111rem;
  color: var(--or-axis);
}

/* ── Bars (shared) ── */
/* Figma draws these as full pill-shaped bars (fully rounded caps at both
   ends), not the slightly-squared 3px radius this used to have. */
.or-bar {
  display: inline-flex;
  align-items: stretch;
  height: 0.72222rem;
  border-radius: 999px;
  overflow: hidden;
  min-width: 0.16667rem;
  flex-shrink: 0;
}
.or-bar--muted {
  height: 0.5rem;
}
.or-bar--empty {
  background: transparent;
}
/* Every "Results Breakdown" chart bar — single-cell's 2-bar MAT-vs-scenario
   chart and the portfolio's 4-column per-brand chart — confirmed against the
   raw Figma node data for both (single-cell node 985:43486, portfolio node
   418:31167): a visibly taller bar (26px) with a small fixed 5px corner
   radius (not the pill shape every small per-row bar on this page uses) and
   a real ~4px gap between the ST/LT segments, each independently rounded
   rather than clipped to one continuous pill. */
.or-bar--breakdown {
  height: 1.44444rem;
  border-radius: 0.27778rem;
  overflow: visible;
  gap: 0.22222rem;
}
.or-bar--breakdown .or-seg {
  border-radius: 0.27778rem;
}
.or-seg {
  display: block;
}

/* ── Results Breakdown: hoverable segments ────────────────────────────────
   Pointing at a segment lifts it clear of the bar while its siblings recede,
   so the part being read is unmistakable in a bar whose pieces otherwise butt
   together. Only `.or-bar--breakdown` segments get this — it already sets
   `overflow: visible`, which is what lets a lifted segment and its shadow
   escape the bar instead of being clipped at its edge. */
.or-seg--interactive {
  cursor: pointer;
  transform-origin: center;
  transition:
    transform var(--motion-duration-normal) var(--motion-easing-spring),
    box-shadow var(--motion-duration-normal) var(--motion-easing-standard),
    opacity var(--motion-duration-normal) var(--motion-easing-standard);
}

.or-seg--lifted {
  /* Scaled on Y only: growing it on X would change the segment's apparent
     VALUE, which is the one thing a bar chart may not misreport. */
  transform: translateY(-0.16667rem) scaleY(1.18);
  box-shadow: 0 0.33333rem 0.66667rem var(--color-bar-seg-lift-shadow);
  position: relative;
  z-index: 1;
}

.or-seg--dimmed {
  opacity: 0.45;
}

.or-seg--interactive:focus-visible {
  outline: var(--space-0-5) solid var(--or-navy);
  outline-offset: var(--space-0-4);
}

/* The readout itself — portaled to <body>, so positioned in viewport
   coordinates and anchored to the segment's top-centre by the transform. */
.or-segtip {
  position: fixed;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-md);
  /* `background` is set inline, to the hovered segment's own colour — a fixed
     surface named one series while describing another. See `BarBody`. */
  box-shadow: 0 var(--space-0-8) var(--space-lg) var(--color-bar-tip-shadow);
  font-family: var(--font-family-base);
  white-space: nowrap;
  /* Sits above the segment, centred on it. `pointer-events: none` matters:
     without it the tooltip can land under the cursor, fire mouseleave on the
     segment, and flicker itself in and out. */
  transform: translate(-50%, calc(-100% - var(--space-sm)));
  pointer-events: none;
  animation: or-segtip-in var(--motion-duration-fast) var(--motion-easing-enter) both;
}

.or-segtip-label {
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-bar-tip-muted);
}

.or-segtip-value {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-bold);
  color: var(--color-bar-tip-text);
}

.or-segtip-share {
  font-size: var(--font-size-2xs);
  color: var(--color-bar-tip-muted);
}

/* A pale segment (long term, and the grey plain/MAT fills) takes dark ink —
   the cream above is unreadable on it. Which set applies is decided from the
   surface's measured luminance, not from the series name, so a palette change
   cannot leave the readout illegible. */
.or-segtip--on-light .or-segtip-value {
  color: var(--color-bar-tip-text-on-light);
}

.or-segtip--on-light .or-segtip-label,
.or-segtip--on-light .or-segtip-share {
  color: var(--color-bar-tip-muted-on-light);
}

/* Flipped under the segment when there is no room above it — see `show()`. */
.or-segtip--below {
  transform: translate(-50%, var(--space-sm));
  animation-name: or-segtip-in-below;
}

@keyframes or-segtip-in {
  from {
    opacity: 0;
    transform: translate(-50%, calc(-100% - var(--space-0-5)));
  }
  to {
    opacity: 1;
    transform: translate(-50%, calc(-100% - var(--space-sm)));
  }
}

@keyframes or-segtip-in-below {
  from {
    opacity: 0;
    transform: translate(-50%, var(--space-0-5));
  }
  to {
    opacity: 1;
    transform: translate(-50%, var(--space-sm));
  }
}

@media (prefers-reduced-motion: reduce) {
  .or-seg--interactive {
    transition: none;
  }
  .or-seg--lifted {
    /* No lift, but the emphasis must survive — the sibling dimming and the
       readout still carry it. */
    transform: none;
  }
  .or-segtip {
    animation: none;
  }
}
.or-seg--st {
  background: var(--or-st);
}
.or-seg--lt {
  background: var(--or-lt);
}
.or-seg--plain {
  background: var(--or-plain);
}
.or-seg--matgrey {
  background: var(--or-mat);
}

/* Table-row bars (`Bar` with `rail`) — the `{Level} breakdown` / `Portfolio
   breakdown` tables (via `MetricCell`) draw the proportional fill inside a
   fixed-width faint rail/track, per Figma node 228:31065. The rail is the
   same width for every row in a column (enforced by the fixed grid track on
   `.or-mcell--bars .or-mcell-row`, not by this element itself). Distinct
   from `.or-bar`/`.or-bar--breakdown` above, which the Results Breakdown
   chart (BrandColumn / .or-scbreak) still uses unchanged. */
.or-rail {
  display: flex;
  align-items: stretch;
  width: 100%;
  border-radius: 999px;
  overflow: hidden;
  flex-shrink: 0;
}
.or-rail--opt {
  height: 0.55556rem;
  background: rgba(0, 0, 0, 0.05);
}
.or-rail--mat {
  height: 0.44444rem;
  background: rgba(0, 0, 0, 0.04);
}
.or-rail--empty {
  background: transparent;
}
.or-rail-fill {
  display: flex;
  align-items: stretch;
  height: 100%;
  min-width: 0.16667rem;
  border-radius: 999px;
  overflow: hidden;
}
/* MAT (bottom) row is "muted": Figma node 228:31065 sets the navy+blue MAT
   fill frame to opacity 0.4 (same treatment as the "MAT · bottom, muted"
   legend chip). Scoped to the stacked navy+blue fill only — the plain grey
   Spend/MROI MAT bar stays full-opacity, exactly as in Figma. */
.or-rail--mat .or-rail-fill:has(.or-seg--st) {
  opacity: 0.4;
}

/* ── Portfolio breakdown ── */
.or-portfolio--split {
  display: grid;
  grid-template-columns: 13.88889rem 1fr;
  /* `stretch` (the default) so `.or-side` fills the row's full height —
     matching `.or-portfolio-table` when the table is the taller of the two
     (otherwise the sidebar's border stops short of the table's bottom edge).
     `.or-portfolio-table` opts out via `align-self: start` below so an
     unbounded "Brands" tree stretching `.or-side` taller than the table
     doesn't inflate the table to match — the JS below measures
     `.or-portfolio-table` to cap the tree's own scroll region, so that
     measurement must stay the table's intrinsic content height. */
  align-items: stretch;
}
.or-portfolio-table {
  min-width: 0;
  align-self: start;
}

/* Sidebar */
.or-side {
  display: flex;
  flex-direction: column;
  gap: 0.66667rem;
  border-right: 1px solid var(--or-border);
  padding-right: 1rem;
}
.or-side-title {
  font-size: 0.58333rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--or-faint);
}
.or-side-search {
  display: flex;
  align-items: center;
  gap: 0.44444rem;
  border: 1px solid var(--or-border);
  border-radius: 0.44444rem;
  padding: 0.44444rem 0.55556rem;
}
.or-side-search-icon {
  width: 0.77778rem;
  height: 0.77778rem;
  color: var(--or-axis);
  flex-shrink: 0;
}
.or-side-search-input {
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.72222rem;
  color: #757575;
  width: 100%;
}
.or-tree-scroll {
  /* Grows to fill whatever extra height `.or-side` picks up from being
     stretched to match a taller table (see `.or-portfolio--split` above),
     instead of leaving that space as a dead gap below the tree. Plain native
     scroll (not the `CustomScrollbar` pill component) — matches
     `PortfolioRecapConstraintsModal`'s own Brands tree (`.prc-tree` in
     PortfolioRecapConstraintsModal.css), which scrolls the same way, so the
     "Brands" sidebar reads as the same control in both places. Both sit
     inside `.or-page`, so this picks up that page's own thin scrollbar skin
     (index.css) automatically — no extra styling needed here. */
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}
.or-tree {
  display: flex;
  flex-direction: column;
  gap: 0.11111rem;
}
.or-tree-no-match {
  font-size: 0.69444rem;
  font-weight: 500;
  color: var(--or-faint);
  text-align: center;
  padding: 0.66667rem 0.22222rem;
}
.or-tree-head {
  display: flex;
  align-items: center;
  gap: 0.33333rem;
  width: 100%;
  border: none;
  background: transparent;
  padding: 0.38889rem 0.22222rem;
  cursor: pointer;
}
.or-tree-chevron {
  width: 0.83333rem;
  height: 0.83333rem;
  color: var(--or-axis);
  transform: rotate(-90deg);
  transition: transform 0.15s ease;
  flex-shrink: 0;
}
.or-tree-chevron.is-open {
  transform: rotate(0deg);
}
.or-tree-brandname {
  font-size: 0.72222rem;
  font-weight: 700;
  color: var(--or-ink);
  flex: 1;
  text-align: left;
  text-transform: capitalize;
}
.or-tree-count {
  font-size: 0.58333rem;
  font-weight: 600;
  color: var(--or-faint);
  background: #f1f2f6;
  border-radius: 0.66667rem;
  padding: 0.05556rem 0.33333rem;
}
.or-tree-combos {
  display: flex;
  flex-direction: column;
  gap: 0.11111rem;
  padding-left: 1.16667rem;
}
.or-tree-combo {
  text-align: left;
  border: none;
  background: transparent;
  border-radius: 0.38889rem;
  padding: 0.38889rem 0.55556rem;
  font-size: 0.69444rem;
  font-weight: 500;
  color: #3b3d42;
  cursor: pointer;
  line-height: 1.3;
  text-transform: capitalize;
}
.or-tree-combo:hover {
  background: #f4f5f9;
}
.or-tree-combo.is-active {
  background: var(--or-combo-sel);
  color: var(--or-eyebrow);
  font-weight: 600;
}

/* View-by toggle */
.or-viewby {
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem;
}
.or-viewby-label {
  font-size: 0.61111rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--or-faint);
}
.or-viewby-toggle {
  display: inline-flex;
  background: var(--or-toggle-bg);
  border-radius: 0.44444rem;
  padding: 0.16667rem;
  gap: 0.11111rem;
}
.or-viewby-btn {
  border: none;
  background: transparent;
  border-radius: 0.33333rem;
  padding: 0.27778rem 0.72222rem;
  font-size: 0.69444rem;
  font-weight: 600;
  color: var(--or-muted);
  cursor: pointer;
}
.or-viewby-btn.is-active {
  background: #fff;
  color: var(--or-ink);
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.08);
}

/* Chart/table view-mode toggle — same segmented-control shape as
   .or-viewby-toggle/.or-levels, icon buttons instead of text. */
.or-modetoggle {
  display: inline-flex;
  background: var(--or-toggle-bg);
  border-radius: 0.44444rem;
  padding: 0.16667rem;
  gap: 0.11111rem;
  flex-shrink: 0;
}
.or-mode-btn-wrap {
  display: inline-flex;
}
.or-mode-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.66667rem;
  height: 1.66667rem;
  border: none;
  background: transparent;
  border-radius: 0.33333rem;
  color: var(--or-muted);
  cursor: pointer;
}
.or-mode-btn.is-active {
  background: #fff;
  color: var(--or-ink);
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.08);
}
.or-mode-icon {
  width: 0.77778rem;
  height: 0.77778rem;
}

/* Table */
.or-table-wrap {
  overflow-x: auto;
  /* No sideways rubber-band (blank strip beside the first column) or swipe-back gesture
     when a horizontal scroll hits its edge; vertical scrolling still passes to the page. */
  overscroll-behavior-x: none;
}
.or-table {
  width: 100%;
  /* Column widths come from the `<colgroup>` in JSX, not from cell content —
     with the default `auto` layout, a sort click swaps which rows are hidden
     by pagination, which changed which names the browser measured for each
     column's width and made columns visibly resize on every sort. `fixed`
     layout keeps every column's width constant regardless of which rows/text
     are currently rendered; overflow text is ellipsized instead of growing
     the column (see `.or-td-chan-text` / `.or-td-dimval`), and the wrapper's
     overflow-x:auto still takes over with a real horizontal scrollbar once
     there's genuinely not enough room. */
  table-layout: fixed;
  min-width: max-content;
  /* `separate` (not `collapse`) — matches the Comparison screen's `.cmp-table`
     and is what lets the per-cell `border-right` grid lines below render
     cleanly alongside the pinned/sticky dimension columns. */
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.72222rem;
}
/* Small-caps labels (KPI eyebrows, metric column headers) are uppercased in JS by
   `capsLabel()` instead of by `text-transform`, which would flatten the deliberate
   lowercase "m" in "mROI" to "MROI". This opts those elements out of the transform
   their container applies. */
.or-caps {
  text-transform: none;
}
.or-table thead th {
  text-align: left;
  font-size: 0.58333rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #7e7e7e;
  /* Top padding matches the Comparison screen's `.cmp-table th` (`0.55556rem`
     all round) — this was `0` before, which is why the header row read
     visibly shorter than Comparison's. */
  padding: 0.55556rem 0.55556rem 0.44444rem 0.83333rem;
  border-bottom: 1px solid var(--or-border);
  /* Full grid lines (right + bottom on every cell), same as the Comparison
     screen's `.cmp-table` — dropped on the last column below. */
  border-right: 1px solid var(--or-border);
  white-space: nowrap;
  /* Establishes the containing block the `left` offsets for pinned/"fixed"
     dimension columns resolve against. */
  position: relative;
  /* Whole header row is tinted — dim columns AND metric columns (Spend/
     Sales/Volume/ROI/mROI) alike. The body (`.or-table tbody td` below)
     carries the same grey by default too; only pinned/frozen columns turn
     white (`.or-table tbody td.or-td-dim--pinned`), which is why that rule
     is scoped to `td` — a pinned column's header stays on this grey. */
  background: var(--or-channel-tint);
}
.or-table thead tr th:last-child {
  border-right: none;
}
.or-table thead .or-th-label {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Numeric metric headers (Spend/Sales/Volume/ROI/MROI) are centered over the
   column; the values/bars underneath stay right-aligned (see `.or-mcell-row`). */
.or-table thead th.or-th-metric {
  text-align: center;
}
/* Pin ("fix"/unfix column) + filter controls, grouped next to the header
   label — Excel-style column affordances for the Channel/Platform/Campaign
   dimension columns. */
.or-th-dim-controls {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  gap: 0.22222rem;
  margin-left: 0.33333rem;
}
.or-th-sort-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
  vertical-align: middle;
}
.or-th-metric .or-th-sort-btn {
  margin-left: 0.22222rem;
}
.or-th-pin-wrap {
  display: inline-flex;
  align-items: center;
}
.or-th-pin-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0.11111rem;
  cursor: pointer;
  color: var(--or-faint);
  border-radius: 0.16667rem;
  text-transform: none;
  letter-spacing: normal;
}
.or-th-pin-btn:hover,
.or-th-pin-btn.is-active {
  color: var(--or-navy);
}
.or-th-pin-btn:focus-visible {
  outline: 2px solid var(--or-navy);
  outline-offset: 1px;
}
.or-th-pin-icon {
  /* Matches the Comparison screen's `.cmp-pin-icon` size. */
  width: 0.83333rem;
  height: 0.83333rem;
}

/* Fixed ("pinned") dimension columns — sticky within `.or-table-wrap`'s
   horizontal scroll (see the `position: sticky` inline style paired with
   this class); the divider shadow on the last fixed column marks the frozen
   boundary — the same visual language spreadsheets use for frozen panes.
   (Background is handled generically for every dim column, pinned or not —
   see `.or-table tbody td.or-td-dim` below — so nothing pin-specific is
   needed here.) */
.or-td-dim--pinned-edge {
  /* Soft blurred shadow — `rgba(14, 15, 17, 0.16)` is `--or-ink` at 16%. */
  box-shadow: 0.33333rem 0 0.33333rem -0.22222rem rgba(14, 15, 17, 0.16);
}

.or-th-filter {
  position: relative;
  /* display: inline-flex;
  margin-left: 0.33333rem; */
}
.or-th-filter-btn {
  display: inline-flex;
  align-items: center;
  border: none;
  background: transparent;
  padding: 0.11111rem;
  cursor: pointer;
  text-transform: none;
  letter-spacing: normal;
}
/* `ColFilterIcon` fills its path with a hardcoded hex rather than
   `currentColor`, so hover feedback has to override that fill directly — a
   CSS rule beats an SVG presentation attribute in the cascade even without
   `!important`. */
.or-th-filter-btn:hover svg path {
  fill: var(--or-navy);
}
.or-td-empty {
  padding: 1.77778rem 0.94444rem;
  text-align: center;
  font-size: 0.72222rem;
  color: var(--or-faint);
}
.or-table tbody td {
  padding: 0.77778rem 0.94444rem;
  border-bottom: 1px solid var(--or-border);
  /* Full grid lines — see `.or-table thead th`'s matching `border-right`. */
  border-right: 1px solid var(--or-border);
  vertical-align: middle;
  /* Grey by default — same tint as the header row — for every METRIC/value
     column (including the ones with the inline bar chart). Dimension
     columns (Channel/Platform/Campaign) override this back to white below
     (`.or-table tbody td.or-td-dim`, regardless of pin state), and the
     total row gets its own distinct tint (`.or-table tbody tr.or-tr-total
     td` below) — both need higher specificity than this rule to win, since
     this one now carries a `background` too. */
  background: var(--or-channel-tint);
}
.or-table tbody tr td:last-child {
  border-right: none;
}
/* Channel/Platform/Campaign columns are always white in the body, pinned or
   not — only their HEADER carries the grey tint (`.or-table thead th`).
   Needs `.or-table tbody` in the selector to out-specificity the default
   grey `.or-table tbody td` rule above. */
.or-table tbody td.or-td-dim {
  background: var(--or-card);
}
.or-td-label {
  font-size: 0.77778rem;
  font-weight: 700;
  color: var(--or-ink);
  text-transform: capitalize;
}
.or-table tbody tr.or-tr-total td {
  border-bottom: none;
  border-top: 1px solid var(--or-border);
  /* Matches the Comparison screen's `.cmp-row-total td` tint — wins over
     both the default grey (`.or-table tbody td`) and the pinned-white
     override (`td.or-td-dim--pinned`), same as Comparison's total row
     overriding even its (normally-white) pinned channel column. */
  background: var(--or-group-cell);
}
.or-tr-total .or-td-label {
  font-size: 0.72222rem;
}

/* A breakdown table's row-count can run into the hundreds (every
   channel/platform/campaign combination) — every filtered row still renders
   into the DOM (bar scaling and the full-dataset PNG download both need
   every row present), but only the current page is actually shown; the rest
   are hidden here rather than unmounted. */
.or-tr-page-hidden {
  display: none;
}

/* Same idea, for the portfolio "Results Breakdown" brand chart — applied to a
   row hidden by pagination OR by a brand search that doesn't match it, and
   (when a search matches nothing) to the title/axis/unit chrome too, so the
   "No match found" overlay isn't left floating next to stray labels. Nothing
   here is ever unmounted: the PNG download always reveals every element this
   class hides, so neither pagination nor search can affect what it exports. */
.or-bcol-row--page-hidden {
  display: none;
}

/* ── Breakdown table pagination — same rows-per-page control and layout as
   the shared `DataTable` component's `.dt-pagination`, restyled with this
   screen's own `--or-*` tokens so it matches the rest of the card. */
.or-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-sm) 0.94444rem 0;
  /* Matches the Comparison screen's `.cmp-pagination` top border. */
  border-top: 1px solid var(--or-border);
  font-size: 0.69444rem;
  color: var(--or-muted);
}
.or-pg-label {
  white-space: nowrap;
}
.or-pg-rpp-wrap {
  position: relative;
}
.or-pg-rpp-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-0-6);
  border: 1px solid var(--or-border);
  border-radius: 0.33333rem;
  padding: 0.22222rem 0.55556rem;
  background: var(--or-card);
  font-size: 0.69444rem;
  font-family: inherit;
  color: var(--or-ink);
  cursor: pointer;
  min-width: 2.77778rem;
}
.or-pg-rpp-chevron {
  width: 0.55556rem;
  height: 0.55556rem;
  flex-shrink: 0;
  color: var(--or-axis);
  transition: transform 0.15s ease;
}
.or-pg-rpp-chevron.is-open {
  transform: rotate(180deg);
}
.or-pg-rpp-dropdown {
  position: absolute;
  bottom: calc(100% + var(--space-xs));
  left: 0;
  right: 0;
  background: var(--or-card);
  border: 1px solid var(--or-border);
  border-radius: 0.33333rem;
  box-shadow: 0 var(--space-xs) var(--space-md) var(--color-shadow-popover);
  overflow: hidden;
  z-index: 10;
}
.or-pg-rpp-option {
  display: block;
  width: 100%;
  padding: 0.33333rem;
  background: none;
  border: none;
  font-size: 0.69444rem;
  font-family: inherit;
  color: var(--or-ink);
  cursor: pointer;
  text-align: center;
}
.or-pg-rpp-option:hover {
  background: var(--or-bg);
}
.or-pg-rpp-option.is-selected {
  background: var(--or-combo-sel);
  font-weight: 700;
}
.or-pg-info {
  white-space: nowrap;
  min-width: 5rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.or-pg-nav-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--or-ink);
  font-size: 1.11111rem;
  line-height: 1;
  padding: 0 0.22222rem;
  display: flex;
  align-items: center;
}
.or-pg-nav-btn:disabled {
  color: var(--or-faint);
  cursor: not-allowed;
}
.or-pg-nav-icon {
  width: 0.83333rem;
  height: 0.83333rem;
  flex-shrink: 0;
}
.or-pg-nav-icon--prev {
  transform: rotate(90deg);
}
.or-pg-nav-icon--next {
  transform: rotate(-90deg);
}

/* Metric cell — table mode is plain numbers (delta + value, muted MAT value
   below); chart mode (`.or-mcell--bars`) adds the inline optimized/MAT bar
   pair back in, so the same row layout serves both toggle states. */
.or-mcell {
  display: flex;
  flex-direction: column;
  gap: 0.33333rem;
  min-width: 7.5rem;
}
.or-mcell--bars {
  min-width: 12.5rem;
}
.or-mcell-row {
  /* Table view (no bars): the change % and the value sit together as a group
     at the RIGHT of the cell — the value's right edge stays under the
     right-aligned metric header, the delta right beside it — so there's no
     large empty gap between a value and its change. */
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  gap: 0.44444rem;
}
.or-mcell--bars .or-mcell-row {
  /* Chart view: the value column is a FIXED width (not `auto`) so the rail
     track next to it — `minmax(4rem, 5rem)` — computes to the exact same
     width on every row in the column; an `auto` value column let the rail's
     width vary per-row with the value text length, which was the alignment
     bug. The value fits the widest values in these tables (e.g. "R$830.27K").
     `display: grid` is set explicitly because the base rule above is flex. */
  display: grid;
  grid-template-columns: 2.44444rem minmax(3.5rem, 4.5rem) 4rem;
  align-items: center;
  gap: 0.44444rem;
}
.or-mcell--bars .or-mcell-val,
.or-mcell--bars .or-mcell-matval {
  text-align: right;
}
.or-mcell-row .or-delta {
  justify-content: flex-start;
  font-size: 0.55556rem;
  font-weight: 700;
}
.or-mcell--bars .or-mcell-row .or-delta {
  justify-content: flex-end;
}
.or-mcell-delta-pad {
  grid-column: 1;
}
.or-mcell-val {
  font-size: 0.69444rem;
  font-weight: 700;
  color: var(--or-ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.or-mcell-matval {
  font-size: 0.59722rem;
  font-weight: 400;
  color: var(--or-faint);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.or-tr-total .or-mcell-val {
  font-size: 0.75rem;
}
.or-tr-total .or-mcell-matval {
  color: var(--or-muted);
  font-weight: 600;
}

@media (max-width: 64rem) {
  .or-kpis {
    grid-template-columns: repeat(2, 1fr);
  }
  .or-kpi:nth-child(-n + 2) {
    border-top: none;
  }
  .or-breakdown {
    grid-template-columns: repeat(2, 1fr);
  }
  .or-portfolio--split {
    grid-template-columns: 1fr;
  }
  .or-side {
    border-right: none;
    border-bottom: 1px solid var(--or-border);
    padding-right: 0;
    padding-bottom: 0.88889rem;
  }
}

/* ══════════════ Single-cell layout (Figma 324/228/231) ══════════════ */

/* Results Breakdown — 2 full-width bars */
.or-scbreak {
  display: flex;
  flex-direction: column;
  gap: 0.66667rem;
}
.or-scbreak-row {
  display: grid;
  /* label · bar track (1fr, lines up with the axis ticks) · value (fixed) */
  grid-template-columns: 8.88889rem 1fr 6rem;
  align-items: center;
  gap: 0.88889rem;
}
.or-scbreak-label {
  font-size: 0.72222rem;
  color: #3b3d42;
  line-height: 1.3;
  text-transform: capitalize;
}
.or-scbreak-barwrap {
  min-width: 0;
  display: flex;
}
.or-scbreak-val {
  text-align: right;
  font-family: var(--ohf-display), serif;
  font-size: 1rem;
  color: var(--or-ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.or-scbreak-axis {
  display: grid;
  /* Same 3 tracks AND gap as .or-scbreak-row so the ticks span exactly the bar
     track — otherwise the bars fall short of their axis positions. */
  grid-template-columns: 8.88889rem 1fr 6rem;
  gap: 0.88889rem;
  border-top: 1px solid #e6e8ee;
  margin-top: 0.33333rem;
  padding-top: 0.33333rem;
}
.or-scbreak-unit {
  text-align: center;
  /* Match the axis's left (label) and right (value) pads so the unit centres
     under the ticks/bar track. */
  padding-left: 8.88889rem;
  padding-right: 6rem;
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.61111rem;
  color: var(--or-axis);
  margin-top: 0.16667rem;
}

/* Controls row: mark-as-private + recap + level toggle + download */
.or-controls {
  display: flex;
  align-items: center;
  gap: 0.88889rem;
  flex-wrap: wrap;
}
.or-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem;
  cursor: pointer;
}
.or-switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.or-switch-track {
  position: relative;
  width: 1.77778rem;
  height: 1rem;
  background: #cfd3dc;
  border-radius: 1rem;
  transition: background 0.15s ease;
  flex-shrink: 0;
}
.or-switch-thumb {
  position: absolute;
  top: 0.11111rem;
  left: 0.11111rem;
  width: 0.77778rem;
  height: 0.77778rem;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.15s ease;
}
.or-switch input:checked + .or-switch-track {
  background: var(--or-navy);
}
.or-switch input:checked + .or-switch-track .or-switch-thumb {
  transform: translateX(0.77778rem);
}
.or-switch-label {
  font-size: 0.72222rem;
  color: var(--or-muted);
}
.or-recap {
  border: 1px solid #b1b8c5;
  background: #fff;
  border-radius: 0.22222rem;
  padding: 0.44444rem 0.83333rem;
  color: #0a1a40;
  cursor: pointer;
  font-family: var(--ohf-body);
  font-weight: 600;
  font-size: calc(0.77778rem * var(--ohf-text-scale));
}
.or-recap:hover {
  background: var(--color-bg-hover-light);
}
.or-levels {
  display: inline-flex;
  background: var(--or-toggle-bg);
  border-radius: 0.44444rem;
  padding: 0.16667rem;
  gap: 0.11111rem;
}
.or-level-btn {
  border: none;
  background: transparent;
  border-radius: 0.33333rem;
  padding: 0.33333rem 0.83333rem;
  font-size: 0.72222rem;
  font-weight: 600;
  color: var(--or-muted);
  cursor: pointer;
}
.or-level-btn.is-active {
  background: #fff;
  color: var(--or-ink);
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.08);
}
.or-level-btn:disabled {
  color: #c2c6d0;
  cursor: not-allowed;
}

/* The legend row that sits ABOVE the table (own line) */
.or-legend--table {
  justify-content: flex-end;
  padding-bottom: 0.55556rem;
  border-bottom: 1px solid var(--or-border);
  border-top: 1px solid var(--or-border);
  padding-top: 0.55556rem;
  margin-bottom: -0.77778rem;
}
.or-th-dim {
  text-align: center;
  font-size: 0.58333rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #7e7e7e;
  /* Top padding added — matches `.or-table thead th`'s fix for the same
     "shorter than Comparison's header" issue. */
  padding: 0.55556rem 0.66667rem 0.66667rem;
  border-bottom: 1px solid var(--or-border);
  white-space: nowrap;
}
.or-td-dim {
  vertical-align: middle;
}
.or-td-chan {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--or-ink);
  text-transform: capitalize;
  /* Column width is fixed (see `.or-table`'s `table-layout: fixed`), so a long
     name has to yield to that width rather than stretch it — `min-width: 0`
     lets this flex item actually shrink below its text's intrinsic width,
     which flex items refuse to do by default. */
  min-width: 0;
}
.or-td-chan-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  /* Grow to fill the row so a trailing response-curve icon (see `.or-row-icon`
     below) lands at a fixed spot at the column's right edge on every row,
     instead of trailing right after the text at a position that shifts with
     the text's own (variable) length. */
  flex: 1 1 auto;
}
.or-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.55556rem;
  height: 1.55556rem;
  border: 1px solid var(--or-border);
  border-radius: 0.44444rem;
  color: var(--or-navy);
  flex-shrink: 0;
}
/* Wraps the interactive `.or-row-icon--btn` variant only (see `ResultsTable`
   in the TSX) — `.or-row-icon` above already carries the fixed size/shrink
   protection the icon itself needs; this just keeps that intact now that the
   button sits inside a tooltip wrapper rather than directly in `.or-td-chan`'s
   flex row. */
.or-row-icon-wrap {
  display: inline-flex;
  flex-shrink: 0;
}
.or-td-dimval {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--or-ink);
  text-transform: none;
  /* Column width is fixed (see `.or-table`'s `table-layout: fixed`) and no
     longer grows to fit content, so a long Platform/Campaign name is clipped
     to one line with an ellipsis instead of wrapping/stretching — every row
     keeps the same height, and the full value is still available via the
     `title` tooltip. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* When this column also carries the response-curve icon (see `ResultsTable`
     in the TSX — icon follows the selected level, not always column 0), it's
     nested inside the `.or-td-chan` flex row alongside the icon; flex items
     don't shrink below their content's natural width by default, which would
     stop the ellipsis from ever kicking in. Growing to fill the row (like
     `.or-td-chan-text` above) pins the icon to a fixed spot at the column's
     right edge on every row rather than trailing right after the text. */
  min-width: 0;
  flex: 1 1 auto;
}
.or-td-total-label {
  font-size: 0.72222rem;
  font-weight: 700;
  color: var(--or-navy);
}

/* Row response-curve button (clickable line-chart icon) */
.or-row-icon--btn {
  padding: 0;
  cursor: pointer;
  transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
}
.or-row-icon--btn:hover {
  border-color: var(--or-navy);
  background: #f2f4f8;
}
.or-row-icon--btn:focus-visible {
  outline: 2px solid var(--or-navy);
  outline-offset: 1px;
}
/* "Scenario Comparison" screen — pixel-matched to Figma frame 158:27347 (single
   cell; portfolio variant 519:14258/519:13199/490:59783 reuses this same layout as
   a best-effort default). Colours/fonts/sizes/spacing below were read directly off
   the frame's own Figma REST API node data (fills, strokes incl. paint opacity,
   text styles, auto-layout gaps/padding, corner radii) — not eyeballed off a
   screenshot. Rem scale: Figma px ÷ 18 -> rem, same convention `OptimisationResults.
   css` documents (this feature's screens are designed at a 1440px-wide frame, which
   is exactly 18px root font-size under this app's viewport-scaled root). */
.cmp-page {
  --cmp-bg: #f6f6f9;
  --cmp-card: #ffffff;
  --cmp-border: rgba(0, 0, 0, 0.08);
  --cmp-border-strong: #b1b8c5;
  /* The KPI strip alone matches the Results screen's cooler, lighter rule (`--or-border`)
     rather than the warmer `--cmp-border` the cards and table gridlines use — the two
     screens show the same KPI strip back to back, so it is the one block that must not
     read as a different component. Deliberately NOT a change to `--cmp-border` itself,
     which everything else on this screen is tuned against. */
  --cmp-kpi-border: #e9eaf0;
  --cmp-ink: #0e0f11;
  --cmp-heading: #0e0f11;
  --cmp-muted: #6b6e76;
  --cmp-back-ink: #6b717d;
  --cmp-faint: #9a9ca2;
  --cmp-navy: #0a1a40;
  --cmp-eyebrow: #213b6e;

  --cmp-th-fg: #7e7e7e;
  --cmp-cell-fg: #3b3d42;

  /* Single Cell pill = blue; Portfolio pill = peach (mirrors the Results screen's
     `--or-badge-*` so the scope pill reads identically across both screens). */
  --cmp-badge-bg: #d7e2f5;
  --cmp-badge-fg: #213b6e;
  --cmp-badge-portfolio-bg: #fcebcc;
  --cmp-badge-portfolio-fg: #9f6700;

  --cmp-up: #0fa870;
  --cmp-down: #e15552;
  --cmp-flat: #8b8b8b;

  /* Scenario A / B accent pair, read off the picker dots / KPI dots / outcome bars
     (all three use this exact pair). */
  --cmp-a: #6a89bf;
  --cmp-b: #a0b2da;
  --cmp-a-tint: #f5f9ff;
  --cmp-b-tint: #f0f0f5;
  --cmp-channel-tint: #faf9f6;
  /* Body-cell partner to `--cmp-channel-tint`: the tinted column groups (MAT Baseline and
     the base scenario) use the flat tint on their HEADER and this fractionally lighter
     shade on the value cells. Was repeated as a literal in three places. */
  --cmp-group-cell: #fbfaf7;

  min-height: 100vh;
  padding-top: var(--space-10);
  background: var(--cmp-bg);
  font-family: "Inter", var(--ohf-body), sans-serif;
  color: var(--cmp-ink);
}

.cmp-loader,
.cmp-error {
  padding: var(--space-xxl) var(--space-xl);
}

/* ── Download scrim ───────────────────────────────────────────────────────────────────
   Shown while an Outcomes PNG (html2canvas) or the table .xlsx is being written. Same
   rule, colour and blur as the Results screen's `.or-download-overlay` — the two screens
   sit back to back, so the wait must not read as a different interaction. Fixed and
   full-viewport so it also swallows clicks on the app chrome, not just the card. */
.cmp-download-overlay {
  position: fixed;
  inset: 0;
  z-index: 2100;
  background: rgba(14, 15, 17, 0.15);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

/* ── Refetch scrim ────────────────────────────────────────────────────────────────────
   Covers the KPI cards, outcome bars and table together while a new `getComparison`
   payload is in flight — they all come from that ONE response, so a per-card spinner
   would just be the same wait drawn three times. The content underneath stays put and
   stays legible through the scrim; what it loses is interactivity, which is the point:
   the level toggle sits under here, and a second click mid-flight would only queue a
   request whose answer the first one is about to invalidate. */
.cmp-results {
  position: relative;
  /* Re-states `.cmp-body`'s own column + gap. The KPI row, outcomes card and table card
     used to be direct children of `.cmp-body` and took their spacing from its gap;
     grouping them under this wrapper put them one level down, out of its reach. Keep the
     two gap values in step. */
  display: flex;
  flex-direction: column;
  gap: 0.88889rem;
}

.cmp-results-scrim {
  position: absolute;
  inset: 0;
  z-index: 10;
  /* Matches the page ground rather than plain white — the cards ARE white, so a white
     veil over them reads as the content having vanished instead of being busy. */
  background: color-mix(in srgb, var(--cmp-bg) 68%, transparent);
  display: flex;
  align-items: flex-start;
  justify-content: center;
}

/* The results region runs well past one screen, so a spinner centred in it would sit
   below the fold exactly when the table is long — which is when the wait is longest.
   Sticky keeps it a third of the way down the VIEWPORT for as long as any part of the
   region is showing, so it's in view wherever the user happens to be scrolled. */
.cmp-results-scrim .chart-loader {
  position: sticky;
  top: 33vh;
  height: auto;
  min-height: 0;
}

/* ── Top breadcrumb bar — same shell as `.or-crumbbar` ── */
.cmp-crumbbar {
  background: var(--cmp-card);
  border-bottom: 1px solid #cfd4df;
  /* Pinned under the app chrome while the page scrolls — same rule, offset and
     min-height as Set Constraints' .scb-strip; see its comment. */
  position: sticky;
  top: var(--app-header-stack-h);
  z-index: 100;
  min-height: var(--app-scope-strip-h);
}
.cmp-crumbbar-inner {
  max-width: 80rem;
  margin: 0 auto;
  padding: 0.72222rem 2.22222rem;
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.44444rem;
  font-size: 0.69444rem;
  min-width: 0;
  overflow: hidden;
}
/* One line, always: every segment keeps its natural width, and only the typed-name
   segments (Scenario / Portfolio — `.cmp-crumb--fluid`) give way when the bar runs out of room,
   ellipsizing their value rather than wrapping the bar onto a second line. With room
   to spare the name is shown in full; the full name is on hover only once clipped. */
.cmp-crumbbar-inner > * {
  flex: 0 0 auto;
  white-space: nowrap;
}
.cmp-crumb {
  display: inline-flex;
  gap: 0.33333rem;
}
.cmp-crumbbar-inner > .cmp-crumb--fluid {
  flex-shrink: 1;
  min-width: 0;
}
.cmp-crumb--fluid .cmp-crumb-label {
  flex-shrink: 0;
}
.cmp-crumb--fluid .cmp-crumb-value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cmp-crumb-label {
  color: var(--cmp-muted);
}
.cmp-crumb-value {
  color: var(--cmp-ink);
  font-weight: 600;
}
/* "+(8)" counter trailing the two spelled-out scope values (see summariseCrumb)
   — same treatment as .or-crumb-more on Scenario Results. */
.cmp-crumb-more {
  margin-left: 0.22222rem;
  font-weight: 500;
  color: var(--cmp-muted);
  font-variant-numeric: tabular-nums;
}
.cmp-crumb-sep {
  color: #b9bcc4;
}

.cmp-body {
  max-width: 80rem;
  margin: 0 auto;
  padding: 1.22222rem 1.77778rem 2.44444rem;
  display: flex;
  flex-direction: column;
  gap: 0.88889rem;
}

.cmp-back {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.33333rem;
  border: none;
  background: transparent;
  padding: 0;
  color: var(--cmp-back-ink);
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.77778rem;
  font-weight: 600;
  cursor: pointer;
}
.cmp-back-icon {
  width: 0.88889rem;
  height: 0.88889rem;
  color: var(--cmp-faint);
}

/* ── Head ── */
.cmp-head {
  display: flex;
  flex-direction: column;
  gap: 0.33333rem;
}
.cmp-eyebrow-row {
  display: flex;
  align-items: center;
  gap: 0.66667rem;
}
.cmp-eyebrow {
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.66667rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cmp-eyebrow);
}
.cmp-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 0.33333rem;
  padding: 0.16667rem 0.5rem;
  font-size: 0.61111rem;
  font-weight: 700;
  background: var(--cmp-badge-bg);
  color: var(--cmp-badge-fg);
}
.cmp-badge--portfolio {
  background: var(--cmp-badge-portfolio-bg);
  color: var(--cmp-badge-portfolio-fg);
}
.cmp-title {
  margin: 0;
  font-family: var(--ohf-heading), serif;
  font-size: 1.33333rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--cmp-heading);
}

/* ── Picker card — Scenario A / Compare with, side by side in ONE card ── */
.cmp-picker-card {
  background: var(--cmp-card);
  border: 1px solid var(--cmp-border);
  border-radius: 0.55556rem;
  padding: 0.88889rem 1.22222rem;
  display: flex;
  align-items: center;
  /* Wraps rather than overflows. The two slots + the scope note need ~960px of
     intrinsic width; below that this row used to keep its size and let Scenario B
     (last in source order) run off the right edge of the card and the page. Wrapping
     is preferred over shrinking so the fields keep their Figma 320px on every line —
     they only shrink (via the max-width/min-width pair below) once the card itself is
     narrower than one field, which is past any viewport this screen targets.
     Row gap is smaller than the column gap: stacked slots need separating, not the
     1.77778rem that reads as "side by side". */
  flex-wrap: wrap;
  gap: 0.88889rem 1.77778rem;
}
.cmp-picker-slot {
  display: inline-flex;
  align-items: center;
  gap: 0.66667rem;
  /* Grows never (the wide layout must stay pixel-identical to Figma), shrinks only
     as a last resort — and `min-width: 0` is what lets it, since a flex item's
     default `min-width: auto` would floor it at the field's intrinsic width and
     reinstate the overflow this rule exists to remove. */
  flex: 0 1 auto;
  min-width: 0;
}
.cmp-picker-field {
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
  flex: 1 1 auto;
  min-width: 0;
}
.cmp-picker-label {
  font-size: 0.58333rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--cmp-faint);
}
.cmp-dot {
  width: 0.55556rem;
  height: 0.55556rem;
  border-radius: 0.16667rem;
  flex-shrink: 0;
  background: var(--cmp-a);
}
.cmp-dot--b {
  background: var(--cmp-b);
}
.cmp-dot--empty {
  opacity: 0.5;
}

/* ── Scenario A / Scenario B fields ────────────────────────────────────────────────────
   Both are the shared `MultiSelectDropdown` — A in `single` (radio) mode, B in the default
   multi mode. They are styled as ONE rule pair on purpose: standing side by side, the two
   pickers must be indistinguishable apart from the glyph in their rows, so any width,
   border or type change here reaches both or neither.

   The component carries a floating-notch label of its own, but this frame stacks a plain
   label ABOVE a bordered box instead (see `.cmp-picker-label`), so `.msd-label` is hidden
   and the wrap/trigger are restyled into a plain bordered field. */
.cmp-a-select.msd-wrap,
.cmp-b-select.msd-wrap {
  border: 1px solid var(--cmp-border);
  border-radius: 0.44444rem;
  /* Figma's 320px, but capped at the slot it sits in: below that the field narrows
     instead of overflowing the card. The open panel is portalled and measures the
     trigger's own rect, so it follows this width without a rule of its own. */
  width: 17.77778rem;
  max-width: 100%;
}
.cmp-a-select .msd-label,
.cmp-b-select .msd-label {
  display: none;
}
.cmp-a-select .msd-trigger,
.cmp-b-select .msd-trigger {
  width: 100%;
  min-height: 2rem;
  padding: 0.5rem;
  justify-content: space-between;
}
/* No `text-transform` here on purpose — this is a scenario NAME as its author typed it, so
   the field must state it verbatim (the component's `capitaliseLabels={false}` does the
   same for the rows and the tooltip strings). Uppercasing it made the same name read two
   ways in one picker, and again in the "Outcomes at a glance" hover chip. Weight and
   colour still ours; the letters are the user's. Same reasoning as `.cmp-segtip-label`. */
.cmp-a-select .msd-value,
.cmp-b-select .msd-value {
  font-weight: 600;
  font-size: 0.69444rem;
  color: var(--cmp-ink);
}
/* The prompt shown while nothing is picked opts back out of the weight/colour above: those
   state a scenario name, and a placeholder is not one. The same faint grey and weight as
   the `.cmp-scope-note` sitting beside it, so an empty field reads as empty rather than as
   holding a value. */
.cmp-a-select .msd-value--placeholder,
.cmp-b-select .msd-value--placeholder {
  font-weight: 500;
  color: var(--cmp-faint);
}
/* Rows and panel adopt this screen's own type scale rather than the filter-bar scale the
   component ships with, so the open list matches the field it drops out of. */
.cmp-a-select .msd-option,
.cmp-b-select .msd-option,
.cmp-a-select .msd-selectall-label,
.cmp-b-select .msd-selectall-label {
  font-size: 0.69444rem;
  color: var(--cmp-ink);
}

.cmp-scope-note {
  margin-left: auto;
  padding-left: 1.33333rem;
  border-left: 1px solid var(--cmp-border);
  color: var(--cmp-faint);
  font-size: 0.63889rem;
  font-weight: 500;
  white-space: nowrap;
}

/* ── KPI mini-row — dot + value (A), dot + value (B), delta ── */
.cmp-kpis {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  background: var(--cmp-card);
  border: 1px solid var(--cmp-kpi-border);
  border-radius: 0.55556rem;
  overflow: hidden;
}
@media (max-width: 900px) {
  .cmp-kpis {
    grid-template-columns: repeat(2, 1fr);
  }
}
.cmp-kpi {
  padding: 1.22222rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.44444rem;
  border-left: 1px solid var(--cmp-kpi-border);
}
.cmp-kpi:first-child {
  border-left: none;
}
.cmp-kpi-label {
  display: inline-flex;
  align-items: center;
  gap: 0.33333rem;
  font-size: 0.58333rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--cmp-faint);
}
.cmp-kpi-value {
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem;
  font-family: var(--ohf-body), sans-serif;
  font-size: 1.27778rem;
  font-weight: 600;
  color: var(--cmp-ink);
  font-variant-numeric: tabular-nums;
}
.cmp-kpi-value--b {
  font-size: 0.88889rem;
  font-weight: 400;
}
.cmp-kpi-dot {
  width: 0.44444rem;
  height: 0.44444rem;
  border-radius: 0.11111rem;
  flex-shrink: 0;
  background: var(--cmp-a);
}
.cmp-kpi-dot--b {
  background: var(--cmp-b);
}

/* KPI info icon + definition popover. Both come from the shared `InfoButton` (see
   `KpiInfo`), which is used ONLY for its placement — everything below re-skins it back
   to this screen's white card. Every rule is paired with `.ib-*` so it out-specifies
   `InfoButton.css` regardless of stylesheet order; none of them touch
   top/left/right/bottom, which `InfoButton` sets inline. */
.cmp-kpi-info-btn.ib-btn {
  color: var(--cmp-faint);
}
.cmp-kpi-info-btn .ib-icon {
  width: 0.72222rem;
  height: 0.72222rem;
}

/* The definition popover. It keeps `InfoButton`'s DEFAULT skin — the grey surface, white
   text, rounded corners and pointer triangle the Results screen's own KPI tooltips use —
   so the same popover reads the same way on both screens, and matches the `HoverTooltip`
   chip this one uses everywhere else. That default supplies the padding, type scale, corner radius and pointer
   triangle (including the flipped one for `placement="top"`), which is why nothing but
   the fixed width the long Definition/Formula text needs is overridden here.

   Note the tooltip is portalled to `document.body`, OUTSIDE `.cmp-page` — this screen's
   `--cmp-*` custom properties are scoped to that element and would not resolve here. That
   is a second reason to lean on the shared defaults rather than re-skin locally. */
.ib-tooltip.cmp-kpi-tooltip {
  width: 16.66667rem;
  max-width: calc(100vw - 1rem);
}

/* ── Delta ── */
.cmp-delta {
  display: inline-flex;
  align-items: center;
  gap: 0.22222rem;
  font-size: 0.66667rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cmp-delta--up {
  color: var(--cmp-up);
}
.cmp-delta--down {
  color: var(--cmp-down);
}
.cmp-delta--flat {
  color: var(--cmp-flat);
}
.cmp-delta-icon {
  width: 0.72222rem;
  height: 0.5rem;
}

/* ── Card shell (Outcomes / Channel comparison) ── */
.cmp-card {
  background: var(--cmp-card);
  border: 1px solid var(--cmp-border);
  border-radius: 0.55556rem;
  padding: 1.22222rem 1.33333rem;
  display: flex;
  flex-direction: column;
  gap: 1.11111rem;
}
.cmp-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.cmp-card-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 400;
  color: var(--cmp-ink);
}
.cmp-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.66667rem;
  height: 1.66667rem;
  border: none;
  background: transparent;
  color: var(--cmp-navy);
  cursor: pointer;
}

/* ── Outcomes at a glance ── */
.cmp-legend {
  display: flex;
  align-items: center;
  gap: 0.77778rem;
}
.cmp-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.33333rem;
  font-size: 0.63889rem;
  color: var(--cmp-muted);
}
.cmp-swatch {
  width: 0.55556rem;
  height: 0.55556rem;
  border-radius: 0.11111rem;
  background: var(--cmp-a);
}
.cmp-swatch--b {
  background: var(--cmp-b);
}

.cmp-outcomes {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.55556rem 2.44444rem;
}
@media (max-width: 700px) {
  .cmp-outcomes {
    grid-template-columns: 1fr;
  }
}
.cmp-outcome {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.cmp-outcome-label {
  font-size: 0.66667rem;
  font-weight: 500;
  color: var(--cmp-cell-fg);
}
.cmp-outcome-bar-row {
  display: flex;
  align-items: center;
  gap: 0.55556rem;
}
.cmp-outcome-track {
  flex: 1;
  height: 1.11111rem;
  border-radius: 0.22222rem;
  background: #eef0f4;
  /* Deliberately NOT `overflow: hidden` — the hovered fill lifts and grows on Y out of the
     track, and clipping would swallow the effect. Nothing is lost by dropping it: the fill
     carries the same radius as the track, so its corners were never the reason for it. */
}
.cmp-outcome-fill {
  display: block;
  height: 100%;
  border-radius: 0.22222rem;
  background: var(--cmp-a);
}
.cmp-outcome-fill--b {
  background: var(--cmp-b);
}

/* ── Bar hover, mirroring the Results screen's `or-seg--*` behaviour ── */
.cmp-outcome-fill--interactive {
  cursor: pointer;
  transform-origin: center;
  transition:
    transform var(--motion-duration-normal) var(--motion-easing-spring),
    box-shadow var(--motion-duration-normal) var(--motion-easing-standard),
    opacity var(--motion-duration-normal) var(--motion-easing-standard);
}
.cmp-outcome-fill--lifted {
  /* Y only: growing it on X would change the bar's apparent VALUE. */
  transform: translateY(-0.16667rem) scaleY(1.18);
  box-shadow: 0 0.33333rem 0.66667rem var(--color-bar-seg-lift-shadow);
  position: relative;
  z-index: 1;
}
.cmp-outcome-fill--dimmed {
  opacity: 0.45;
}
.cmp-outcome-fill--interactive:focus-visible {
  outline: 2px solid var(--cmp-navy);
  outline-offset: 2px;
}

/* The readout chip — portalled to <body>, so positioned in viewport coordinates and
   anchored to the bar's top-centre by the transform. Colours come from the app-wide
   `--color-bar-tip-*` tokens (the same ones the Results screen's readout uses): a portal
   sits outside `.cmp-page`, where this screen's own `--cmp-*` properties do not resolve. */
.cmp-segtip {
  position: fixed;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  gap: var(--space-0-5);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-md);
  /* `background` is set inline, to the hovered bar's own colour — see `OutcomeBars`. */
  box-shadow: 0 var(--space-0-8) var(--space-lg) var(--color-bar-tip-shadow);
  font-family: var(--font-family-base);
  white-space: nowrap;
  /* `pointer-events: none` matters: without it the chip can land under the cursor, fire
     mouseleave on the bar, and flicker itself in and out. */
  transform: translate(-50%, calc(-100% - var(--space-sm)));
  pointer-events: none;
  animation: cmp-segtip-in var(--motion-duration-fast) var(--motion-easing-enter) both;
}
/* Deliberately NOT uppercased. This label was a fixed role caption ("Scenario A") when the
   caps were a styling choice; it now carries the scenario's OWN name as the user typed it
   (see `OutcomeBars`' `rows`), and a user-entered name is content, not chrome — "Test"
   shown as "TEST" no longer matches the name in the picker above. The tracking stays: it
   keeps this small bold caption legible without touching the letters themselves. */
.cmp-segtip-label {
  font-size: var(--font-size-2xs);
  font-weight: var(--font-weight-bold);
  letter-spacing: 0.06em;
  color: var(--color-bar-tip-muted);
}
.cmp-segtip-value {
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-bold);
  color: var(--color-bar-tip-text);
}
/* A pale bar takes dark ink — the cream above is unreadable on it. Which set applies is
   decided from the surface's measured luminance, not from the scenario name. */
.cmp-segtip--on-light .cmp-segtip-value {
  color: var(--color-bar-tip-text-on-light);
}
.cmp-segtip--on-light .cmp-segtip-label {
  color: var(--color-bar-tip-muted-on-light);
}
/* Flipped under the bar when there is no room above it — see `show()`. */
.cmp-segtip--below {
  transform: translate(-50%, var(--space-sm));
  animation-name: cmp-segtip-in-below;
}
@keyframes cmp-segtip-in {
  from {
    opacity: 0;
    transform: translate(-50%, calc(-100% - var(--space-0-5)));
  }
  to {
    opacity: 1;
    transform: translate(-50%, calc(-100% - var(--space-sm)));
  }
}
@keyframes cmp-segtip-in-below {
  from {
    opacity: 0;
    transform: translate(-50%, var(--space-0-5));
  }
  to {
    opacity: 1;
    transform: translate(-50%, var(--space-sm));
  }
}
@media (prefers-reduced-motion: reduce) {
  .cmp-outcome-fill--interactive {
    transition: none;
  }
  .cmp-outcome-fill--lifted {
    /* No lift, but the emphasis must survive — the sibling dimming and the chip carry it. */
    transform: none;
  }
  .cmp-segtip {
    animation: none;
  }
}
.cmp-outcome-val {
  min-width: 4rem;
  text-align: right;
  font-family: var(--ohf-body), sans-serif;
  font-size: 0.83333rem;
  font-weight: 500;
  color: var(--cmp-ink);
  font-variant-numeric: tabular-nums;
}

/* ── Channel comparison controls ── */
.cmp-controls {
  display: flex;
  align-items: center;
  gap: 0.88889rem;
}
.cmp-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.44444rem;
  cursor: pointer;
}
.cmp-switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.cmp-switch-track {
  width: 1.88889rem;
  height: 1.11111rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.18);
  position: relative;
  transition: background 0.15s ease;
}
.cmp-switch-thumb {
  position: absolute;
  top: 0.11111rem;
  left: 0.11111rem;
  width: 0.88889rem;
  height: 0.88889rem;
  border-radius: 999px;
  background: #fff;
  transition: transform 0.15s ease;
}
.cmp-switch input:checked + .cmp-switch-track {
  background: var(--cmp-navy);
}
.cmp-switch input:checked + .cmp-switch-track .cmp-switch-thumb {
  transform: translateX(0.77778rem);
}
.cmp-switch-label {
  font-size: 0.69444rem;
  color: var(--cmp-cell-fg);
  font-weight: 500;
}
/* Channel/Platform/Campaign segmented control */
.cmp-level-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0;
  background: #f1efea;
  border-radius: 0.38889rem;
  padding: 0.16667rem;
}
.cmp-level-btn {
  border: none;
  background: transparent;
  border-radius: 0.27778rem;
  padding: 0.33333rem 0.77778rem;
  font-size: 0.69444rem;
  font-weight: 600;
  color: var(--cmp-muted);
  cursor: pointer;
}
.cmp-level-btn.is-active {
  background: var(--cmp-card);
  color: var(--cmp-ink);
}
.cmp-level-btn:disabled {
  color: var(--cmp-faint);
  cursor: not-allowed;
}

/* ── Channel comparison table — scenario-tinted grouped columns ── */
.cmp-table-wrap {
  overflow-x: auto;
  /* No sideways rubber-band (blank strip beside the first column) or swipe-back gesture
     when a horizontal scroll hits its edge; vertical scrolling still passes to the page. */
  overscroll-behavior-x: none;
}
.cmp-table {
  width: 100%;
  /* Declared per-column widths (`comparisonColumns.ts`), applied through `<colgroup>`, with
     `min-width` set inline to their sum. This replaced `auto`: content-driven sizing made a
     column's width change as the user paged, filtered or picked a different scenario, and
     left the frozen columns' offsets unknowable without measuring the DOM after every
     render. Fixed widths are also what lets this table line up with the constraints table,
     whose dimension widths these share. Anything that doesn't fit scrolls in
     `.cmp-table-wrap` rather than being squeezed — same rule as `.sct-scroll`. */
  table-layout: fixed;
  /* `separate` rather than `collapse` — under `collapse` the borders belong to the table's
     own grid rather than to the cells, and Chrome drops them entirely on `position: sticky`
     cells, so the frozen columns would lose their gridlines the moment they pinned. Renders
     identically here because the cell rule below only ever draws a right and a bottom edge:
     with no left/top edges to meet them there is nothing to double up, which is the usual
     reason to prefer `collapse`. */
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.72222rem;
}

/* ── Frozen leading columns ──────────────────────────────────────────────────────────
   Applied by `CompareTable`'s `frozenCell()`, which also supplies each cell's `left`
   offset inline (measured — `table-layout: auto` makes the widths content-driven). Every
   cell that can be frozen already paints an opaque background of its own, which is what
   lets the scrolling columns pass underneath it. */
.cmp-table .cmp-sticky {
  position: sticky;
  z-index: 2;
}
/* Header cells outrank body cells: a pinned header must stay above the body cells it
   shares a column with, and above the scrolling headers it overlaps. */
.cmp-table thead .cmp-sticky {
  z-index: 3;
}
/* Every column's width is declared inline on its `<col>` from `comparisonColumns.ts` —
   there are no width rules here to disagree with it. */

/* ── Dimension header: pin toggle + drag-resize handle ──────────────────────────────
   Ported from the constraints table's `.sct-pin-btn` / `.sct-col-resize` so the two
   tables' controls look and behave the same. */
.cmp-th-channel {
  position: relative; /* containing block for the absolute resize handle */
}
/* The header cell must let the filter popover escape (cells are `overflow: hidden`); the
   label keeps its own ellipsis and the handle stays inside, so nothing else spills. */
.cmp-table thead .cmp-th-channel {
  overflow: visible;
}
.cmp-channel-head-label {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Group header carrying a control (MAT Baseline's pin) — keeps the label centred as the
   bare group headers are, with the button sitting beside it rather than pushing it off. */
.cmp-group-head {
  display: inline-flex;
  align-items: center;
  gap: 0.22222rem;
}
.cmp-pin-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0.11111rem;
  cursor: pointer;
  color: var(--cmp-faint);
  border-radius: 0.22222rem;
  flex-shrink: 0;
}
.cmp-pin-btn:hover,
.cmp-pin-btn--active {
  color: var(--cmp-navy);
}
.cmp-pin-icon {
  width: 0.83333rem;
  height: 0.83333rem;
}
/* Any header cell carrying a resize handle needs to be the handle's containing block. The
   dimension headers get this via `.cmp-th-channel`; this covers the MAT subheaders. */
.cmp-th-resizable {
  position: relative;
}
.cmp-col-resize {
  position: absolute;
  top: 0;
  right: 0;
  width: 0.44444rem; /* 8px hit area */
  height: 100%;
  cursor: col-resize;
  touch-action: none;
  z-index: 3;
}
.cmp-col-resize::after {
  content: "";
  position: absolute;
  top: 20%;
  right: 0.16667rem;
  width: 2px;
  height: 60%;
  border-radius: 1px;
  background: transparent;
}
.cmp-col-resize:hover::after,
body.cmp-col-resizing .cmp-col-resize::after {
  background: var(--cmp-faint);
}
/* While a resize drag is in flight, keep the col-resize cursor everywhere and suppress
   selection so dragging over labels doesn't highlight them. */
body.cmp-col-resizing {
  cursor: col-resize !important;
  user-select: none;
}

/* The dimension value, truncated with an ellipsis inside its fixed-width cell. Hovering
   reveals the full name in the shared `HoverTooltip` chip (`.ib-tooltip`). */
.cmp-td-dim-text {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* A MERGED cell's value (`rowSpan > 1` — see `dimRowSpans`/`dimMergedMaxLines` in
   `OptimisationComparison.tsx`) wraps onto a few lines instead, using the extra height its
   merge freed up rather than ellipsising on the first line regardless of how much room is
   actually available below it. `-webkit-line-clamp` itself is set inline per cell (it's a
   dynamic per-merge value, not something a static class can express) — this class only
   supplies the fixed parts of the recipe it needs to mean anything. Still falls back to
   the shared `HoverTooltip` chip for a value too long even for its lines' worth of room,
   the same as the single-line case above. */
.cmp-td-dim-text--wrap {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  white-space: normal;
  overflow-wrap: anywhere;
  text-overflow: unset;
}

.cmp-table th,
.cmp-table td {
  padding: 0.55556rem 0.55556rem;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmp-table .cmp-subhead th {
  /* Deliberately NOT `normal`: the label and its sort caret must stay on one line, and
     under `auto` layout the column widens to fit rather than wrapping. */
  white-space: nowrap;
  line-height: 1.3;
}
.cmp-table .cmp-th-channel,
.cmp-table .cmp-td-channel {
  text-align: left;
  vertical-align: bottom;
  padding-left: 1.33333rem;
  background: var(--cmp-channel-tint);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--cmp-ink);
}
/* The first-column HEADER ("CHANNEL" / "BRAND") matches the metric column headers
   (Spend, Inc Sales, …) — same grey, small, tracked, uppercase treatment as
   `.cmp-subhead th` / `.cmp-th-brand` — instead of inheriting the larger dark body-cell
   style above (which still applies to the channel/brand VALUE cells). */
.cmp-table .cmp-th-channel {
  text-transform: uppercase;
  font-size: 0.58333rem;
  letter-spacing: 0.03em;
  color: var(--cmp-th-fg);
  /* Each dimension header is ONE cell spanning both header rows (`rowSpan={2}`) — the
     scenario side stacks its scenario name over the metric labels, these don't. Centring
     the label in that merged cell is what makes it read as merged; bottom-aligning it
     (as the body value cells still are) left an empty block above that looked like a
     separate, blank header cell. Centred horizontally too, matching the metric headers
     and the Figma reference — the VALUE cells stay left-aligned via the rule above,
     since campaign names run long enough that centring them reads as ragged. */
  vertical-align: middle;
  text-align: center;
}
.cmp-table tbody .cmp-td-channel {
  background: var(--cmp-card);
}
/* Excel-style vertical merge (`dimRowSpans` in `OptimisationComparison.tsx`) — a cell now
   spanning several rows' worth of height reads oddly bottom-aligned to its LAST row, so
   centre its value in the merged block instead. Single-row cells (`span === 1`, including
   every leaf-column cell, which is never merged) keep the rule above unchanged. */
.cmp-table .cmp-td-merged {
  vertical-align: middle;
}
/* Single Cell channel names are UPPERCASE (Figma 158:27347 "OOH", "OTHER DISPLAY"); the
   Portfolio channel/brand row names are title-case bold (519:13199 "Search", "Ponds"). */
.cmp-td-uppercase {
  text-transform: capitalize;
}
.cmp-td-rowname {
  font-weight: 700;
  font-size: 0.77778rem;
  text-transform: capitalize;
}
/* Small-caps labels (KPI eyebrows, metric column headers) are uppercased in JS by
   `capsLabel()` instead of by `text-transform`, which would flatten the deliberate
   lowercase "m" in "mROI" to "MROI". This opts those elements out of the transform
   their container applies. */
.cmp-caps {
  text-transform: none;
}
.cmp-channel-head {
  display: flex;
  align-items: center;
  gap: 0.22222rem;
  /* Leaves room for the resize handle on the cell's right edge. */
  padding-right: 0.33333rem;
}
.cmp-th-channel:not(.cmp-th-brand) .cmp-channel-head {
  justify-content: center;
}
.cmp-filter-icon {
  width: 0.66667rem;
  height: 0.66667rem;
  color: var(--cmp-faint);
}
/* Muted "-" placeholder for the Scenario B group before a B is picked (Figma 112:8588 /
   519:14258 keep the B columns visible, greyed). */
.cmp-th-group--empty {
  color: var(--cmp-faint);
}
.cmp-td-empty {
  color: var(--cmp-faint);
}
/* The `<th>` already clips (`.cmp-table th`), but `HoverTooltip` measures the element it
   wraps — so the span inside has to do the ellipsising itself, or `scrollWidth >
   clientWidth` would never be true and the full name would stay unreachable. */
.cmp-th-group-text {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmp-th-group {
  text-align: center;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: 0.69444rem;
  color: var(--cmp-ink);
}
/* The base scenario's group and the MAT Baseline pair share one tint, in BOTH variants —
   they are the two reference blocks the compared scenario is read against, so they read as
   one band. This was previously the Portfolio table's own override (a warm tint) while
   Single Cell fell through to a cool blue, which made the same column group two different
   colours depending on the scope type. */
.cmp-th-group--a,
.cmp-th-group--mat {
  background: var(--cmp-channel-tint);
}
td.cmp-th-group--a,
td.cmp-th-group--mat {
  background: var(--cmp-group-cell);
}
/* Only the FIRST scenario's group carries a tint; every compared scenario beside it
   stays on the plain card surface, so the eye lands on the baseline column block.
   (`--cmp-b-tint` is still used by the Portfolio sidebar hover states.) */
.cmp-th-group--b {
  background: var(--cmp-card);
}
.cmp-table .cmp-subhead th {
  /* Metric column headers (SPEND, INC SALES, …) are centred over their values. */
  text-align: center;
  font-weight: 600;
  font-size: 0.58333rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--cmp-th-fg);
}
.cmp-table tbody td {
  /* Metric values are centred (the first row-label column keeps its own left
     alignment via the higher-specificity `.cmp-td-channel` rule above). */
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--cmp-cell-fg);
  font-weight: 500;
}
/* Full grid. The hairline is the one the group-header underline already used
   (`--cmp-border`, rgba(0,0,0,0.08)), now drawn on every cell edge so the dimension
   columns read as a grid rather than as free-floating text. `border-collapse: collapse`
   on `.cmp-table` merges each pair of adjacent edges into a single line. */
.cmp-table th,
.cmp-table td {
  border-right: 1px solid var(--cmp-border);
  border-bottom: 1px solid var(--cmp-border);
}
/* No trailing line down the table's outer edge — the card border already closes it,
   and with `overflow-x` a hanging right edge reads as a cut-off column. */
.cmp-table tr > *:last-child {
  border-right: none;
}
.cmp-td-bval {
  margin-right: 0.44444rem;
}

.cmp-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.55556rem;
  padding-top: 0.77778rem;
  border-top: 1px solid var(--cmp-border);
  font-size: 0.72222rem;
  color: var(--cmp-muted);
}
.cmp-pagination-label {
  color: var(--cmp-muted);
}
/* Rows-per-page control. Same shape as the shared DataTable's `.dt-rpp-*`: a bordered
   trigger showing the current size, with the listbox opening UPWARD because this footer
   sits at the bottom of the card. */
.cmp-rpp-wrap {
  position: relative;
}
.cmp-pagination-size {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  border: 1px solid var(--color-table-pagination-border);
  border-radius: 0.33333rem;
  padding: 0.22222rem 0.55556rem;
  background: var(--color-white);
  font-size: 0.69444rem;
  font-family: inherit;
  color: var(--color-table-pagination-ink);
  cursor: pointer;
  min-width: 2.77778rem;
}
/* ChevronDownIcon drops its own inline sizing as soon as a className is passed, so the
   dimensions have to come from here. */
.cmp-rpp-chevron {
  display: block;
  width: 0.55556rem;
  height: 0.55556rem;
  flex-shrink: 0;
  color: var(--color-table-pagination-axis);
  transition: transform 0.15s ease;
}
.cmp-rpp-chevron--open {
  transform: rotate(180deg);
}
.cmp-rpp-dropdown {
  position: absolute;
  bottom: calc(100% + 0.22222rem);
  left: 0;
  right: 0;
  background: var(--color-white);
  border: 1px solid var(--color-table-pagination-border);
  border-radius: 0.33333rem;
  box-shadow: 0 0.22222rem 0.66667rem var(--color-shadow-popover);
  overflow: hidden;
  z-index: 10;
}
.cmp-rpp-option {
  display: block;
  width: 100%;
  padding: 0.33333rem;
  border: none;
  background: none;
  font-size: 0.69444rem;
  font-family: inherit;
  color: var(--color-table-pagination-ink);
  text-align: center;
  cursor: pointer;
}
.cmp-rpp-option:hover {
  background: var(--color-table-pagination-hover-bg);
}
.cmp-rpp-option--selected {
  background: var(--color-table-pagination-selected-bg);
  font-weight: 700;
}
.cmp-pagination-count {
  color: var(--cmp-muted);
  margin-left: 0.55556rem;
}
.cmp-pagination-btn {
  display: inline-flex;
  align-items: center;
  border: none;
  background: none;
  color: var(--cmp-ink);
  cursor: pointer;
  padding: 0 0.22222rem;
}
.cmp-pagination-btn:disabled {
  color: var(--cmp-faint);
  cursor: not-allowed;
}
.cmp-nav-icon {
  width: 0.83333rem;
  height: 0.83333rem;
  flex-shrink: 0;
}
.cmp-nav-icon--prev {
  transform: rotate(90deg);
}
.cmp-nav-icon--next {
  transform: rotate(-90deg);
}

.cmp-placeholder {
  background: var(--cmp-card);
  border: 1px dashed var(--cmp-border);
  border-radius: 0.66667rem;
  padding: 2rem;
  text-align: center;
  color: var(--cmp-muted);
  font-size: 0.83333rem;
}

/* ════════════════════════ Portfolio layout (Figma 519:13199 / 490:59783) ════════════════════════
   No KPI cards / no "Outcomes at a glance" — just the Channel-comparison card with a VIEW BY
   Channel/Brand toggle over a BRANDS sidebar. */

/* VIEW BY: reuses the segmented `.cmp-level-toggle` styling with a small "View by" caption. */
.cmp-viewby {
  display: inline-flex;
  align-items: center;
  gap: 0.55556rem;
}
.cmp-viewby-label {
  font-size: 0.61111rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--cmp-faint);
}

/* ── Channel view: sidebar + scrolling table ── */
.cmp-portfolio-body {
  display: flex;
  align-items: stretch;
  gap: 0;
}
.cmp-sidebar {
  flex: 0 0 11.11111rem;
  width: 11.11111rem;
  display: flex;
  flex-direction: column;
  gap: 0.72222rem;
  padding: 0 1.11111rem 0 0;
  border-right: 1px solid var(--cmp-border);
}
.cmp-sidebar-title {
  font-size: 0.58333rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cmp-faint);
}
.cmp-sidebar-search {
  display: flex;
  align-items: center;
  gap: 0.44444rem;
  border: 1px solid var(--cmp-border-strong);
  border-radius: 0.44444rem;
  padding: 0.44444rem 0.55556rem;
  background: var(--cmp-card);
}
.cmp-sidebar-search-icon {
  width: 0.77778rem;
  height: 0.77778rem;
  color: var(--cmp-faint);
  flex-shrink: 0;
}
.cmp-sidebar-search-input {
  border: none;
  outline: none;
  background: transparent;
  font-family: inherit;
  font-size: 0.69444rem;
  color: var(--cmp-ink);
  width: 100%;
}
.cmp-sidebar-search-input::placeholder {
  color: var(--cmp-faint);
}
.cmp-sidebar-scroll {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}
.cmp-sidebar-tree {
  display: flex;
  flex-direction: column;
  gap: 0.11111rem;
}
.cmp-sidebar-empty {
  padding: 0.44444rem 0.38889rem;
  font-size: 0.69444rem;
  color: var(--cmp-faint);
  text-align: center;
}
.cmp-brand-node {
  display: flex;
  flex-direction: column;
}
.cmp-brand-row {
  display: flex;
  align-items: center;
  gap: 0.44444rem;
  width: 100%;
  border: none;
  background: transparent;
  border-radius: 0.38889rem;
  padding: 0.44444rem 0.38889rem;
  cursor: pointer;
  text-align: left;
}
.cmp-brand-row:hover {
  background: var(--cmp-b-tint);
}
.cmp-brand-caret {
  width: 0.83333rem;
  height: 0.83333rem;
  color: var(--cmp-faint);
  transform: rotate(-90deg);
  transition: transform 0.15s ease;
  flex-shrink: 0;
}
.cmp-brand-caret.is-open {
  transform: rotate(0deg);
}
.cmp-brand-name {
  flex: 1;
  font-size: 0.72222rem;
  font-weight: 700;
  color: var(--cmp-ink);
  text-transform: capitalize;
}
.cmp-brand-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.11111rem;
  height: 1.11111rem;
  padding: 0 0.33333rem;
  border-radius: 999px;
  background: #eceef3;
  color: var(--cmp-muted);
  font-size: 0.61111rem;
  font-weight: 600;
}
.cmp-combo-row {
  border: none;
  background: transparent;
  border-radius: 0.38889rem;
  padding: 0.44444rem 0.44444rem 0.44444rem 1.55556rem;
  text-align: left;
  cursor: pointer;
  font-size: 0.69444rem;
  color: var(--cmp-cell-fg);
}
.cmp-combo-row:hover {
  background: var(--cmp-b-tint);
}
.cmp-combo-row.is-active {
  background: var(--cmp-a-tint);
  color: var(--cmp-navy);
  font-weight: 600;
}
.cmp-portfolio-table {
  flex: 1;
  min-width: 0;
  padding-left: 1.11111rem;
  display: flex;
  flex-direction: column;
  gap: 0.55556rem;
}

/* ── Portfolio table variant: A·/B· group headers are mixed-case bold (not the
   Single Cell uppercase scenario name). Scenario name is centred (see
   `.cmp-table th.cmp-th-group` below). The A-side tint that used to live here is now a
   base rule shared with Single Cell — see `.cmp-th-group--a, .cmp-th-group--mat`. ── */
.cmp-table--portfolio .cmp-th-group {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 700;
}
.cmp-table--portfolio .cmp-th-brand {
  text-transform: uppercase;
  font-size: 0.58333rem;
  letter-spacing: 0.03em;
  color: var(--cmp-th-fg);
}

/* Bold "Portfolio total" row under VIEW BY Brand (Figma 490:59783). */
.cmp-row-total td {
  border-top: 1px solid var(--cmp-border);
  font-weight: 700;
  color: var(--cmp-ink);
  background: var(--cmp-group-cell);
}
.cmp-table tbody .cmp-row-total .cmp-td-channel {
  font-weight: 700;
  background: var(--cmp-group-cell);
}

@media (max-width: 820px) {
  .cmp-portfolio-body {
    flex-direction: column;
  }
  .cmp-sidebar {
    flex-basis: auto;
    width: 100%;
    border-right: none;
    border-bottom: 1px solid var(--cmp-border);
    padding: 0 0 0.88889rem 0;
  }
  .cmp-portfolio-table {
    padding-left: 0;
  }
}

/* ════════════════════════ Table interactions: sort + column filter ════════════════════════ */

/* Centre the scenario-name group header for BOTH variants. The base
   `.cmp-th-group { text-align: center }` is out-specificity'd by `.cmp-table th
   { text-align: right }` (0,1,1 > 0,1,0), so it needs an explicit higher-specificity
   rule (0,2,1) to win. */
.cmp-table th.cmp-th-group {
  text-align: center;
}

/* Sort control appended after each numeric sub-header label; sits inline at the end of
   the label, which `.cmp-subhead th`'s `nowrap` keeps on the same line. */
.cmp-sort-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  vertical-align: middle;
  flex-shrink: 0;
}

/* Funnel button beside each dimension-column header. */
.cmp-filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  padding: 0;
  margin-left: 0.16667rem;
  cursor: pointer;
}
/* Same hover feedback as the RESULTS screen's `.or-th-filter-btn:hover svg path` —
   `ColFilterIcon` fills its path with a hardcoded hex rather than `currentColor`, so hover
   has to override that fill directly; a CSS rule beats an SVG presentation attribute in
   the cascade even without `!important`. */
.cmp-filter-btn:hover svg path {
  fill: var(--cmp-navy);
}

/* Empty state when every row is filtered out. */
.cmp-table td.cmp-td-empty-row {
  text-align: center;
  white-space: normal;
  padding: 1.55556rem 0.55556rem;
  color: var(--cmp-faint);
  font-weight: 500;
}

/* The column-filter popover itself is now the shared `ColumnFilter` component
   (`src/components/ColumnFilter`) — it ships its own stylesheet reproducing
   the old optimizer's `DataTable` filter popover, so no `.cmp-filter-pop*`
   styles live here any more. */
/*$vite$:1*/