/* ========= Sidebar: no-flash init when pinned (class set by <head> script) ===
   Applied before first paint so the sidebar renders at full width instantly.
   Removed immediately after JS applies .sidebar-pinned, restoring transitions. */
html._sbp .sidebar-nav {
  width: 260px;
  transition: none !important;
}
html._sbp .sidebar-nav .sidebar-nav__brand span {
  opacity: 1;
  transition: none !important;
}
html._sbp .sidebar-nav .sidebar-toggle-label {
  opacity: 1;
  transition: none !important;
}
html._sbp .sidebar-nav .sidebar-nav__toggle {
  color: var(--accent);
}
html._sbp .sidebar-nav .sidebar-nav__label {
  opacity: 1;
  transition: none !important;
}
html._sbp .sidebar-nav .sidebar-nav__collapse-trigger::after {
  opacity: 1;
  transition: none !important;
}
html._sbp .sidebar-nav .sidebar-nav__logout .sidebar-nav__label {
  opacity: 1;
  transition: none !important;
}
html._sbp .sidebar-nav ~ .main-panel > .content {
  padding-left: calc(260px + 30px) !important;
  transition: none !important;
}
@media (max-width: 991.98px) {
  html._sbp .sidebar-nav ~ .main-panel > .content {
    padding-left: 30px !important;
  }
}
/* ======================================================================== */

/* ========= Solution-B type + colour scale — single source of truth =========
   One coherent font ladder AND one "whiteness" ladder for the detail/form
   pages. Sizes climb from the standard input/label text up to the section-
   emphasis ceiling (h4); tabs sit one notch above that, and the project header
   keeps its size but drops to a thin weight. Plot font SIZES live in qsystem.ts
   (Plotly needs px): on-screen plot title = the .stacked-area-chart-header (var
   below), axis titles = 13px, export plot title = 18px.

   Colour: on the dark bg, text is one white at decreasing alpha — higher alpha
   reads as more important/whiter. Params/body stay at the theme default (0.8),
   sitting between the headers (0.9) and the input text (0.6). Plot axis text is
   dimmed page-scoped further down (it can't read CSS vars from JS, so the SVG
   fill is overridden there). Reference these vars instead of hard-coding. */
body.solution-b {
  --fs-input: 0.75rem; /* 12px   — input value text (smallest standard) */
  --fs-text: 0.8125rem; /* 13px   — field labels, body, tables */
  --fs-emphasis: 0.875rem; /* 14px   — sub-section headings; sparingly, hard ceiling */
  --fs-tab: 0.9375rem; /* 15px   — tabs + on-screen plot title */

  --fc-strong: #fff; /* 1.0 — whitest: active tab */
  --fc-kpi: rgba(255, 255, 255, 0.85); /* 0.85 — KPI value (softened) */
  --fc-heading: rgba(255, 255, 255, 0.9); /* 0.9 — sub-section headers */
  --fc-muted: rgba(255, 255, 255, 0.6); /* 0.6 — input/table text, plot axes */
  --fc-faint: rgba(
    255,
    255,
    255,
    0.5
  ); /* lowest emphasis; 0.5 keeps small text legible (was 0.4) */

  /* Brand colours. Use var(--accent) for solid uses and
     rgba(var(--accent-rgb), a) where an alpha is needed. */
  --accent: #08acde; /* primary accent (links, active borders, bus) */
  --accent-rgb: 8, 172, 222;
  --panel-bg: #27293d; /* card/panel background on the dark theme */
}

/* ========= Sidebar Nav — flat navbar style, vertical orientation ========= */
.main-panel > .navbar {
  display: none !important;
}
.sidebar-nav {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  width: 62px;
  background: var(--panel-bg);
  border-right: 2px solid var(--accent);
  z-index: 1030;
  overflow: hidden;
  transition: width 0.3s ease;
  display: flex;
  flex-direction: column;
  font-family: "Poppins", sans-serif;
}
.sidebar-nav:hover,
.sidebar-nav.sidebar-pinned {
  width: 260px;
}
.sidebar-nav__body {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 8px 0;
}
.sidebar-nav__bottom {
  flex: 0 0 auto;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding: 8px 0;
}
.sidebar-nav__brand {
  display: flex;
  align-items: center;
  /* left padding matches .sidebar-nav__item (18px) so the logo shares the
     nav-icon left guide */
  padding: 12px 18px;
  text-decoration: none;
  color: #fff;
  text-transform: uppercase;
  font-size: 1.125rem;
  font-weight: 400;
  white-space: nowrap;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  flex: 0 0 auto;
}
.sidebar-nav__brand img {
  /* logo.png is 72x60 — keep its aspect ratio instead of squashing into a
     square (was width:30px;height:30px which distorted it). */
  height: 30px;
  width: auto;
  object-fit: contain;
  margin-right: 12px;
  flex-shrink: 0;
}
.sidebar-nav__brand span {
  opacity: 0;
  transition: opacity 0.2s ease 0.1s;
}
.sidebar-nav:hover .sidebar-nav__brand span,
.sidebar-nav.sidebar-pinned .sidebar-nav__brand span {
  opacity: 1;
}
.sidebar-nav__toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 6px 14px;
  background: none;
  border: none;
  color: var(--fc-muted);
  cursor: pointer;
  font-size: 16px;
  flex: 0 0 auto;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.sidebar-nav__toggle:hover {
  color: #fff;
}
.sidebar-nav__toggle .sidebar-toggle-label {
  opacity: 0;
  margin-left: 10px;
  font-size: 0.75rem;
  text-transform: uppercase;
  transition: opacity 0.2s ease 0.1s;
  white-space: nowrap;
}
.sidebar-nav:hover .sidebar-toggle-label,
.sidebar-nav.sidebar-pinned .sidebar-toggle-label {
  opacity: 1;
}
.sidebar-nav.sidebar-pinned .sidebar-nav__toggle {
  color: var(--accent);
}
.sidebar-nav__item {
  display: flex;
  align-items: center;
  padding: 8px 18px;
  color: rgba(255, 255, 255, 0.8);
  text-decoration: none;
  white-space: nowrap;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  transition: color 0.15s ease, background 0.15s ease;
}
.sidebar-nav__item:visited,
.sidebar-nav__item:active,
.sidebar-nav__item:focus {
  color: rgba(255, 255, 255, 0.8) !important;
  background: none !important;
}
.sidebar-nav__item:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
  text-decoration: none;
}
.sidebar-nav__item.show:hover {
  color: #fff !important;
  background: rgba(255, 255, 255, 0.06) !important;
  text-decoration: none;
}
.sidebar-nav__item:hover,
.sidebar-nav__item.show:hover,
.sidebar-nav__item.active:hover,
.sidebar-nav__item[aria-expanded="true"]:hover,
.sidebar-nav__item.collapsing:hover {
  color: #fff !important;
  background: rgba(255, 255, 255, 0.06) !important;
  text-decoration: none;
}
.sidebar-nav__item i {
  font-size: 18px;
  width: 26px;
  text-align: center;
  flex-shrink: 0;
  margin-right: 12px;
}
.sidebar-nav__item .sidebar-nav__label {
  opacity: 0;
  transition: opacity 0.2s ease 0.1s;
}
.sidebar-nav:hover .sidebar-nav__label,
.sidebar-nav.sidebar-pinned .sidebar-nav__label {
  opacity: 1;
}
.sidebar-nav__collapse-trigger {
  cursor: pointer;
  position: relative;
}
.sidebar-nav__collapse-trigger::after {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid rgba(255, 255, 255, 0.5);
  border-bottom: 1.5px solid rgba(255, 255, 255, 0.5);
  transform: rotate(-45deg);
  transition: transform 0.2s ease;
  position: absolute;
  right: 18px;
  top: 50%;
  margin-top: -4px;
  opacity: 0;
}
.sidebar-nav:hover .sidebar-nav__collapse-trigger::after,
.sidebar-nav.sidebar-pinned .sidebar-nav__collapse-trigger::after {
  opacity: 1;
}
.sidebar-nav__collapse-trigger[aria-expanded="true"]::after {
  transform: rotate(45deg);
  margin-top: -6px;
}
.sidebar-nav__sub {
  padding-left: 0;
  list-style: none;
  margin: 0;
}
.sidebar-nav__sub .sidebar-nav__subitem {
  display: block;
  padding: 5px 18px 5px 56px;
  color: var(--fc-muted);
  font-size: 0.7rem;
  text-transform: none;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s ease, background 0.15s ease;
}
.sidebar-nav__sub .sidebar-nav__subitem:visited,
.sidebar-nav__sub .sidebar-nav__subitem:active,
.sidebar-nav__sub .sidebar-nav__subitem:focus {
  color: var(--fc-muted) !important;
  background: none !important;
}
.sidebar-nav__sub .sidebar-nav__subitem:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
  text-decoration: none;
}
.sidebar-nav__sub .sidebar-nav__subheader {
  display: block;
  padding: 6px 18px 2px 56px;
  color: var(--fc-faint);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  pointer-events: none;
}
.sidebar-nav__sub .sidebar-nav__divider {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  margin: 4px 56px 4px 56px;
}
.sidebar-nav__job-spinner {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 20px;
  flex-shrink: 0;
  margin-right: 12px;
}
.sidebar-nav__job-spinner::after {
  content: "";
  display: block;
  width: 20px;
  height: 20px;
  border: 2px solid var(--panel-bg);
  border-top-color: var(--accent);
  border-top-color: var(--accent);
  border-right-color: var(--accent);
  border-bottom-color: var(--accent);
  border-radius: 50%;
  animation: sidebar-spin 0.8s linear infinite;
}
@keyframes sidebar-spin {
  to {
    transform: rotate(360deg);
  }
}
.sidebar-nav__logout {
  display: flex;
  align-items: center;
  padding: 8px 18px;
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  background: none;
  border: none;
  width: 100%;
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}
.sidebar-nav__logout:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
  text-decoration: none;
}
.sidebar-nav__logout i {
  font-size: 18px;
  width: 26px;
  text-align: center;
  flex-shrink: 0;
  margin-right: 12px;
}
.sidebar-nav__logout .sidebar-nav__label {
  opacity: 0;
  transition: opacity 0.2s ease 0.1s;
}
.sidebar-nav:hover .sidebar-nav__logout .sidebar-nav__label,
.sidebar-nav.sidebar-pinned .sidebar-nav__logout .sidebar-nav__label {
  opacity: 1;
}
.main-panel > .content {
  padding-left: calc(62px + 30px) !important;
  padding-top: 15px !important;
  transition: padding-left 0.3s ease;
}
.sidebar-nav.sidebar-pinned ~ .main-panel > .content {
  padding-left: calc(260px + 30px) !important;
}
.sidebar-nav__mobile-toggle {
  display: none;
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 1070;
  background: var(--panel-bg);
  border: 1px solid var(--accent);
  border-radius: 4px;
  color: #fff;
  font-size: 20px;
  padding: 6px 10px;
  cursor: pointer;
  line-height: 1;
}
@media (max-width: 991.98px) {
  .sidebar-nav {
    transform: translateX(-100%);
    transition: transform 0.3s ease, width 0.3s ease;
    width: 260px;
  }
  .sidebar-nav.sidebar-open {
    transform: translateX(0);
  }
  .sidebar-nav.sidebar-open .sidebar-nav__label,
  .sidebar-nav.sidebar-open .sidebar-nav__brand span,
  .sidebar-nav.sidebar-open .sidebar-toggle-label,
  .sidebar-nav.sidebar-open .sidebar-nav__collapse-trigger::after,
  .sidebar-nav.sidebar-open .sidebar-nav__logout .sidebar-nav__label {
    opacity: 1;
  }
  .sidebar-nav__mobile-toggle {
    display: block;
  }
  .main-panel > .content {
    padding-left: 30px !important;
    padding-top: 50px !important;
  }
  .sidebar-nav.sidebar-pinned ~ .main-panel > .content {
    padding-left: 30px !important;
  }
  .sidebar-nav-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 1055;
  }
  .sidebar-nav-backdrop.active {
    display: block;
  }
}

/* --- Settings field rows --- */
.settings-field-row {
  margin-bottom: 2px;
}
.settings-field-row .form-group {
  margin-bottom: 0;
}
.settings-field-row [class*="col-"] {
  padding-right: 0;
}
.settings-field-row .col-form-label {
  font-size: var(--fs-text);
  font-weight: 300;
  padding-top: 0.25rem;
  padding-bottom: 0;
}
/* Field frame: one slightly-translucent grey line shared by every input field.
   A translucent white adapts to the card behind it, so the line reads equally
   soft whether the card is near-black (settings/component cards) or lighter
   (the #2b2d42 min/base/max cards). The solid #676767 theme line looked harsher
   on the darker cards; this matches the soft min/base/max look everywhere.
   Kept at low specificity so per-field :hover/:focus (accent) still win. */
.form-control:not([type="checkbox"]):not([type="radio"]) {
  border-color: rgba(255, 255, 255, 0.18);
}
.settings-field-row .form-control:not([type="checkbox"]),
.create-settings-strip .css-field .form-control {
  /* Transparent fill so the card shows through (frame colour set globally above). */
  background-color: transparent;
  /* entered values read as filled, not placeholder (brighter + normal weight) */
  color: var(--fc-kpi);
  font-size: var(--fs-input);
  font-weight: 400;
  /* The theme gives inputs a fixed height, leaving the value floating with empty
     space above/below; size to content instead so dense forms stay compact. */
  height: auto;
  line-height: 1.4;
  padding-top: 0.2rem;
  padding-bottom: 0.2rem;
  padding-left: 8px;
}
.settings-field-row .form-control::placeholder,
.create-settings-strip .css-field .form-control::placeholder {
  color: var(--fc-faint);
  font-weight: 300;
}
.settings-field-row .form-control:not([type="checkbox"]):hover,
.create-settings-strip .css-field .form-control:hover {
  border-color: var(--fc-faint);
}
.settings-field-row .form-control:not([type="checkbox"]):focus,
.create-settings-strip .css-field .form-control:focus {
  border-color: var(--accent);
  background-color: transparent;
}
.settings-field-row .form-control[type="checkbox"] {
  width: auto;
  height: auto;
  background-color: transparent;
  border-color: transparent;
  padding: 0;
  margin-top: 0.55rem;
  display: block;
}
.settings-field-row.has-danger .form-control {
  border-color: #ff8d72;
  color: #ff8d72;
}
.settings-field-row.has-danger:after {
  color: #ff8d72;
}
.settings-field-unit {
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.45);
  padding-top: 0.25rem;
}

/* Inside compact component cards the unit column is narrow — allow wrapping
   after "/" so e.g. "€/kWh" can split to "€/" + "kWh" rather than overflow. */
.component-card .settings-field-unit {
  overflow-wrap: anywhere;
  hyphens: none;
}

/* --- Settings description column --- */
.settings-description-col {
  display: flex;
  flex-direction: column;
}
.settings-description-col hr.settings-section-hr {
  flex-shrink: 0;
  border: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  margin-top: 0;
  margin-bottom: 10px;
  width: 100%;
}
.settings-description-col textarea {
  flex: 1 1 0;
  min-height: 100px;
  max-height: none;
  resize: none;
  background-color: transparent;
  color: inherit;
  font-size: 0.875rem;
  padding-left: 8px;
}
.settings-description-col textarea:hover {
  border-color: var(--fc-faint);
}
.settings-description-col textarea:focus {
  border-color: var(--accent);
  background-color: transparent;
  outline: none;
}
.settings-section-hr {
  border-color: rgba(255, 255, 255, 0.15);
  margin-top: 6px;
  margin-bottom: 10px;
}

/* --- Settings name field --- */
.settings-name-icon {
  font-size: 1.1rem;
}

/* --- Settings layout --- */
.settings-row {
  column-gap: 15px;
  align-items: stretch;
}
/* Space after each project-settings section so stacked sections (e.g. Economic
   + Sensitivity, Location + Optimization) don't butt together — a gap before the
   next section's header. Only project settings use .table-responsive as the
   section wrapper; component forms space their rows via .mt-3, so they're
   unaffected. Collapses with .settings-optimization-section's margin-top. */
.settings-row .table-responsive {
  margin-bottom: 1.25rem;
}
#location-row {
  column-gap: 15px;
  margin-top: 20px;
  align-items: stretch;
}
.col-third {
  flex: 0 0 32%;
  min-width: 0;
}
.col-third-wide {
  flex: 0 0 32.5%;
  min-width: 0;
}
.col-two-thirds {
  flex: 0 0 65%;
  min-width: 0;
}
.col-half {
  flex: 0 0 49%;
  min-width: 0;
}
.aging-formset-chart-section {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  gap: 15px;
  align-items: flex-start;
}
.aging-formset-chart-section .aging-matrix-col,
.aging-formset-chart-section .aging-chart-col {
  flex: 1;
  min-width: 0;
  overflow: hidden;
}
.settings-optimization-section {
  margin-top: 20px;
}
.settings-map-col {
  flex: 0 0 49%;
  display: flex;
  padding-top: 2.5rem;
}
#project-location-map {
  width: 100%;
  /* bigger + square (was a short landscape strip) */
  aspect-ratio: 1 / 1;
  height: auto !important;
  min-height: 360px;
}

/* --- Settings form errors --- */
#tab-settings .has-danger .form-control {
  border-color: #ff8d72;
  color: #ff8d72;
}
#tab-settings .has-danger:after {
  color: #ff8d72;
}
.form-control-feedback {
  color: #ff8d72;
  font-size: 0.875em;
}
.errorlist {
  padding-left: 11px;
}
#id_name_error.errorlist {
  margin-left: 25px;
}

/* --- General layout --- */
.nav-link {
  padding-top: 4px !important;
  padding-bottom: 4px !important;
  padding-left: 10px !important;
  padding-right: 10px !important;
}
.card {
  margin-bottom: 15px !important;
}
.tab-content.tab-space {
  padding-top: 15px !important;
}
.card-header {
  padding-top: 15px !important;
}
.card-body {
  padding-top: 0px !important;
  margin-top: -5px !important;
  margin-bottom: -10px !important;
}
#components-row,
#environment-row {
  margin-top: 25px !important;
}
#inputs-row {
  margin-top: 18px !important;
}
#tab-settings .table input[type="checkbox"].form-control {
  width: auto;
  height: auto;
  display: inline-block;
}

/* --- Reusable row layout --- */
.gap-row {
  column-gap: 15px;
}

/* --- Dropdown --- */
.dropdown-inline {
  display: inline-block;
}

/* --- System schematic --- */
.system-schematic-img {
  padding: 10px 20px 20px;
}

/* --- Table header actions (input file / RES data) --- */
.table-header-actions {
  margin-right: 20%;
}

/* --- Summary hrules --- */
.hrule-pb {
  padding-bottom: 10px;
}
.hrule-mt {
  margin-top: 20px;
}

/* --- Overview items --- */
.overview-row {
  display: flex;
  margin-top: 10px;
  margin-bottom: 0;
}
/* KPI tiles: icon in front, small UPPERCASE label, large value, small unit.
   Boxed (matching the Economics/Technical .skpi tiles) with the theme's vertical
   dividers dropped, so the two KPI styles read as one. */
.overview-item-body {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  text-align: left;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  height: 100%;
}
/* Drop the theme's vertical divider between tiles (now each tile is a box). */
.result-highlight:not(:last-child) {
  border-right: none;
}
.overview-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.45);
  font-size: 26px;
}
.overview-text {
  min-width: 0;
}
.overview-label {
  margin-bottom: 0;
  /* one eyebrow-label size, shared with the .skpi section tiles */
  font-size: 0.66rem;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.25;
  color: var(--fc-muted);
}
.overview-value-p {
  margin-bottom: 0;
  margin-top: 5px;
  line-height: 1.2;
}
.overview-value {
  /* one big-number size + weight, shared with the .skpi section tiles */
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--fc-heading);
}
/* Unavailable KPI value: a quiet "n/a" instead of full-size placeholder dashes. */
.overview-value.overview-na {
  font-size: 1rem;
  font-weight: 300;
  color: var(--fc-faint);
}
.overview-unit {
  font-size: 0.75rem;
  font-weight: 300;
  color: var(--fc-muted);
}
.overview-help-icon {
  margin-top: -4px;
  font-size: 0.8rem;
}

/* --- Economics charts --- */
/* Side-by-side charts (Initial investment + Costs overview). The Bootstrap .row
   negative margins made the fixed-% columns overflow and wrap; use a plain flex
   row with equal-width children so they always sit next to each other. */
.economics-chart-row {
  display: flex;
  flex-wrap: nowrap;
  gap: 12px;
  margin-left: 0;
  margin-right: 0;
  padding: 0;
}
.economics-chart-row > .triple-plot {
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
}
/* Section titles above the result tables (Economic/Technical performance,
   Operations, Emissions) — were dropped in the scroll-section redesign. */
.section-table-title {
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--fc-heading);
  margin-bottom: 0.75rem;
}

/* Result-page data tables sit in boxes that match the plot boxes
   (.plotly-plot-div): thin border, 12px radius, transparent fill. Scoped to the
   Summary + Economics/Technical data tables; the Settings tab reuses
   .table-responsive as a plain section wrapper, so it is left untouched. */
.summary-tables-box,
.results-scroll-section .table-responsive {
  border: 1.5px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
}
.results-scroll-section .table-responsive {
  padding: 6px 14px;
  margin-bottom: 16px;
}
.results-scroll-section .table-responsive .table {
  margin-bottom: 0;
}
/* Summary: About + Warnings share one box, and both columns are flex so the plot
   box and the tables box each fill the equal column height and come out the same
   size. (Without this the plot box was 10px shorter — its theme margin-bottom.) */
#summary-plot-row > div {
  display: flex;
  flex-direction: column;
}
#summary-plot-row .plotly-plot-div {
  flex: 1;
  margin-bottom: 0;
}
.summary-tables-box {
  flex: 1;
  padding: 10px 16px 14px;
}
.summary-tables-box .table {
  margin-bottom: 0;
}
/* The result-table rows are Bootstrap .row's (negative side margins), so they
   bled ~15px past the full-width plot boxes. Zero the row margins + column
   gutters and let .gap-row provide the inter-column gap, so the tables line up
   exactly with the plot boxes above them. */
#economics-row,
#technical-row,
#technical-emissions-row {
  margin-left: 0;
  margin-right: 0;
}
#economics-row > [class*="col-"],
#technical-row > [class*="col-"],
#technical-emissions-row > [class*="col-"] {
  padding-left: 0;
  padding-right: 0;
}

/* --- Time-series time-range selector: a compact, light segmented control in
   the top-right of each chart header (replaces the chunky button group). The
   radio inputs/names are unchanged, so the existing window logic in qsystem.ts
   still drives it — only the look + placement change. Kept quieter than the
   section selector pills above (smaller, dimmer, subtle blue when active). --- */
.ts-plot-header-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.ts-plot-header-row .stacked-area-chart-header {
  flex: 1 1 auto;
  min-width: 0; /* allow a long title to wrap instead of crowding the pills */
  margin-bottom: 0;
  text-align: left;
}
.ts-timerange {
  flex: 0 0 auto;
  align-self: flex-start; /* stay at the top if the title wraps to two lines */
  display: inline-flex;
  flex-wrap: wrap;
  gap: 3px;
  justify-content: flex-end;
}
.ts-timerange > .btn {
  margin: 0 !important;
  padding: 4px 7px !important; /* higher + less wide than before */
  font-size: var(--fs-text) !important; /* same size as the section selector */
  font-weight: 300 !important;
  line-height: 1.2 !important;
  border-radius: 6px !important;
  color: rgba(255, 255, 255, 0.55) !important;
  background: transparent !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  box-shadow: none !important;
}
.ts-timerange > .btn:hover {
  color: var(--fc-heading) !important;
}
.ts-timerange > .btn.active {
  color: var(--fc-strong) !important;
  border-color: var(--accent) !important;
}

/* Nudge the hover modebar down off the top edge of the time-series plots so it
   no longer sits right on the chart title / top gridline. */
body.solution-b .stacked-area-plot-div .modebar {
  top: 12px !important;
  right: 8px !important;
}

/* Mute the hard white 1.5px frame the shared theme (_plots.scss .plotly-plot-div)
   draws around every plot — it reads as a bright "white box" on the dark UI.
   solution_b.css loads after the compiled theme, so this wins. */
.plotly-plot-div {
  border-color: rgba(255, 255, 255, 0.08);
  /* Match the 12px card radius (theme draws plot boxes at ~4px). */
  border-radius: 12px;
  /* More breathing room before the (now left-aligned) plot title: the shared
     theme gives 11px top and no left padding, so the title hugged the box edge. */
  padding-top: 18px;
  padding-left: 16px;
}
/* The bundled theme forces `.triple-plot { padding-left: 0 !important }`, which
   made the initial-investment / costs plot titles hug the left edge. Restore the
   same left padding as the other plots (needs !important to beat it). */
#project-detail-card .triple-plot,
#component-detail-card .triple-plot {
  padding-left: 16px !important;
}

/* --- Technical performance --- */
#efficiency-plot-container {
  max-height: 375px;
}

/* --- Sensitivity tab --- */
#tab-sensitivity .table td {
  border-top: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.sensitivity-label-td {
  width: 65%;
}
.sensitivity-value-td {
  width: 50%;
}
.sensitivity-badge {
  font-weight: normal;
  font-size: 1em;
  background-color: rgba(255, 255, 255, 0.1);
  color: inherit;
}
.sensitivity-alert-icon {
  margin-top: -3px;
}

/* --- Project detail card and tabs --- */
#project-detail-card,
#component-detail-card {
  border-radius: 0 0 0.2857rem 0.2857rem;
}
/* The Economics/Technical results selector is position:sticky, which needs a
   non-clipping path up to the scroll container (.main-panel). The theme sets
   overflow:hidden on .card and .card-body, which would pin the selector to the
   non-scrolling card and break it. Unclip the project-detail card + its body;
   display:flow-root keeps the block-formatting context so margins/layout are
   unchanged. Scoped + in solution_b.css, so the original UI is untouched. */
#project-detail-card,
#project-detail-card > .card-body {
  overflow: visible;
  display: flow-root;
}
#project-detail-tabs,
#component-detail-tabs {
  border-bottom: none;
  padding: 0;
  margin-bottom: 0px;
  position: relative;
  z-index: 1;
  /* Equal-width tabs sized to the WIDEST label — not stretched to the full
     window. An auto-flow grid of 1fr columns shrunk to its content
     (width:max-content) makes every tab the same width = the widest tab's
     content; max-width:100% keeps an over-long strip from exceeding the card.
     Applies independently to the component and the project-settings strips. */
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  width: max-content;
  max-width: 100%;
  gap: 2px;
}
#project-detail-tabs .nav-item > .nav-link,
#component-detail-tabs .nav-item > .nav-link {
  border-radius: 8px 8px 0 0 !important;
  border-top: 2px solid rgba(255, 255, 255, 0.06);
  border-left: 1px solid rgba(255, 255, 255, 0.08);
  border-right: 1px solid rgba(255, 255, 255, 0.08);
  border-bottom: 2px solid transparent;
  padding: 8px 10px;
  text-align: center;
  font-size: var(--fs-tab);
  font-weight: 300;
  color: rgba(255, 255, 255, 0.55);
  background-color: rgba(255, 255, 255, 0.03);
  transition: none;
  /* Fill the grid cell so every tab matches the tallest one's height — a label
     that wraps to two lines no longer leaves the other tabs short with a gap
     above the content block. The grid (above) already stretches each cell. */
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#project-detail-tabs .nav-item > .nav-link:hover,
#component-detail-tabs .nav-item > .nav-link:hover {
  border-top: 2px solid var(--accent) !important;
  border-left: 1px solid var(--accent) !important;
  border-right: 1px solid var(--accent) !important;
  border-bottom: 2px solid var(--panel-bg) !important;
  color: var(--fc-heading);
}
/* The selected tab: a solid accent top border + solid card-coloured fill make
   it read clearly as the active tab against the faint resting tabs (the resting
   container styling otherwise left the selection too subtle on the component
   pages). The bottom border matches the card so the tab connects into it. The
   side borders are transparent (kept at 1px to avoid reflow) so the selected
   tab shows no stray edge line — the blue top + fill carry the selection. */
#project-detail-tabs .nav-item > .nav-link.active,
#component-detail-tabs .nav-item > .nav-link.active {
  border-radius: 8px 8px 0 0 !important;
  border-top: 2px solid var(--accent) !important;
  border-left: 1px solid transparent !important;
  border-right: 1px solid transparent !important;
  border-bottom: 2px solid var(--panel-bg) !important;
  color: var(--fc-strong);
  background-color: var(--panel-bg);
}
#project-detail-tabs .nav-item > .nav-link.active i,
#component-detail-tabs .nav-item > .nav-link.active i {
  color: var(--accent);
}
.tab-icon {
  margin-right: 5px;
}

/* A warning/error alert at the very top of the component form lands in the zone
   where the active tab connects into the card (the card-body has padding:0 and
   the tab strip is position:relative; z-index:1), so the active tab overlaps
   it. Drop top-of-form alerts down clear of the tabs. Covers the "locked"
   warning (card-body) and form non-field errors (#component-form-container). */
#component-detail-card .card-body > .alert:first-child,
#component-form-container > .alert:first-child {
  margin-top: 14px;
}

/* --- Results "scroll" layout (Economics / Technical tabs) ---
   Tables and Charts live on one page; the selector scrolls to a section
   instead of switching panes, and stays pinned to the top while you scroll
   (scroll position drives the active pill — scroll-spy in qsystem.ts). --- */
.results-scroll-nav-wrapper {
  position: sticky;
  top: 0;
  z-index: 6;
  background-color: var(--panel-bg);
  padding-top: 4px;
  margin-bottom: 8px;
}
/* The Tables/Charts switch buttons: SAME pill shape whether active or not —
   only the border + text colour change. !important is needed because the
   theme's `.nav-tabs.nav-tabs-primary` active rule (5 classes) out-specifies us
   and otherwise paints a fill + blue text. Inactive = dim like the resting
   tabs; active = white text + a blue surround (the active highlight is moved by
   initResultsScrollNav in qsystem.ts). */
.results-scroll-nav {
  gap: 6px;
}
.results-scroll-nav > .nav-item > .nav-link {
  cursor: pointer;
  font-size: var(--fs-text);
  font-weight: 300;
  color: rgba(255, 255, 255, 0.55) !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  border-radius: 6px !important;
  background-color: transparent !important;
  padding: 4px 14px;
}
.results-scroll-nav > .nav-item > .nav-link:hover {
  color: var(--fc-heading) !important;
}
.results-scroll-nav > .nav-item > .nav-link.active {
  color: var(--fc-strong) !important;
  border-color: var(--accent) !important;
}
.results-scroll-section {
  /* Land below the sticky selector when scrolled to via the pills. */
  scroll-margin-top: 60px;
}
.results-scroll-section + .results-scroll-section {
  margin-top: 22px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* --- Detail page header top bar (project name + primary actions, pt 1) --- */
.project-detail-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 10px;
}
.project-detail-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Project (and component) detail header: keep the large h2 size, but drop to a
   thin weight so it sits quietly above the data (type-scale concept). */
.project-detail-topbar .card-title {
  font-weight: 200;
}

/* --- De-emphasise chart titles so the data leads (pt 7). Applies to ALL
   Solution-B plot titles (detail cards + the create wizard, which previously
   kept the theme's large centered h3). --- */
body.solution-b .stacked-area-chart-header {
  font-size: var(--fs-tab);
  font-weight: 400;
  /* override Bootstrap's .text-center (which is !important) */
  text-align: left !important;
}
#project-detail-card .card-body h4:not(.overview-label),
#component-detail-card .card-body h4 {
  font-size: var(--fs-emphasis);
  font-weight: 300;
  color: var(--fc-heading);
}

/* --- Plot axis text (Plotly SVG): dim tick labels + axis titles so the data
   leads and the axes don't read as bright white. Plotly paints these as <text>
   with a fill from layout.font.color; override the fill here (page-scoped)
   instead of threading colours through the shared JS layout factories. Result
   plots get a moderate dim (--fc-muted); the component pages + edit modal get a
   stronger one (--fc-faint) — their axes were standing out far too much. --- */
#project-detail-card .js-plotly-plot .xtick text,
#project-detail-card .js-plotly-plot .ytick text,
#project-detail-card .js-plotly-plot .x2tick text,
#project-detail-card .js-plotly-plot .y2tick text,
#project-detail-card .js-plotly-plot .xtitle,
#project-detail-card .js-plotly-plot .ytitle,
#project-detail-card .js-plotly-plot .x2title,
#project-detail-card .js-plotly-plot .y2title {
  fill: var(--fc-muted) !important;
}
#component-detail-card .js-plotly-plot .xtick text,
#component-detail-card .js-plotly-plot .ytick text,
#component-detail-card .js-plotly-plot .x2tick text,
#component-detail-card .js-plotly-plot .y2tick text,
#component-detail-card .js-plotly-plot .xtitle,
#component-detail-card .js-plotly-plot .ytitle,
#component-detail-card .js-plotly-plot .x2title,
#component-detail-card .js-plotly-plot .y2title,
#componentEditModal .js-plotly-plot .xtick text,
#componentEditModal .js-plotly-plot .ytick text,
#componentEditModal .js-plotly-plot .x2tick text,
#componentEditModal .js-plotly-plot .y2tick text,
#componentEditModal .js-plotly-plot .xtitle,
#componentEditModal .js-plotly-plot .ytitle,
#componentEditModal .js-plotly-plot .x2title,
#componentEditModal .js-plotly-plot .y2title {
  fill: var(--fc-faint) !important;
}

/* --- Component edit modal ---
   qsystem.css has two coupled rules that must be neutralised (same issue
   as #addComponentModal above):
     .modal.show .modal-dialog  { transform: translate(0, 30%) }
     .modal-content             { margin-top: -50% }  ← % of *width*, not height
   Both are cancelled here so the dialog sits at a predictable fixed distance
   from the top of the viewport.  The modal-body gets its own scroll so tall
   component forms never push the dialog off-screen. */
#componentEditModal .modal-dialog {
  transform: none !important;
  transition: none !important;
  margin-top: 20px;
  margin-bottom: 20px;
  max-width: 90%;
}
#componentEditModal .modal-content {
  margin-top: 0 !important;
}
#componentEditModal .modal-body {
  overflow-y: auto;
  max-height: calc(100vh - 160px);
}

/* --- Calculation-summary dialog (Review before calculating) ---
   Wide, light-content modal that mirrors the #unsavedChangesModal treatment and
   the detail-page component cards: a responsive grid of per-component cards with
   a clear min/base/max strip and a tidy key/value parameter list. */
.calc-summary-modal {
  max-width: 900px;
}
.calc-summary-modal .modal-content {
  background-color: #ffffff;
  color: #222a42;
}
.calc-summary-modal .modal-title,
.calc-summary-modal .close {
  color: #222a42;
}
.calc-summary-modal .cs-intro {
  color: #6c757d;
  margin-bottom: 1.25rem;
}
.calc-summary-modal .cs-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #6c757d;
  margin: 0 0 0.75rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid #e3e6ea;
}
.calc-summary-modal .cs-section-title:not(:first-of-type) {
  margin-top: 1.5rem;
}
.calc-summary-modal .cs-count {
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 700;
  border-radius: 10px;
  padding: 1px 8px;
}
.calc-summary-modal .cs-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}
.calc-summary-modal .cs-card {
  border: 1px solid #e3e6ea;
  border-radius: 8px;
  padding: 12px 14px;
  background: #f8f9fb;
}
.calc-summary-modal .cs-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.calc-summary-modal .cs-icon {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  background: rgba(var(--accent-rgb), 0.12);
  color: var(--accent);
  font-size: 1.1rem;
}
.calc-summary-modal .cs-titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.calc-summary-modal .cs-name {
  font-weight: 600;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.calc-summary-modal .cs-type {
  font-size: 0.72rem;
  color: #6c757d;
}
.calc-summary-modal .cs-dims {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}
.calc-summary-modal .cs-dim {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: #ffffff;
  border: 1px solid #e9ecef;
  border-radius: 6px;
  padding: 5px 4px;
}
.calc-summary-modal .cs-dim-lbl {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #8a929c;
}
.calc-summary-modal .cs-dim-val {
  font-weight: 600;
  font-size: 0.95rem;
}
.calc-summary-modal .cs-dim-cap {
  font-size: 0.6rem;
  color: #8a929c;
  margin-top: 1px;
  white-space: nowrap;
}
.calc-summary-modal .cs-params {
  margin: 0;
  border-top: 1px dashed #e3e6ea;
  padding-top: 8px;
}
.calc-summary-modal .cs-param {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.8rem;
  padding: 2px 0;
}
.calc-summary-modal .cs-param dt {
  font-weight: 400;
  color: #6c757d;
}
.calc-summary-modal .cs-param dd {
  margin: 0;
  font-weight: 600;
  text-align: right;
}
.calc-summary-modal .cs-options {
  display: flex;
  align-items: center;
  gap: 14px;
}
.calc-summary-modal .cs-option-label {
  margin: 0;
  font-weight: 600;
}
.calc-summary-modal #force-hourly-selector {
  color: #222a42;
  width: 100px;
}
@media (max-width: 700px) {
  .calc-summary-modal .cs-grid {
    grid-template-columns: 1fr;
  }
}

.btn-primary {
  color: #fff !important;
}

/* --- Unsaved-changes prompt (Calculate) --- */
#unsavedChangesModal .modal-content {
  background-color: #ffffff;
  color: #222a42;
}
#unsavedChangesModal .modal-title,
#unsavedChangesModal .close {
  color: #222a42;
}
#unsavedChangesModal .unsaved-list {
  margin: 0.5rem 0 1rem;
  padding-left: 1.25rem;
}
#unsavedChangesModal .unsaved-list li {
  margin-bottom: 0.25rem;
  color: #222a42;
  font-weight: 600;
}

/* --- Upload / preview modal (Inputs tab) --- */

/* Custom file input: style the Browse button for dark bg */
#uploadModal .custom-file-label {
  background-color: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.2);
}
#uploadModal .custom-file-label::after {
  color: #fff;
  background-color: var(--accent);
  border-color: var(--accent);
}
/* Form selects inside modal */
#uploadModal select.form-control {
  background-color: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.2);
}
/* Info box for upload instructions */
#uploadModal .info-box {
  background-color: rgba(255, 255, 255, 0.05);
  border: 1.5px solid rgba(255, 255, 255, 0.15);
  padding: 15px;
  border-radius: 0.2857rem;
  margin-bottom: 20px;
}
#uploadModal .info-box code {
  color: var(--accent);
}
/* Upload modal action buttons */
#uploadModal .upload-modal-actions {
  margin-top: 30px;
  display: flex;
  justify-content: space-between;
}
/* Preview: help text section */
#uploadModal .load-preview-help-text {
  margin-top: 15px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  padding-bottom: 15px;
}
/* Preview: RES download section */
#uploadModal .preview-res-section {
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  margin-bottom: 25px;
}
#uploadModal .preview-res-heading {
  margin-top: 20px;
  margin-bottom: 5px;
  font-size: 1rem;
}
/* Preview: action buttons layout */
#uploadModal .load-generator-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 15px;
}
/* Preview: reserve the full Plotly render height (600px, matching makeBasicPlotLayout /
   makeTimeSeriesLayout) on the chart target divs. This ensures the afterSwap height
   measurement already includes chart space so the animation targets the correct final
   height and Plotly rendering into those divs causes no visible jump. */
#uploadModal #modal-load-profile-plot,
#uploadModal #modal-inputs-timeseries-plot {
  min-height: 600px;
}
#uploadModal .tab-content.tab-space {
  min-height: 400px;
}

/* Body-level upload spinner (hidden by default, shown via JS or hx-indicator) */
#upload-body-spinner {
  display: none;
}
#upload-body-spinner.htmx-request {
  display: block !important;
}

/* --- Main content blur when upload modal is open --- */
.main-panel > .content,
.main-panel > nav,
.main-panel > .footer,
.sidebar-nav {
  transition: filter 0.2s ease;
}
.modal-open-blur .main-panel > .content,
.modal-open-blur .main-panel > nav,
.modal-open-blur .main-panel > .footer,
.modal-open-blur .sidebar-nav {
  filter: blur(4px);
}

.modal-body .card-header {
  background-color: inherit;
}

/* transform removed: CSS transform on a modal ancestor creates a new stacking context
   that traps the Bootstrap backdrop behind modal content, preventing dismiss clicks. */

/* --- Component form field groups & formset sections --- */
.component-formset-section {
  margin-top: 1rem;
  margin-bottom: 1rem;
}
.component-formset-section [id$="-component-chart"],
#wind-power-curve-chart {
  width: 100%;
  min-height: 250px;
  margin-bottom: 0.75rem;
}
.component-formset-section .formset-row-header {
  font-weight: 600;
  font-size: var(--fs-text);
  color: var(--fc-muted);
  margin-bottom: 6px;
}
.component-formset-section .formset-row-fields {
  margin-bottom: 4px;
}
/* Match the compact settings-field inputs (.settings-field-row .form-control):
   the matrix cells (cycle-aging, charge/discharge-power, etc.) otherwise kept
   the default Bootstrap input height/font and read much bigger than the rest. */
.component-formset-section .formset-row-fields input.form-control {
  background-color: transparent;
  color: var(--fc-muted);
  font-size: var(--fs-input);
  font-weight: 300;
  height: auto;
  line-height: 1.4;
  padding-top: 0.2rem;
  padding-bottom: 0.2rem;
  padding-left: 8px;
}
#component-detail-card .settings-row {
  margin-top: 0;
}
#component-detail-card .settings-row + .settings-row {
  margin-top: 20px;
}
#component-output-plot-container {
  height: 350px;
  margin-left: 10px;
  border: none;
}

/* --- Detail-page tables: pull onto the type + colour scale ---
   The theme paints .table text slate (#525f7f) at the base font-size, so the
   summary/result tables read dim and oversized against the dense settings UI.
   Match them to the settings inputs — same size (--fs-input) and white
   (--fc-muted) — so they fit in. Scoped to the detail cards; .list-table etc.
   keep their own. */
#project-detail-card .table,
#component-detail-card .table {
  font-size: var(--fs-input);
  color: var(--fc-muted);
}
/* Make the value column stand out from its label (was the same dim grey). */
#project-detail-card .table tbody td:last-child,
#component-detail-card .table tbody td:last-child {
  color: var(--fc-heading);
  font-weight: 500;
}

/* --- Shared list table styles --- */
.list-search {
  max-width: 300px;
}
.list-table {
  table-layout: fixed;
  font-size: var(
    --fs-input
  ); /* match the detail/result tables (one table size) */
}
.list-table td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.list-table td:last-child {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}
.list-table th.sortable {
  cursor: pointer;
  user-select: none;
}
.list-table th.sortable:hover {
  color: inherit;
}
.list-table .sort-icon {
  font-size: 0.65rem;
  margin-left: 4px;
  opacity: 0.5;
  transition: opacity 0.15s ease;
}
.list-table th.sortable:hover .sort-icon {
  opacity: 1;
}
.list-table tr.filtered-out {
  display: none;
}
.list-table tbody tr {
  cursor: pointer;
}
.list-table td a {
  color: #fff;
}
.list-table tbody tr:hover {
  background: rgba(var(--accent-rgb), 0.15);
}
.list-table .component-btn {
  padding: 0.15rem 0.35rem;
  font-size: 0.85rem;
  line-height: 1;
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.8);
  background: transparent;
  cursor: default;
}
.list-table .component-btn:hover {
  background: rgba(255, 255, 255, 0.1);
}
.no-results-message {
  text-align: center;
  color: rgba(255, 255, 255, 0.5);
  padding: 2rem 0;
  font-size: 0.95rem;
}
.component-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
}

/* --- Project list table (column widths) --- */
.project-search {
  max-width: 300px;
}
.project-table-wrapper {
}
.project-table th:nth-child(1) {
  width: auto;
}
.project-table th:nth-child(2) {
  width: 10rem;
}
.project-table th:nth-child(3) {
  width: 120px;
}
.project-table th:nth-child(4) {
  width: 120px;
}
.project-table th:nth-child(5) {
  width: 110px;
}
.project-table th:nth-child(6) {
  width: 120px;
}
.project-table-wrapper .tooltip .tooltip-inner {
  text-align: center;
  min-width: 0;
}

/* --- Component list table (column widths) --- */
.component-search {
  max-width: 300px;
}
/* --- Category filters (#subclass-filter on the component lists + the
   #component-picker-filter in the add-component modal) --- Evenly-gapped pills
   that wrap cleanly and left-align on every row (a joined btn-group can't wrap
   without the rows drifting out of alignment). Unselected buttons are a quiet
   ghost so the selected one (solid accent) clearly stands out. */
#subclass-filter,
#component-picker-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-start;
}
#subclass-filter {
  margin-top: 20px;
}
#subclass-filter .btn,
#component-picker-filter .btn {
  flex: 0 0 auto;
  margin: 0 !important; /* drop btn-group negative margins so every row aligns left */
  white-space: nowrap;
  min-width: max-content; /* grow to fit the full label ("Thermal storage") */
  overflow: visible;
  padding: 5px 12px !important;
  font-size: var(--fs-text) !important;
  font-weight: 400 !important;
  line-height: 1.3 !important;
  border-radius: 7px !important;
  box-shadow: none !important;
}
/* Unselected: quiet ghost so the selected filter stands out. */
#subclass-filter .btn.btn-outline-primary,
#component-picker-filter .btn.btn-outline-primary {
  background: rgba(255, 255, 255, 0.04) !important;
  background-image: none !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  color: var(--fc-muted) !important;
}
#subclass-filter .btn.btn-outline-primary:hover,
#component-picker-filter .btn.btn-outline-primary:hover {
  border-color: var(--accent) !important;
  color: var(--accent) !important;
  background: rgba(var(--accent-rgb), 0.1) !important;
}
/* Selected: solid accent — one "selected" colour across tabs, toggles, filters. */
#subclass-filter .btn.btn-primary,
#subclass-filter .btn.active,
#component-picker-filter .btn.btn-primary,
#component-picker-filter .btn.active {
  background: var(--accent) !important;
  background-image: none !important;
  border: 1px solid var(--accent) !important;
  color: #fff !important;
}
.dropdown-menu .dropdown-item .bi {
  vertical-align: middle;
  position: relative;
  top: -2px;
}
/* Tweak this value to control when filter labels hide (icon-only mode) */
@media (max-width: 1199px) {
  #subclass-filter .filter-label {
    display: none;
  }
  #subclass-filter .btn {
    width: 60px;
  }
}
.component-table-wrapper {
}
.component-table th:nth-child(1) {
  width: auto;
}
.component-table th:nth-child(2) {
  width: 140px;
}
.component-table th:nth-child(3) {
  width: 110px;
}
.component-table th:nth-child(4) {
  width: 130px;
}
.component-table th:nth-child(5) {
  width: 130px;
}
.component-table th:nth-child(6) {
  width: 120px;
}
.component-table-wrapper .tooltip .tooltip-inner {
  text-align: center;
  min-width: 0;
}
/* Shared editable-component table (create-project sizing wizard). The project
   detail Summary page uses the .comp-grid card layout instead — see below. */
.component-table-editable td > i.bi {
  font-size: 2rem;
}
.table.component-table-editable td:first-of-type {
  width: 1%;
  white-space: nowrap;
  padding: 0 4px;
}
.table.component-table-editable td:nth-of-type(2) {
  width: 20%;
}

#selected-components-table {
  table-layout: fixed;
}
#selected-components-table th:first-of-type {
  width: 2rem;
  white-space: nowrap;
  padding: 0 4px;
}
#selected-components-table th:last-of-type,
#selected-components-table td:last-of-type {
  width: 3.5rem;
  text-align: center;
}

.modal-backdrop.show {
  backdrop-filter: blur(6px);
  background: rgba(0, 0, 0, 0.5);
  opacity: 1;
}

.asset-remove-td button {
  width: 0.75rem;
}

.add-component-dropdown {
  margin: -1.75rem 0 1.25rem;
  text-align: center;
}

.component-table-add-mode .already-added-badge {
  font-size: 0.75rem;
}

.add-component-modal .modal-content {
  background-color: #ffffff;
  color: #222a42;
}

.add-component-modal .modal-title,
.add-component-modal label,
.add-component-modal .close {
  color: #222a42;
}

.add-component-modal .form-control {
  background-color: #ffffff;
  border: 1px solid #ced4da;
  color: #222a42;
}

.add-component-modal .form-control:focus {
  background-color: #ffffff;
  border-color: var(--accent);
  box-shadow: 0 0 0 0.2rem rgba(var(--accent-rgb), 0.25);
  color: #222a42;
}

.add-component-modal .form-control::placeholder {
  color: #6c757d;
}

/* --- Unit Capacity & Capacity Figures (detail page) --- */

.capacity-figure {
  display: block;
  color: var(--fc-muted);
  font-size: 0.72rem;
  white-space: nowrap;
}

.min-max-uc-row td {
  padding-top: 0.25rem;
  padding-bottom: 0.5rem;
  border-top: none;
}

.unit-capacity-input {
  max-width: 7rem;
}

.unit-capacity-unit {
  color: var(--fc-muted);
  font-size: 0.85rem;
  white-space: nowrap;
}

/* --- Components card grid (project detail Summary) ---
   Replaces the editable table on the detail page with KPI-aligned cards. The
   form field ids/names/datasets are unchanged, so the existing dispatch +
   validation JS drives it as-is. Scoped to #components so the create-project
   sizing wizard (shared .component-table-editable) is untouched. */
#components .comp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
  margin-bottom: 18px;
}
.comp-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: #2b2d42;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 16px 16px 14px;
  transition: transform 0.15s, border-color 0.15s;
}
.comp-card:hover {
  transform: translateY(-2px);
  border-color: rgba(var(--accent-rgb), 0.4);
}
.comp-card .cc-del {
  position: absolute;
  top: 11px;
  right: 11px;
  width: auto;
  padding: 0;
  background: none;
  border: none;
  line-height: 1;
  color: var(--fc-faint);
  font-size: 0.98rem;
}
.comp-card .cc-del:hover {
  color: #ff8a8a;
}
.comp-card .cc-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-right: 18px;
}
.cc-icon {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border-radius: 11px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  color: var(--accent);
  background: radial-gradient(
    circle at 30% 25%,
    rgba(var(--accent-rgb), 0.22),
    rgba(var(--accent-rgb), 0.06)
  );
  border: 1px solid rgba(var(--accent-rgb), 0.25);
}
.cc-titles {
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}
.cc-cat {
  display: block;
  font-size: 0.95rem;
  color: var(--fc-strong);
  font-weight: 400;
  line-height: 1.2;
}
a.cc-cat {
  cursor: pointer;
  text-decoration: none;
}
a.cc-cat:hover {
  color: var(--accent);
}
.cc-name {
  display: block;
  font-size: 0.66rem;
  color: var(--fc-muted);
  font-weight: 300;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
a.cc-name:hover {
  color: var(--accent);
}
.cc-fields {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
}
.cc-field,
.cc-uc {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.cc-field > label,
.cc-uc > label {
  margin: 0;
  font-size: 0.6rem;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--fc-muted);
}
.comp-card .form-control {
  height: auto;
  padding: 5px 8px;
  font-size: var(--fs-input); /* one input size across the app */
  border-radius: 7px;
}
.cc-uc-input {
  display: flex;
  align-items: center;
  gap: 6px;
}
.cc-uc-input .unit-capacity-input {
  max-width: none;
  flex: 1;
}
.cc-opt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-top: auto;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-top: 10px;
}
.cc-opt-lbl {
  font-size: 0.6rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--fc-muted);
}
.cc-opt-val {
  font-size: 1rem;
  font-weight: 600;
  color: var(--accent);
  text-align: right;
}
.cc-opt-val .capacity-figure {
  display: inline;
  margin-left: 4px;
  color: var(--fc-muted);
  font-weight: 400;
  font-size: 0.62rem;
}
/* Dashed add-component tile — sits in the grid and reflows with the cards */
.comp-grid .add-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 150px;
  font-family: inherit;
  border: 1.5px dashed rgba(255, 255, 255, 0.22);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.015);
  color: var(--fc-muted);
  cursor: pointer;
  transition: 0.15s;
}
.comp-grid .add-card:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.05);
}
.comp-grid .add-card:disabled {
  cursor: default;
  opacity: 0.5;
}
.add-card-plus {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
}
.add-card-text {
  font-size: 0.78rem;
}

/* --- Add-component modal (create project B wizard) --- */
/* qsystem.css has two coupled rules that cancel for small modals but
   push large ones off-screen:
     .modal.show .modal-dialog  { transform: translate(0, 30%) }
     .modal-content             { margin-top: -50% }  ← % of *width*, not height
   Both are neutralised here. The modal-body gets its own scroll so the
   dialog never needs to grow taller than the viewport. */
#addComponentModal .modal-dialog {
  transform: none !important;
  transition: none !important;
  margin-top: 1.75rem;
}
#addComponentModal .modal-content {
  margin-top: 0 !important;
}
#addComponentModal .modal-body {
  overflow-y: auto;
  max-height: calc(100vh - 120px);
}

/* --- Inline-editable component cards (create project B wizard) --- */

/* Create step 1: components stacked one per full-width row. Each card mirrors
   the results-Summary card header (clickable icon + category + name opening the
   editor) with Remove/Save fixed top-right, and lays its General fields across
   three column-major columns (fewer-field components leave the last columns
   empty), so every card looks consistent and the buttons always line up. */
#component-cards-row {
  display: flex !important;
  flex-direction: column;
  gap: 14px;
}

.component-card {
  width: 100%;
  min-height: 96px;
  height: auto;
  padding: 0 20px 16px;
  background: rgba(255, 255, 255, 0.025) !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  border-radius: 12px !important;
  display: flex;
  flex-direction: column;
}
.component-card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 0 12px;
  margin-bottom: 14px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.component-card-acts {
  margin-left: auto;
  display: flex;
  gap: 8px;
}
.component-card-fields {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0 44px;
}
.ccf-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Add tile: a full-width row that matches a component card. */
.component-card-add-pseudo {
  width: 100%;
  min-height: 0;
  height: auto;
  flex-direction: row !important;
  gap: 14px;
  padding: 24px;
  border: 2px dashed rgba(var(--accent-rgb), 0.4);
  border-radius: 10px;
  background: transparent !important;
}
.component-card-add-pseudo .add-pseudo-text {
  display: block;
  margin: 0;
  color: var(--fc-muted);
  font-size: 0.9rem;
}

/* Quick project-settings strip */
.create-settings-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 28px;
  padding: 14px 18px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
}
.create-settings-strip .css-label {
  font-weight: 600;
  color: var(--fc-heading);
  display: flex;
  align-items: center;
  gap: 8px;
}
.create-settings-strip .css-field {
  display: flex;
  align-items: center;
  gap: 10px;
}
.create-settings-strip .css-field label {
  margin: 0;
  color: var(--fc-muted);
  font-size: 0.85rem;
  white-space: nowrap;
}
.create-settings-strip .css-field .form-control {
  width: 90px;
}
.create-settings-strip .css-more {
  margin-left: auto;
  color: var(--accent);
}
.create-settings-strip .has-danger .form-control {
  border-color: #ff8d72;
}

/* Project Settings box (Setup step 1) — same look as a component card: a pencil
   icon-box + the project-name field in the head, a divider, then the quick
   lifetime/WACC fields + "More in Advanced" below. Mirrors .component-card /
   .component-card-head without reusing those classes (keeps it clear of the
   component-card JS). The body reuses .create-settings-strip field styling. */
.ps-card {
  width: 100%;
  padding: 0 20px 16px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  margin-top: 12px;
}
.ps-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 0 12px;
  margin-bottom: 14px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.ps-head .cc-icon {
  font-size: 1.2rem;
}
.ps-name-field {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
}
.ps-name-field > label {
  margin: 0;
  color: var(--fc-muted);
  font-size: 0.85rem;
  white-space: nowrap;
}
.ps-name-field .form-control {
  flex: 1;
  background-color: transparent;
  color: var(--fc-kpi);
  font-size: var(--fs-input);
  font-weight: 400;
  height: auto;
  line-height: 1.4;
  padding: 0.2rem 8px;
  /* The bundle's `.card form label+.form-control` adds a 20px bottom margin
     (the name input directly follows its label), which shoved the field ~10px
     above the label in the centered head row. Drop it (bundle rule isn't
     !important, so this wins). */
  margin-bottom: 0 !important;
}
.ps-name-field.has-danger .form-control {
  border-color: #ff8d72;
}
/* The project name is the field the user must set to create a project — guide
   them to it: accent outline + glow + a "name your project" note until they
   give it a real name. Two triggers: the field is empty (:invalid — it's a
   required input), or it still holds the pre-filled default (JS adds
   .ps-name-needs-rename on create flows until the value changes). Suppressed
   once a real submit error (.has-danger) takes over so the red error wins. */
.ps-name-field:not(.has-danger) .form-control:invalid,
.ps-name-field.ps-name-needs-rename:not(.has-danger) .form-control {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.2);
}
.ps-name-field:not(.has-danger):has(.form-control:invalid) > label,
.ps-name-field.ps-name-needs-rename:not(.has-danger) > label {
  color: var(--accent);
}
.ps-name-field:not(.has-danger):has(.form-control:invalid) > label::after,
.ps-name-field.ps-name-needs-rename:not(.has-danger) > label::after {
  content: " — name your project";
  font-weight: 400;
}
/* Inside the box the quick-settings row is not a box-in-box. */
.ps-settings-strip.create-settings-strip {
  background: none;
  border: none;
  border-radius: 0;
  padding: 0;
  margin-top: 14px;
}
.ps-name-error {
  margin-top: 8px;
}

/* Create-project page title — sits at the very top, styled like the results
   page project title (reuses .project-detail-topbar .card-title). The template
   name is accented. */
.create-page-topbar .card-title em {
  font-style: normal;
  font-weight: 400;
  color: var(--accent);
}
/* Tab selectors + actions on one row inside the card (Undo / Save & continue /
   Cancel sit on the right, visible on both tabs). The top margin gives the
   selectors breathing room from the card's top edge. */
.create-tabs-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 16px;
}
.create-tabs-row #create-tabs {
  margin-bottom: 0;
}
.create-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  padding-bottom: 6px;
}
.create-actions .btn {
  white-space: nowrap;
}

/* --- Import pages (project + component): a clean centred dropzone card.
   Keeps the Bootstrap fileinput plugin hooks (.fileinput / data-provides /
   :file / :submit) so the existing upload-enable JS still works. --- */
/* The global .card-body{padding-top:0} (dense detail layout) left the import
   dropzone flush to the card top; restore top breathing room on this page. */
.card-body > .import-form {
  margin-top: 24px;
}
.import-dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding: 48px 24px;
  border: 2px dashed rgba(var(--accent-rgb), 0.4);
  border-radius: 12px;
  background: rgba(var(--accent-rgb), 0.04);
}
.import-dropzone__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  font-size: 1.9rem;
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.12);
  border: 1px solid rgba(var(--accent-rgb), 0.25);
}
.import-dropzone__title {
  font-size: 1rem;
  font-weight: 500;
  color: var(--fc-strong);
}
.import-dropzone__hint {
  font-size: 0.8rem;
  color: var(--fc-muted);
  max-width: 460px;
}
.import-dropzone__hint code {
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.1);
  padding: 1px 6px;
  border-radius: 4px;
}
.import-dropzone__name {
  font-size: 0.85rem;
  color: var(--fc-kpi);
}
.import-dropzone__name .bi {
  color: var(--accent);
}
.import-dropzone__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.import-dropzone__actions .btn-file {
  white-space: nowrap;
}
.import-dropzone__remove {
  color: #ff8a8a !important;
}
.import-foot {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
}
.import-foot .import-cancel {
  color: var(--fc-muted) !important;
}

/* "Save & continue" is the primary action — wider than the others (≈2×) and
   kept on one line so it doesn't grow taller than the Cancel button. */
.create-top-row .create-save-btn {
  min-width: 190px;
  white-space: nowrap;
}

/* Step-1 field label + balanced schematic */
.create-field-label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--fc-muted);
}
.system-schematic-img {
  display: block;
  max-width: 100%;
  max-height: 260px;
  margin: 0 auto;
}

.component-card-add-pseudo button {
  margin-left: 5px;
}

.component-card .card-header {
  padding-top: 0.75rem !important;
  padding-left: 10px;
  padding-right: 0.75rem;
  padding-bottom: 0;
}

.component-card .card-header h4 {
  word-break: break-word;
}

.component-card .card-header .settings-section-hr {
  margin-top: 8px;
  margin-bottom: 0;
}

.component-card .card-header {
  flex-shrink: 0;
}

.component-card .card-body {
  flex: 1;
  min-height: 0;
  margin-top: 15px !important;
  margin-bottom: 0 !important;
  padding-bottom: 0 !important;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.component-card .card-body form {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.component-card-fields {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* overflow-y:auto forces overflow-x to compute as auto; a few px of gutter
     then draws a stray horizontal scrollbar. Suppress it explicitly. */
  overflow-x: hidden;
}

.component-card .card-footer.component-card-footer {
  flex-shrink: 0;
  padding: 0 0.75rem 0.75rem;
  background: transparent;
  border-top: none;
}

.component-card .card-footer .settings-section-hr {
  margin-top: 0;
  margin-bottom: 8px;
}

/* Trash-icon remove, matching the Summary card's .cc-del (was a red button). */
.component-card .component-remove-btn {
  margin: 0 !important;
  padding: 0;
  background: none;
  border: none;
  line-height: 1;
  color: var(--fc-faint);
  font-size: 1.05rem;
  cursor: pointer;
  align-self: center;
}
.component-card .component-remove-btn:hover {
  color: #ff8a8a;
}

/* Amber left border when a card has unsaved changes */
.component-card--dirty {
  border-left: 3px solid #f5a623;
}

/* Badge shown on a detail-page tab that contains validation errors */
.tab-error-badge {
  font-size: 0.7rem;
  vertical-align: middle;
  margin-left: 4px;
}

.row.settings-row.general-tab-row {
  margin-left: 0px;
}

.component-formset-section.aging-formset-chart-section {
  margin-top: 0px;
}

.row.settings-row.general-tab-row.mt-3 > .col-lg-12 {
  padding-left: 0px;
}

/* PV Orientation section: narrow label, wide unit to fit values like
   "south = 0, east = -90, west = 90, north = 180" */
.pv-orientation-fields .settings-field-row > .col-7 {
  flex: 0 0 30%;
  max-width: 30%;
}
.pv-orientation-fields .settings-field-row > .col-3 {
  flex: 0 0 20%;
  max-width: 20%;
}
.pv-orientation-fields .settings-field-row > .col-2 {
  flex: 0 0 50%;
  max-width: 50%;
}

/* ===================================================================
   Inputs tab (project detail + create-project inputs step) — redesign.
   The form ids/names, slider ids and plot includes are unchanged; this is
   layout + styling only. Scoped to .inputs-tab.
   =================================================================== */
.inputs-tab {
  padding-top: 4px;
}
.inputs-alert {
  font-size: var(--fs-text);
  margin-bottom: 14px;
}
.inputs-alert i {
  margin-right: 6px;
}
.inputs-section-h {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 0.66rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--fc-muted);
  font-weight: 500;
  margin: 22px 0 12px;
}
.inputs-section-h:first-child {
  margin-top: 4px;
}
.inputs-hr {
  flex: 1;
  height: 1px;
  background: var(--line, rgba(255, 255, 255, 0.1));
}

/* Small info button revealing the help text (data-toggle=tooltip) */
.setup-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1px solid var(--fc-faint);
  color: var(--fc-faint);
  font-size: 0.58rem;
  font-style: normal;
  cursor: help;
  flex: 0 0 auto;
  font-family: serif;
}
.setup-info:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* --- Data setup cards --- */
.inputs-setup-grid {
  display: grid;
  grid-template-columns: 1fr 1.3fr;
  gap: 14px;
}
.setup-card {
  position: relative;
  background: #2b2d42;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 15px 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.setup-card-req {
  border-color: rgba(255, 141, 114, 0.45);
}
.setup-card > .setup-info {
  position: absolute;
  top: 13px;
  right: 13px;
}
.setup-card-h {
  display: flex;
  align-items: center;
  gap: 11px;
}
.setup-ic {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.1);
  border: 1px solid rgba(var(--accent-rgb), 0.22);
  flex: 0 0 auto;
}
.setup-titles {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  min-width: 0;
}
.setup-t {
  font-size: 0.86rem;
  color: var(--fc-strong);
}
.setup-sub {
  font-size: 0.66rem;
  color: var(--fc-muted);
}

/* --- Buttons ---
   The data-setup row (Download / Upload new) and the footer (Reset / Save
   inputs) use the standard theme .btn classes inside flex rows. Without these
   guards the theme .btn shrinks and wraps the label onto two lines — which
   inflated them to ~49px. Stop the shrink/wrap so they keep the native theme
   button height, matching the action buttons on the rest of the wizard. */
.setup-btn-row .btn,
.inputs-foot .btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* Disabled buttons should read INACTIVE, not "go": drop the bright theme
   gradient to a flat muted fill so a disabled Save / Calculate / Upload no
   longer looks clickable. Solution-B only — original UI keeps the theme look. */
body.solution-b .btn:disabled,
body.solution-b .btn.disabled,
body.solution-b .btn[disabled] {
  background-image: none !important;
  background-color: rgba(255, 255, 255, 0.07) !important;
  color: var(--fc-faint) !important;
  border-color: rgba(255, 255, 255, 0.12) !important;
  box-shadow: none !important;
  opacity: 1 !important;
}

/* "Upload new" keeps a flat accent fill (no gradient) at standard button size. */
.inputs-upload-flat {
  background-image: none !important;
  background-color: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #fff !important;
}

/* The theme's btn-secondary is near-white, which read as a bright block on the
   dark UI (the wizard Back button, the Undo/Reset buttons). Give it a neutral
   dark-theme fill instead. The light review modals are overridden back below. */
body.solution-b .btn-secondary {
  background-image: none !important;
  background-color: rgba(255, 255, 255, 0.08) !important;
  color: var(--fc-heading) !important;
  border: 1px solid rgba(255, 255, 255, 0.15) !important;
}
body.solution-b .btn-secondary:hover,
body.solution-b .btn-secondary:focus {
  background-color: rgba(255, 255, 255, 0.14) !important;
  color: #fff !important;
}
body.solution-b #unsavedChangesModal .btn-secondary,
body.solution-b #confirmSettingsModal .btn-secondary {
  background-color: #e9ecef !important;
  color: #222a42 !important;
  border-color: #ced4da !important;
}
body.solution-b #unsavedChangesModal .btn-secondary:hover,
body.solution-b #confirmSettingsModal .btn-secondary:hover {
  background-color: #dde1e6 !important;
  color: #222a42 !important;
}

.setup-btn-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* --- Renewable toggles --- */
.renewable-toggles {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.toggle-row {
  display: flex;
  align-items: center;
  gap: 11px;
}
.toggle-ic {
  /* width matches .setup-ic (38px) so the sun/wind glyphs line up vertically
     under the Renewable-data card icon, and the toggle labels align with the
     card title (both rows use an 11px gap). No chip box — just the darker
     icon colour, same fixed glyph size for both icons. */
  width: 38px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  color: var(--fc-muted);
  background: transparent;
  flex: 0 0 auto;
}
.toggle-ic i {
  font-size: inherit;
  line-height: 1;
}
.toggle-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.toggle-label {
  margin: 0;
  font-size: 0.8rem;
  color: var(--fc-kpi);
  font-weight: 300;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.64rem;
  padding: 2px 8px;
  border-radius: 20px;
  width: fit-content;
}
.status-chip.status-req {
  color: #ff8d72;
  background: rgba(255, 141, 114, 0.12);
}
.status-chip.status-ok {
  color: #00bf9a;
  background: rgba(0, 191, 154, 0.1);
}
.status-chip.status-muted {
  color: var(--fc-muted);
  background: rgba(255, 255, 255, 0.05);
}

/* Checkboxes rendered as toggle switches (download_solar/wind + scale demand) */
.inputs-tab #id_download_solar,
.inputs-tab #id_download_wind,
.inputs-tab #id_scaled {
  -webkit-appearance: none;
  appearance: none;
  position: relative;
  width: 42px;
  height: 23px;
  min-height: 0;
  padding: 0;
  margin: 0;
  border: none;
  border-radius: 23px;
  background: rgba(255, 255, 255, 0.15);
  cursor: pointer;
  flex: 0 0 auto;
  transition: background 0.15s;
}
.inputs-tab #id_download_solar::before,
.inputs-tab #id_download_wind::before,
.inputs-tab #id_scaled::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: #fff;
  transition: left 0.15s;
}
.inputs-tab #id_download_solar:checked,
.inputs-tab #id_download_wind:checked,
.inputs-tab #id_scaled:checked {
  background: var(--accent);
}
.inputs-tab #id_download_solar:checked::before,
.inputs-tab #id_download_wind:checked::before,
.inputs-tab #id_scaled:checked::before {
  left: 22px;
}
.inputs-tab #id_download_solar:disabled,
.inputs-tab #id_download_wind:disabled,
.inputs-tab #id_scaled:disabled {
  opacity: 0.5;
  cursor: default;
}

/* --- Demand card --- */
.demand-source-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.demand-source-label {
  margin: 0;
  font-size: 0.66rem;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--fc-muted);
}
.demand-card .demand-source-row > select.form-control {
  width: auto;
  min-width: 240px;
  max-width: 340px;
}
.scale-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 0.8rem;
  color: var(--fc-kpi);
  font-weight: 300;
  cursor: pointer;
}
.demand-scaler {
  margin-top: 16px;
  padding-top: 15px;
  border-top: 1px dashed rgba(255, 255, 255, 0.12);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.scaler-fields {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 220px));
  gap: 14px;
}
.inputs-fld {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.inputs-fld > label {
  margin: 0;
  font-size: 0.6rem;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--fc-muted);
}
.inputs-tab .inputs-fld .form-control {
  height: auto;
  padding: 6px 9px;
  font-size: var(--fs-input); /* one input size across the app */
  border-radius: 7px;
  color: var(--fc-kpi);
  font-weight: 400;
}
.scaler-sliders {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  max-width: 680px;
}
.load-gen-slider-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.slider-cap {
  font-size: 0.7rem;
  color: var(--fc-muted);
}
.slider-cap span {
  color: var(--fc-kpi);
}

/* --- Footer --- */
.inputs-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

/* --- Preview pills (match the section-selector pill look) --- */
.inputs-preview-pills {
  gap: 6px;
  border: none;
  margin-bottom: 12px;
}
.inputs-preview-pills > .nav-item > .nav-link {
  cursor: pointer;
  font-size: var(--fs-text);
  font-weight: 300;
  color: rgba(255, 255, 255, 0.55) !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  border-radius: 6px !important;
  background-color: transparent !important;
  padding: 4px 14px;
}
.inputs-preview-pills > .nav-item > .nav-link:hover {
  color: var(--fc-heading) !important;
}
.inputs-preview-pills > .nav-item > .nav-link.active {
  color: var(--fc-strong) !important;
  border-color: var(--accent) !important;
}

/* ===================================================================
   Summary components — energy-bus layout (project detail). The cards keep
   the .comp-card / .min-max-row markup and every form id, so the dispatch +
   validation JS is unchanged; this is layout + the card refinements only.
   Scoped to #components .component-bus so the create-wizard grid is untouched.
   =================================================================== */
/* Components section header: give the Save/Undo actions breathing room above
   the component bus, and nudge them up so they sit nearer the top-bar actions. */
#component-schematic-column > h4 {
  margin-bottom: 1.5rem;
}
#component-schematic-column > h4 > .float-right {
  margin-top: -0.5rem;
}

#components .component-bus {
  display: grid;
  grid-template-columns: 1fr 230px 1fr;
  align-items: start;
  width: 100%;
}
.component-bus .bus-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* Cards stretch to fill each side column, so their outer edges line up with the
   full-width "Add component" button (and the KPI tiles above). */
.component-bus .comp-card {
  width: 100%;
}
.component-bus .bus-mid {
  position: relative;
  align-self: stretch;
  z-index: 2; /* line + node + dots paint over the connectors, so each line
                 reads as starting from the bus rather than the card */
}
.bus-line {
  position: absolute;
  left: 50%;
  top: 8px;
  bottom: 8px;
  width: 2px;
  transform: translateX(-50%);
  border-radius: 2px;
  background: linear-gradient(
    180deg,
    rgba(var(--accent-rgb), 0.5),
    rgba(29, 140, 248, 0.5)
  );
  /* Hidden until positionEnergyBus places it at the first-row card centre, so it
     never flashes at its default full-height position on first load. */
  opacity: 0;
  transition: opacity 0.25s ease;
}
/* End caps — the line runs from the centre of the top card to the centre of the
   bottom card (positioned by positionEnergyBus); the outer cards connect here. */
.bus-line::before,
.bus-line::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  transform: translateX(-50%);
  box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.6);
}
.bus-line::before {
  top: -4px;
}
.bus-line::after {
  bottom: -4px;
}
.bus-node {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 110px;
  padding: 11px 8px;
  text-align: center;
  background: var(--panel-bg);
  border: 1px solid rgba(var(--accent-rgb), 0.5);
  border-radius: 10px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
  opacity: 0; /* revealed by positionEnergyBus once placed (see .bus-line) */
  transition: opacity 0.25s ease;
}
.bus-node i {
  font-size: 1.2rem;
  color: var(--accent);
}
.bus-node-n {
  font-size: 0.66rem;
  color: var(--fc-strong);
}
/* Undirected connector line from each card to the central bus */
.bus-col-left .comp-card::after,
.bus-col-right .comp-card::before {
  content: "";
  position: absolute;
  top: 50%;
  width: 115px;
  height: 2px;
  background: rgba(var(--accent-rgb), 0.55);
}
.bus-col-left .comp-card::after {
  left: 100%;
}
.bus-col-right .comp-card::before {
  right: 100%;
}
.cc-dot {
  position: absolute;
  top: 50%;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  transform: translateY(-50%);
  display: none;
  z-index: 1;
}
.bus-col-left .comp-card .cc-dot {
  right: -3px;
  display: block;
}
.bus-col-right .comp-card .cc-dot {
  left: -3px;
  display: block;
}
/* Full-width add-component tile beneath the components */
.add-card-wide {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 52px;
  margin-top: 16px;
  font-family: inherit;
  font-size: 0.78rem;
  border: 1.5px dashed rgba(255, 255, 255, 0.22);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.015);
  color: var(--fc-muted);
  cursor: pointer;
  transition: 0.15s;
}
.add-card-wide:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(var(--accent-rgb), 0.05);
}
.add-card-wide .add-card-plus {
  width: 28px;
  height: 28px;
  font-size: 1rem;
}

/* --- Card refinements (clickable icon, tight kW, optimal capacity/units) --- */
a.cc-icon {
  cursor: pointer;
  text-decoration: none;
  transition: 0.13s;
}
a.cc-icon:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.2);
}
/* kW figure tight up under each input */
.comp-card .cc-field {
  gap: 0;
}
.comp-card .cc-field > label {
  margin-bottom: 4px;
}
.comp-card .cc-field .capacity-figure {
  margin-top: 2px;
  font-size: 0.58rem;
  line-height: 1.15;
}
/* Optimal: big blue capacity (kWh/kW) with the small grey unit count below */
.comp-card .cc-opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: auto;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-top: 9px;
}
.cc-opt-figs {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.2;
}
.cc-opt-kw {
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--accent);
}
.cc-opt-units {
  font-size: 0.62rem;
  color: var(--fc-muted);
}
.cc-opt-count {
  color: var(--fc-muted);
}
.cc-opt-stale {
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--fc-faint);
  cursor: help;
}

/* Stack the bus into one column on narrow screens */
@media (max-width: 991px) {
  #components .component-bus {
    grid-template-columns: 1fr;
  }
  .component-bus .bus-mid {
    display: none;
  }
  .bus-col-left .comp-card::after,
  .bus-col-right .comp-card::before,
  .cc-dot {
    display: none;
  }
}

/* Space above the peak-demand plot + simulation-tables row (Summary) */
#summary-plot-row {
  margin-top: 30px;
}
.summary-tables-col h4 {
  margin-top: 0;
}
.summary-tables-col h4 + .table-responsive {
  margin-bottom: 18px;
}

/* Connector hover: hovering a component card lights its line up and sends an
   animated "energy flow" pulse toward the bus, plus a brighter end dot. */
.bus-col-left .comp-card:hover::after,
.bus-col-right .comp-card:hover::before {
  background: linear-gradient(
    90deg,
    rgba(var(--accent-rgb), 0.35),
    #5fd0f5,
    rgba(var(--accent-rgb), 0.35)
  );
  background-size: 200% 100%;
  height: 3px;
  box-shadow: 0 0 9px rgba(var(--accent-rgb), 0.65);
  animation: busFlow 1.1s linear infinite;
}
.bus-col-left .comp-card:hover .cc-dot,
.bus-col-right .comp-card:hover .cc-dot {
  width: 10px;
  height: 10px;
  box-shadow: 0 0 11px rgba(var(--accent-rgb), 0.95);
}
@keyframes busFlow {
  from {
    background-position: 200% 0;
  }
  to {
    background-position: 0 0;
  }
}

/* ===================================================================
   Create-new-project quick start: a responsive gallery of starting
   points (example templates + a "from scratch" card) styled like the
   rest of the Solution-B cards, replacing the two oversized plain cards.
   =================================================================== */
.quick-start-head {
  margin-bottom: 1.5rem;
}
.quick-start-sub {
  color: var(--fc-muted);
  margin: 0;
}
.quick-start-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}
.qs-card {
  display: flex;
  flex-direction: column;
  background: var(--panel-bg);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
  transition: transform 0.15s ease, border-color 0.15s ease,
    box-shadow 0.15s ease;
}
.qs-card:hover,
.qs-card:focus {
  transform: translateY(-3px);
  border-color: var(--accent);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
  color: inherit;
  text-decoration: none;
}
.qs-card-scratch {
  border-style: dashed;
  border-color: rgba(var(--accent-rgb), 0.5);
}
.qs-card-media {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 180px;
  padding: 18px;
  background: rgba(255, 255, 255, 0.02);
}
.qs-card-media img {
  max-width: 100%;
  max-height: 170px;
  object-fit: contain;
}
/* Auto-generated component-icon schematic on the quick-create cards. Two icon
   columns flank a central vertical bus line; each icon connects to the bus with
   a short horizontal lead. Mirrors the Summary energy-bus left/right split. */
.qs-schematic {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.qs-bus-line {
  position: absolute;
  left: 50%;
  top: 16px;
  bottom: 16px;
  width: 2px;
  transform: translateX(-50%);
  background: linear-gradient(
    to bottom,
    rgba(var(--accent-rgb), 0.05),
    rgba(var(--accent-rgb), 0.55) 18%,
    rgba(var(--accent-rgb), 0.55) 82%,
    rgba(var(--accent-rgb), 0.05)
  );
  border-radius: 2px;
}
.qs-schematic-col {
  display: flex;
  flex-direction: column;
  z-index: 1;
}
.qs-schematic-left {
  align-items: flex-end;
}
.qs-schematic-right {
  align-items: flex-start;
}
.qs-ic {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(var(--accent-rgb), 0.14);
  border: 1px solid rgba(var(--accent-rgb), 0.45);
  color: var(--accent);
  flex: 0 0 auto;
}
/* Horizontal lead from each icon to the central bus line. */
.qs-ic-left::after,
.qs-ic-right::before {
  content: "";
  position: absolute;
  top: 50%;
  height: 2px;
  background: rgba(var(--accent-rgb), 0.45);
}
.qs-ic-left::after {
  left: 100%;
}
.qs-ic-right::before {
  right: 100%;
}
/* Size tiers. The column gap (center spacing) equals 2× the lead width + the
   2px bus, so the leads always meet the central line. "lg" (<=4 components)
   fills the card with two big rows; "sm" (5-6, or truncated) packs three rows. */
.qs-schematic--lg {
  gap: 64px;
}
.qs-schematic--lg .qs-schematic-col {
  gap: 26px;
}
.qs-schematic--lg .qs-ic {
  width: 60px;
  height: 60px;
  font-size: 1.75rem;
}
.qs-schematic--lg .qs-ic-left::after,
.qs-schematic--lg .qs-ic-right::before {
  width: 31px;
}
.qs-schematic--sm {
  gap: 52px;
}
.qs-schematic--sm .qs-schematic-col {
  gap: 13px;
}
.qs-schematic--sm .qs-ic {
  width: 42px;
  height: 42px;
  font-size: 1.2rem;
}
.qs-schematic--sm .qs-ic-left::after,
.qs-schematic--sm .qs-ic-right::before {
  width: 25px;
}
/* Overflow marker: shown when a system has more than six components. */
.qs-ic-more {
  background: transparent;
  border-style: dashed;
}
/* From-scratch card: a single large dashed placeholder, no bus. */
.qs-schematic-scratch {
  gap: 0;
}
.qs-ic-scratch {
  width: 64px;
  height: 64px;
  font-size: 1.9rem;
  border-style: dashed;
}
.qs-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.qs-card-name {
  font-weight: 600;
  color: var(--fc-heading);
  line-height: 1.2;
}
.qs-card-tag {
  flex: 0 0 auto;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--fc-muted);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 10px;
  padding: 1px 8px;
}
.qs-card-tag-accent {
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.12);
}

/* ===================================================================
   Results plot loading spinner: result charts on the heavy tabs render in
   the background after the page is interactive; until each is ready its
   container shows a centred spinner instead of an empty/janky area.
   =================================================================== */
.plot-loading {
  position: relative;
  min-height: 260px;
}
.plot-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  margin: -28px 0 0 -20px;
  border: 3px solid rgba(var(--accent-rgb), 0.25);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: qPlotSpin 0.8s linear infinite;
}
.plot-loading::before {
  content: "Loading chart\2026";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, 26px);
  color: var(--fc-muted);
  font-size: 0.8rem;
  white-space: nowrap;
}
@keyframes qPlotSpin {
  to {
    transform: rotate(360deg);
  }
}

/* ===================================================================
   Results loading overlay: covers the project-detail card until every
   result chart has rendered, with a progress bar, so the page is revealed
   only once it's fully interactive (no half-loaded tab-switch jank).
   =================================================================== */
#project-detail-card {
  position: relative;
}
#results-loading-overlay {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: var(--panel-bg);
  border-radius: inherit;
}
#results-loading-overlay.rlo-hidden {
  display: none;
}
.rlo-box {
  margin-top: 17vh;
  width: 240px;
  max-width: 70%;
  text-align: center;
}
.rlo-spinner {
  width: 30px;
  height: 30px;
  margin: 0 auto 14px;
  border: 2px solid rgba(var(--accent-rgb), 0.2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: qPlotSpin 0.8s linear infinite;
}
.rlo-title {
  color: var(--fc-muted);
  font-weight: 400;
  font-size: 0.85rem;
  margin-bottom: 10px;
}
.rlo-bar {
  width: 100%;
  height: 4px;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  overflow: hidden;
}
.rlo-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.3s ease;
}
.rlo-count {
  margin-top: 8px;
  font-size: 0.8rem;
  color: var(--fc-muted);
}

/* ===================================================================
   Create-project wizard: a clean horizontal stepper (Set up -> Inputs ->
   Sizing) replacing the dated card-in-card + progress-bar indicator, so the
   creation flow matches the rest of the Solution-B UI.
   =================================================================== */
.wizard-steps {
  display: flex;
  margin: 4px 0 28px;
  padding: 0 8px;
}
.wizard-step {
  flex: 1;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
/* connector from the previous step's badge to this one */
.wizard-step::before {
  content: "";
  position: absolute;
  top: 16px;
  left: -50%;
  right: 50%;
  height: 2px;
  background: rgba(255, 255, 255, 0.12);
  z-index: 0;
}
.wizard-step:first-child::before {
  display: none;
}
.wizard-step.is-done::before,
.wizard-step.is-active::before {
  background: var(--accent);
}
.wizard-step-badge {
  position: relative;
  z-index: 1;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--panel-bg);
  border: 2px solid rgba(255, 255, 255, 0.18);
  color: var(--fc-muted);
  font-weight: 600;
  margin-bottom: 8px;
}
.wizard-step.is-active .wizard-step-badge {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.15);
}
.wizard-step.is-done .wizard-step-badge {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.wizard-step-label {
  font-size: 0.85rem;
  color: var(--fc-muted);
}
.wizard-step.is-active .wizard-step-label {
  color: var(--fc-heading);
  font-weight: 600;
}

/* ===================================================================
   Section KPI tiles under the Economics/Technical result plots —
   existing result rows promoted as tiles, plus safe series aggregates
   (revenue composition %, peak demand).
   =================================================================== */
.section-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin: 16px 0 6px;
}
.skpi {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 12px 15px;
}
.skpi-lbl {
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fc-muted);
  margin-bottom: 4px;
  line-height: 1.25;
}
.skpi-val {
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--fc-heading);
  line-height: 1.1;
}
.skpi-unit {
  font-size: 0.72rem;
  color: var(--fc-muted);
  font-weight: 400;
  margin-left: 4px;
}
.revenue-composition {
  margin: 16px 0 6px;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
}
.revenue-composition .rc-title {
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fc-muted);
  margin-bottom: 10px;
}
.revenue-composition .rc-bar {
  display: flex;
  height: 14px;
  border-radius: 7px;
  overflow: hidden;
  margin-bottom: 12px;
  background: rgba(255, 255, 255, 0.06);
}
.revenue-composition .rc-seg {
  height: 100%;
}
.revenue-composition .rc-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font-size: 0.8rem;
  color: var(--fc-muted);
}
.revenue-composition .rc-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.revenue-composition .rc-item b {
  color: var(--fc-heading);
  font-weight: 600;
}
.revenue-composition .rc-dot {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  display: inline-block;
}

/* ── Custom collapsible legend for the multi-axis timeseries charts ──
   Replaces Plotly's native legend (which can't collapse groups in 1.x and
   dwarfed the plot). A thin full-width bar above the plot: chips for the
   shown series + a "Series" button opening a floating, per-domain picker. */
body.solution-b .ts-legend-bar {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 2px 0 6px;
  font-size: 12px;
}
body.solution-b .ts-legend-pick-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: rgba(255, 255, 255, 0.85);
  border-radius: 6px;
  padding: 3px 11px;
  font-size: 12px;
  line-height: 1.4;
}
body.solution-b .ts-legend-pick-btn:hover {
  background: rgba(8, 172, 222, 0.18);
  border-color: rgba(8, 172, 222, 0.5);
}
body.solution-b .ts-legend-active {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  flex: 1 1 auto;
  min-width: 0;
}
body.solution-b .ts-active-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 11px;
  padding: 1px 8px;
  color: rgba(255, 255, 255, 0.85);
  font-size: 11px;
  max-width: 260px;
}
body.solution-b .ts-active-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.solution-b .ts-active-x {
  color: rgba(255, 255, 255, 0.45);
  font-size: 13px;
  line-height: 1;
}
body.solution-b .ts-active-chip:hover {
  border-color: rgba(253, 93, 147, 0.55);
}
body.solution-b .ts-active-chip:hover .ts-active-x {
  color: #fd5d93;
}
body.solution-b .ts-legend-empty {
  color: rgba(255, 255, 255, 0.45);
  font-size: 11px;
}
body.solution-b .ts-lg-sw {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex: 0 0 auto;
  display: inline-block;
}
/* floating per-domain picker */
body.solution-b .ts-legend-picker {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 30;
  margin-top: 4px;
  width: 360px;
  max-width: 90vw;
  max-height: 380px;
  overflow-y: auto;
  background: #1e2030;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 8px;
  padding: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
body.solution-b .ts-legend-bar.picker-open .ts-legend-picker {
  display: block;
}
body.solution-b .ts-lg-group-head {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.9);
  font-size: 12px;
  font-weight: 500;
  padding: 5px 4px;
  text-align: left;
}
body.solution-b .ts-lg-group-head:hover {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 5px;
}
body.solution-b .ts-lg-chev {
  font-size: 10px;
  transition: transform 0.15s ease;
}
body.solution-b .ts-lg-group.open .ts-lg-chev {
  transform: rotate(90deg);
}
body.solution-b .ts-lg-count {
  margin-left: auto;
  color: rgba(255, 255, 255, 0.45);
  font-size: 11px;
  font-weight: 400;
}
body.solution-b .ts-lg-items {
  display: none;
  padding: 2px 0 6px 18px;
}
body.solution-b .ts-lg-group.open .ts-lg-items {
  display: block;
}
body.solution-b .ts-lg-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 7px;
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.55);
  font-size: 11px;
  padding: 3px 6px;
  text-align: left;
  border-radius: 4px;
}
body.solution-b .ts-lg-item:hover {
  background: rgba(255, 255, 255, 0.05);
}
body.solution-b .ts-lg-item.on {
  color: rgba(255, 255, 255, 0.95);
}
body.solution-b .ts-lg-item .ts-lg-sw {
  opacity: 0.25;
}
body.solution-b .ts-lg-item.on .ts-lg-sw {
  opacity: 1;
}

/* Dispatch heat map source selector (Technical → Dispatch) */
body.solution-b .dispatch-heatmap-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}
body.solution-b .dispatch-heatmap-controls label {
  margin: 0;
  color: rgba(255, 255, 255, 0.6);
  font-size: 12px;
  white-space: nowrap;
}
body.solution-b #dispatch-heatmap-source {
  width: auto;
  min-width: 200px;
  max-width: 320px;
  height: auto;
  padding: 3px 26px 3px 10px;
  font-size: 12px;
  background-color: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 6px;
}
body.solution-b #dispatch-heatmap-source:focus {
  border-color: rgba(8, 172, 222, 0.6);
}
