/* ========= 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 --- */
/* Whole-pixel line heights through the settings tab.

   The theme's ratios give fractional boxes: 14px x 1.45 = 20.297 for a
   heading, 13px x 1.4286 = 18.571 for a field row. Those fractions add up
   down a column, so each heading started on a different fraction of a pixel
   (.516, .938, .797, .094 measured) and the browser rasterised each one
   slightly differently -- one heading reading a shade heavier, the next a
   shade lighter, at identical font, size and weight. Rounding both boxes to
   whole pixels puts every heading on the same fraction, so they all render
   alike. */
.settings-section h4,
#location-row h4 {
  line-height: 20px;
}
.settings-field-row,
.settings-field-row label,
.settings-field-row .form-group {
  line-height: 18px;
}
.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;
}

/* The options inside a native dropdown are painted by the browser, not by the
   page, and they do not inherit the select's colours. With the control left
   transparent above, every unselected option fell back to the platform's own
   pair -- dark on dark here, so the open list read as empty until an entry was
   highlighted. Both ends are stated. It covers every select under Solution B,
   since they all share that transparent control. */
body.solution-b select option,
body.solution-b select optgroup {
  background-color: var(--panel-bg);
  color: var(--fc-kpi);
}
.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);
  /* Zero, and it has to be: this column is a flex container, and flex items do
     not collapse margins.  Every other section is a block, where the heading's
     bottom margin and this rule's top margin collapse into one gap; here they
     would add, putting the rule 6px below the one beside it in the Location
     column and taking the whole Description column down with it. */
  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 {
  /* The section-heading icons inherit their heading's size; at 1.1rem this one
     sat noticeably larger than all of them. */
  font-size: 0.95rem;
}

/* --- 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 and Description keep their own row -- they are a map and a free-text
   box, not field lists -- but the row has to sit on the same grid as the
   sections above it, or the two headings, their icons and their rules all land
   at different x than every other section.
   Two equal columns with the same 24px gutter as ``.settings-columns``, and the
   Bootstrap gutters removed so the left edge matches the column block rather
   than being inset by half a gutter.
   No margin-top: every section already ends with 28px of padding, and adding a
   margin here stacked a second gap on top of it. */
#location-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 24px;
  margin-top: 0;
  margin-left: 0;
  margin-right: 0;
  align-items: start;
}
#location-row > .settings-map-col,
#location-row > .settings-description-col {
  flex: none;
  width: auto;
  max-width: none;
  padding-left: 0;
  padding-right: 0;
}
.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 {
  /* Width comes from the grid on #location-row; this remains for any other
     context that still lays the column out with flex. */
  flex: 0 0 49%;
  min-width: 0;
}
#project-location-map {
  width: 100%;
  /* Landscape rather than square: the coordinate fields now sit under the map
     in the same section, and a square map pushed them off the screen. */
  aspect-ratio: 4 / 3;
  height: auto !important;
  min-height: 300px;
  /* On a wide screen 4:3 would make the map taller than the viewport. */
  max-height: 460px;
}

/* --- Per-period charts (revenues per day/week/year) --- */
/* The period buttons sit where the zoom windows sit on the hourly charts, so
   the two rows line up when they are read one after the other. */
.period-plot-div {
  margin-bottom: 1.5rem;
}
.period-plot-div .ts-timerange .btn {
  min-width: 58px;
}

/* --- Location picker: address search over the map --- */
.location-picker {
  position: relative;
  margin-bottom: 14px;
}
/* Clear of Leaflet's zoom control (top left) and above the map's own panes. */
.address-search {
  position: absolute;
  top: 10px;
  left: 52px;
  right: 10px;
  z-index: 1000;
  display: flex;
  gap: 6px;
}
.address-search input.form-control {
  flex: 1 1 auto;
  height: 32px;
  min-height: 32px;
  font-size: var(--fs-input);
  color: var(--fc-strong);
  background-color: rgba(39, 41, 61, 0.94);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 4px;
  padding: 0 10px;
}
.address-search input.form-control:focus {
  background-color: rgba(39, 41, 61, 0.98);
  border-color: var(--accent);
  color: var(--fc-strong);
}
.address-search .btn {
  flex: 0 0 auto;
  width: 38px;
  min-width: 0;
  height: 32px;
  margin: 0;
  padding: 0;
  font-size: var(--fs-input);
  line-height: 1;
}
.address-search .btn i {
  margin: 0;
}
/* The candidate list and the message hang below the search field, over the map. */
.address-search-results,
.address-search-message {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 44px;
  background-color: rgba(39, 41, 61, 0.97);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 4px;
  font-size: var(--fs-input);
  color: var(--fc-muted);
}
.address-search-message {
  padding: 6px 10px;
}
.address-search-results {
  max-height: 190px;
  overflow-y: auto;
}
.address-search-result {
  display: block;
  width: 100%;
  text-align: left;
  padding: 6px 10px;
  border: 0;
  background: transparent;
  color: var(--fc-muted);
  font-size: var(--fs-input);
  line-height: 1.35;
}
.address-search-result:hover,
.address-search-result:focus {
  background-color: rgba(var(--accent-rgb), 0.18);
  color: var(--fc-strong);
  outline: none;
}

/* A field the map or the search has just written to. The location fields are
   also typed into by hand, so a value that changes from elsewhere has to be
   seen changing rather than appear to change on its own. */
@keyframes field-just-changed {
  from {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.35);
  }
  to {
    border-color: inherit;
    box-shadow: none;
  }
}
.field-just-changed {
  animation: field-just-changed 1.2s ease-out;
}

/* --- 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 {
  /* A fixed box, with the glyph centred in it.  The Bootstrap Icons glyphs are
     not the same width -- bi-gear, bi-geo-alt, bi-cash-coin and bi-file-text
     all differ -- so without this each heading started at its own x and left
     its own gap before the text: measured 107 vs 109 on one column and 818 vs
     816 on the other, which reads as sections that do not line up. */
  display: inline-block;
  width: 1.15em;
  text-align: center;
  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);
}

/* Both routes to a component — the edit modal and the detail page — head it with
   the category above its own name, so the two read alike. A label, not a title. */
body.solution-b .component-category {
  font-size: var(--fs-emphasis);
  font-weight: 300;
  color: var(--fc-muted);
  line-height: 1.2;
}
body.solution-b .component-category-icon {
  color: var(--accent);
  margin-right: 4px;
}
body.solution-b .component-title-stack {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
body.solution-b .component-title-stack .card-title {
  margin-bottom: 0;
}

/* --- "Summary" derived figures (component form, right column) ---
   Read-only numbers the converter computes from the values on the left. Laid out
   on the same 7/3/2 grid as the input rows opposite so labels, values and units
   line up across the two columns. */
body.solution-b .derived-figure-row {
  margin-bottom: 2px;
}
/* Value and its unit share one size and the accent colour, the way .cc-opt-val
   presents an optimal figure on the sizing cards: these are computed results, not
   entered values, so they should not read as more form content. The "per unit"
   qualifier stays small and muted, like .capacity-figure does there. */
body.solution-b .derived-figure-value,
body.solution-b .settings-field-unit .derived-figure-unit {
  /* Same size as the labels opposite — the accent already sets these apart, so
     they do not need to be larger as well. */
  font-size: var(--fs-text);
  color: var(--accent);
  font-weight: 500;
  line-height: 1.4;
}
body.solution-b .derived-figure-value {
  padding-top: 0.2rem;
  padding-bottom: 0.2rem;
  text-align: right;
}
body.solution-b .derived-figure-row .derived-figure-scope {
  color: var(--fc-muted);
  font-weight: 300;
}
body.solution-b .derived-figures {
  margin-bottom: 18px;
  /* The settings rows drop their right gutter, which leaves the unit column
     running to the card edge — fine for "EUR", tight for the longest one,
     "EUR/kWh/a". Inset the panel so even that keeps a margin. */
  padding-right: 22px;
}

/* The description moved out of the flex column that used to stretch its textarea,
   so give it its own height here rather than inheriting one from a flex parent. */
body.solution-b .component-description-field {
  margin-top: 18px;
}
body.solution-b .component-description-field textarea {
  /* The widget renders rows="10", which left a tall empty box below the fields
     now that the description sits in the left column. Size it to a few lines and
     let the user drag it taller when they actually write something. */
  height: 96px;
  min-height: 96px;
  max-height: none;
  resize: vertical;
  background-color: transparent;
  color: inherit;
  /* Matches the input fields it now sits beneath. It kept the larger 0.875rem of
     its old home in the right-hand column, where nothing was next to it. */
  font-size: var(--fs-input);
  padding-left: 8px;
  width: 100%;
}
body.solution-b .component-description-field textarea:hover {
  border-color: var(--fc-faint);
}
body.solution-b .component-description-field textarea:focus {
  border-color: var(--accent);
  background-color: transparent;
  outline: none;
}

/* Total vs per-day on the battery-cycles chart. A filled pill, deliberately
   unlike the outlined time-range buttons beside it: they choose a resolution,
   this chooses what the bars mean. */
body.solution-b .cycles-mode-switch {
  flex: 0 0 auto;
  align-self: flex-start;
  display: inline-flex;
  gap: 0;
  padding: 2px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
body.solution-b .cycles-mode-switch > .btn.cycles-mode-option {
  margin: 0 !important;
  padding: 3px 12px !important;
  font-size: var(--fs-text) !important;
  font-weight: 300 !important;
  line-height: 1.2 !important;
  border-radius: 999px !important;
  color: rgba(255, 255, 255, 0.55) !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  cursor: pointer;
}
body.solution-b .cycles-mode-switch > .btn.cycles-mode-option:hover {
  color: var(--fc-heading) !important;
}
body.solution-b .cycles-mode-switch > .btn.cycles-mode-option.active {
  color: var(--fc-strong) !important;
  background: var(--accent) !important;
}
body.solution-b .cycles-mode-switch > .btn.cycles-mode-option.disabled {
  opacity: 0.4;
  cursor: default;
}

/* The explainer beside a chart title. */
body.solution-b .cycles-info-icon {
  margin-left: 6px;
  font-size: 0.8em;
  color: rgba(255, 255, 255, 0.45);
  cursor: help;
}
body.solution-b .cycles-info-icon:hover {
  color: var(--accent);
}

/* Reference panel explaining each market and the input that drives it. Sizes
   and colours come from the page scale — see the token block at the top —
   because the panel sits among the results sections and has no business
   inventing its own. Collapsed by default: something to consult, not to scroll
   past every visit. */
body.solution-b .markets-info {
  margin: 0 0 16px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.03);
  overflow: hidden;
}
body.solution-b .markets-info-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px 14px;
  border: none;
  background: transparent;
  color: var(--fc-heading);
  font-size: var(--fs-emphasis);
  font-weight: 400;
  text-align: left;
}
body.solution-b .markets-info-toggle span {
  flex: 1 1 auto;
}
body.solution-b .markets-info-toggle .bi-info-circle {
  color: var(--accent);
}
body.solution-b .markets-info-chevron {
  transition: transform 0.18s ease;
  font-size: var(--fs-input);
  color: var(--fc-muted);
}
body.solution-b
  .markets-info-toggle[aria-expanded="true"]
  .markets-info-chevron {
  transform: rotate(180deg);
}
body.solution-b .markets-info-intro {
  padding: 10px 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  font-size: var(--fs-text);
  line-height: 1.6;
  max-width: 90ch;
}
body.solution-b .markets-info-intro p {
  margin-bottom: 10px;
}
body.solution-b .markets-info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  gap: 10px;
  padding: 0 14px 14px;
}
/* A panel with no intro paragraph still needs to clear the toggle. */
body.solution-b
  .markets-info-toggle
  + .collapse
  > .markets-info-grid:first-child {
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
}
body.solution-b .markets-info-card {
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-left-width: 3px;
  background: rgba(255, 255, 255, 0.02);
}
body.solution-b .markets-info-card h4 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 6px;
  font-size: var(--fs-emphasis);
  font-weight: 400;
  color: var(--fc-heading);
}
body.solution-b .markets-info-tag {
  padding: 1px 7px;
  border-radius: 999px;
  font-size: var(--fs-input);
  background: rgba(255, 255, 255, 0.08);
  color: var(--fc-muted);
}

/* Each market reads as a small table: what it is, which prices drive it, when
   it is dispatched, how it is traded, and what can be changed. */
body.solution-b .markets-info-rows {
  display: grid;
  grid-template-columns: minmax(9rem, 30%) 1fr;
  margin: 0;
}
body.solution-b .markets-info-rows dt {
  padding: 6px 12px 6px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  color: var(--fc-muted);
  font-size: var(--fs-input);
  font-weight: 400;
}
body.solution-b .markets-info-rows dd {
  margin: 0;
  padding: 6px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  font-size: var(--fs-text);
  line-height: 1.55;
}
body.solution-b .markets-info-rows dt:first-of-type,
body.solution-b .markets-info-rows dd:first-of-type {
  border-top: none;
}
@media (max-width: 720px) {
  body.solution-b .markets-info-rows {
    grid-template-columns: 1fr;
  }
  body.solution-b .markets-info-rows dd {
    padding-top: 0;
    border-top: none;
  }
}

/* One accent per family, so the cards group at a glance. */
body.solution-b .markets-info-reserve {
  border-left-color: var(--accent);
}
body.solution-b .markets-info-reserve .markets-info-tag {
  background: rgba(var(--accent-rgb), 0.18);
  color: var(--fc-heading);
}
body.solution-b .markets-info-soc {
  border-left-color: #5ecfa0;
}
body.solution-b .markets-info-soc .markets-info-tag {
  background: rgba(94, 207, 160, 0.18);
  color: var(--fc-heading);
}
body.solution-b .markets-info-energy {
  border-left-color: #f5a623;
}
body.solution-b .markets-info-energy .markets-info-tag {
  background: rgba(245, 166, 35, 0.18);
  color: var(--fc-heading);
}

/* The closing block: what happens when, over a delivery day. Numbered because
   the order is the point. */
body.solution-b .markets-info-sequence {
  margin: 0 14px 14px;
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.02);
}
body.solution-b .markets-info-sequence h4 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 8px;
  font-size: var(--fs-emphasis);
  font-weight: 400;
  color: var(--fc-heading);
}
body.solution-b .markets-info-sequence h4 .bi {
  color: var(--accent);
}
body.solution-b .markets-info-sequence ol {
  margin: 0 0 8px;
  padding-left: 1.1rem;
}
body.solution-b .markets-info-sequence li,
body.solution-b .markets-info-sequence p {
  margin-bottom: 6px;
  font-size: var(--fs-text);
  line-height: 1.55;
}
body.solution-b .markets-info-sequence p {
  margin: 0;
}
body.solution-b .markets-info-step {
  display: block;
  color: var(--fc-heading);
}

/* The abbreviation spelled out beside a reserve product's name. */
body.solution-b .markets-info-fullname {
  flex: 1 1 auto;
  color: var(--fc-muted);
  font-size: var(--fs-input);
  font-weight: 300;
}

/* The cycle equation, set apart from the sentence carrying it. */
body.solution-b .cycle-formula {
  white-space: nowrap;
  padding: 1px 6px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--fc-heading);
}

/* ── Simulated period ─────────────────────────────────────────────────────
   The horizon block in the General settings: a choice between the project
   lifetime and a date range, and the two dates. Whichever is not in force is
   dimmed rather than hidden, so the layout does not jump and the values stay
   readable. */
body.solution-b .simulation-period-dates,
body.solution-b .settings-field-row.is-inactive {
  transition: opacity 0.15s ease;
}

body.solution-b .simulation-period-dates.is-inactive,
body.solution-b .settings-field-row.is-inactive {
  opacity: 0.45;
}

/* Messages under the dates: what the period does, or what it needs. Full width
   and on their own line — in the input column they are three words wide and
   overlap the row beneath. Muted for a consequence, warning-coloured for
   something the user has to act on. */
body.solution-b .simulation-period-message {
  margin: -0.25rem 0 0.75rem;
  font-size: var(--fs-input);
  line-height: 1.35;
  color: var(--fc-muted);
}

body.solution-b .simulation-period-message.is-problem {
  color: #ff8d72;
}

body.solution-b .simulation-period-message ul,
body.solution-b .simulation-period-message .errorlist {
  margin: 0;
  padding: 0;
  list-style: none;
}

body.solution-b .create-horizon-dates {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

body.solution-b .css-field.is-inactive {
  opacity: 0.45;
}

/* Two button groups in one chart header: the basis and the period. */
body.solution-b .ts-plot-controls {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  /* Pinned to the top like ``.ts-timerange`` and ``.ts-data-download``, which
     both set it so they hold their place when a long title wraps to two lines.
     Without it this wrapper was centred by the header row while the Data link
     beside it was top-pinned, so the two sat at different heights. */
  align-self: flex-start;
}

/* The information marker on a result tile that carries an explanation. */
body.solution-b .skpi-info {
  margin-left: 0.2rem;
  font-size: 0.7em;
  opacity: 0.75;
}

/* ======== Generated PDF report — the button on the report page ========
   Report page only; the original design does not render the button at all. */
.report-pdf-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
}
.report-pdf-status {
  font-size: 0.8125rem;
  /* Explicit rather than muted: this is the only sign the user has that a
     generation lasting several seconds is still running. */
  color: var(--fc-heading);
}
/* The button keeps its shape while it works — a disabled button that also loses
   its label reads as having vanished. */
#generate-report-pdf.is-working {
  opacity: 1;
  min-width: 150px;
}
#generate-report-pdf.is-working::before {
  content: "";
  display: inline-block;
  width: 11px;
  height: 11px;
  margin-right: 8px;
  vertical-align: -1px;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: report-pdf-spin 0.7s linear infinite;
}
@keyframes report-pdf-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ================= Report page (Solution B) =================
   Renders the same report definition the PDF does. On screen it keeps the
   application's dark theme; the document inverts to dark-on-white, because a
   printed page is not a screenshot. */
.report-b__content {
  max-width: 1100px;
  margin: 0 auto;
  padding: 32px 24px 80px;
}
.report-b__header {
  margin-bottom: 48px;
}
.report-b__kicker {
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 6px;
}
.report-b__title {
  font-size: 1.75rem;
  font-weight: 600;
  margin: 0;
  overflow-wrap: anywhere;
}
.report-b__description {
  margin: 16px 0;
  color: var(--fc-muted);
}
.report-b__facts {
  margin: 20px 0;
  border-collapse: collapse;
  width: 100%;
  max-width: 520px;
  font-size: 0.8125rem;
}
.report-b__facts td {
  padding: 6px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.report-b__facts td:first-child {
  color: var(--fc-muted);
  width: 180px;
}
.report-b__kpis {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 24px;
}
.report-b__kpi {
  flex: 1 1 210px;
  background: var(--panel-bg);
  border-top: 2px solid var(--accent);
  padding: 14px 16px;
}
.report-b__kpi-label {
  font-size: 0.6875rem;
  color: var(--fc-muted);
  margin: 0 0 6px;
}
.report-b__kpi-value {
  font-size: 1.25rem;
  font-weight: 600;
  margin: 0;
  color: var(--fc-kpi);
}
.report-b__section {
  margin-bottom: 56px;
}
.report-b__section-title {
  font-size: 1.25rem;
  font-weight: 600;
  margin: 0;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--accent);
  display: inline-block;
}
/* One sentence saying what the section answers. A reader who stops after the
   leads has still read the report. */
.report-b__lead {
  color: var(--fc-muted);
  font-size: 0.875rem;
  margin: 14px 0 24px;
  max-width: 70ch;
}
.report-b__block-title {
  font-size: 0.875rem;
  color: var(--fc-heading);
  margin: 24px 0 8px;
}
.report-b__figure {
  margin: 0 0 32px;
}
.report-b__caption {
  font-size: 0.75rem;
  color: var(--fc-muted);
  margin-top: 8px;
}
.report-b__schematic {
  text-align: center;
  margin-bottom: 24px;
}
.report-b__schematic img {
  max-width: 640px;
  height: auto;
}
.report-b__facts-table td {
  font-size: 0.875rem;
}

/* ---- The system as an energy bus, on the report page ----
   The document uses the same geometry in report_pdf.css, so the two read as one
   drawing in two palettes. Cards in a column share its height, or a component
   whose name wraps to two lines would sit taller than the one beside it. */
.rbus {
  display: flex;
  align-items: stretch;
  margin: 8px 0 28px;
}
.rbus__col {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.rbus__spine {
  flex: 0 0 130px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rbus__spine::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  background: var(--accent);
  transform: translateX(-50%);
}
.rbus__node {
  position: relative;
  background: var(--accent);
  color: #fff;
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 6px 12px;
  white-space: nowrap;
}
.rbus__card {
  flex: 1 1 0;
  background: var(--panel-bg);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left: 3px solid var(--accent);
  padding: 12px 14px 12px 48px;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-width: 0;
}
.rbus__icon {
  position: absolute;
  left: 15px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.25rem;
  color: var(--accent);
  line-height: 1;
}
.rbus__type {
  font-size: 0.6875rem;
  color: var(--fc-muted);
}
.rbus__name {
  font-size: 0.8125rem;
  color: var(--fc-heading);
  overflow-wrap: anywhere;
}
.rbus__size {
  font-size: 1rem;
  font-weight: 600;
  color: var(--fc-kpi);
}

/* ---------------- The report page as its own editor ---------------- */
.report-b__toolbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--panel-bg);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  padding: 12px 16px;
  margin: -32px -24px 28px;
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}
.report-b__hint {
  margin: 0;
  font-size: 0.75rem;
  color: var(--fc-muted);
}
.report-b__logo {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}
.report-b__logo img {
  max-height: 60px;
  max-width: 220px;
  background: #fff;
  padding: 6px;
  border-radius: 2px;
}
/* Anything editable shows where it is only on approach: a page covered in
   boxes reads as a form rather than as the report it is previewing. */
[data-report-edit] {
  border-radius: 2px;
  outline: 1px dashed transparent;
  outline-offset: 4px;
  transition: outline-color 0.15s ease;
  min-height: 1em;
}
[data-report-edit]:hover {
  outline-color: rgba(var(--accent-rgb), 0.5);
}
[data-report-edit]:focus {
  outline: 1px solid var(--accent);
  outline-offset: 4px;
}
[data-report-edit]:empty::before,
[data-report-edit][data-empty="true"]::before {
  content: attr(data-report-placeholder);
  color: var(--fc-faint);
  font-style: italic;
}
.report-b__intro {
  margin: 16px 0;
  color: var(--fc-muted);
  max-width: 70ch;
}
.report-b__figure {
  position: relative;
}
.report-b__remove {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 5;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: var(--fc-muted);
  border-radius: 2px;
  width: 26px;
  height: 26px;
  line-height: 1;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.report-b__figure:hover .report-b__remove {
  opacity: 1;
}
.report-b__remove:hover {
  color: #fff;
  border-color: var(--accent);
}
.report-b__removed {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 8px 0 24px;
}
.report-b__removed-label {
  font-size: 0.75rem;
  color: var(--fc-muted);
}
/* Unsaved work is said in words beside the button. It used to be a bullet on
   the button itself, which wrapped onto a line of its own and read as damage. */
.report-b__unsaved {
  font-size: 0.75rem;
  color: var(--accent);
  white-space: nowrap;
}

/* The numbers behind a chart, at the right-hand end of its controls — last in
   the markup as well as on screen, so what a reader tabs to matches what they
   see. Quiet: it is there for the reader who wants to check a figure, not a
   thing to press by default. */
.ts-data-download {
  /* align-self matters more than any of the sizing: the pill group beside it is
     pinned to the top of the header row so it stays put when a long title wraps
     to two lines, while the row itself centres its children. Centred against
     top-pinned pills is what left this sitting low; it is pinned the same way,
     and matches their padding, border and line height so the two read as one
     row of controls. */
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 8px;
  padding: 4px 9px;
  line-height: 1.2;
  border: 1px solid transparent;
  border-radius: 6px;
  font-size: var(--fs-text);
  font-weight: 300;
  color: rgba(255, 255, 255, 0.55);
  white-space: nowrap;
}
.ts-data-download:hover {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.12);
  text-decoration: none;
}

/* ---- Settings sections that fold away ----
   Off-grid operation and reserve, and the sensitivity values: both matter to a
   minority of projects and both are long, so they open on request rather than
   filling the tab by default. */
.settings-foldaway__head {
  cursor: pointer;
  display: flex;
  align-items: center;
  /* No gap: the icon already carries ``.tab-icon``'s 5px margin, exactly as it
     does on the block headings, and a flex gap on top of it put 13px between
     icon and text here against 5px everywhere else.  The chevron is pushed to
     the far end by its own margin-left:auto, so it needs no gap either. */
  gap: 0;
  user-select: none;
}
.settings-foldaway__chevron {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--fc-muted);
  transition: transform 0.15s ease;
}
.settings-foldaway[data-open="true"] .settings-foldaway__chevron {
  transform: rotate(180deg);
}
.settings-foldaway__body {
  display: none;
}
/* A closed section keeps its rule. The rule belongs to the heading, not to the
   body, and hiding it left the heading floating with nothing to anchor it while
   the sections above and below still had one — which is what made the spacing
   read as arbitrary. Every section is now heading, rule, then body or nothing,
   with one gap between them whatever their state.

   That gap is the h4's own bottom margin, left alone here. Zeroing it put the
   rule 6px under these two headings against 15px under every other one. */
.settings-foldaway[data-open="true"] .settings-foldaway__body {
  display: block;
}
/* Ignored by the calculation while the switch above them is off; said by the
   interface rather than left to a tooltip. The switch itself keeps its
   contrast, and the values stay editable — greying is a statement about what
   the calculation will use, not a lock. */
.settings-fields-inactive .settings-field-row {
  opacity: 0.45;
}
/* Not :first-child — the switch is rendered wherever the model declares it, and
   that is last, so position picked the wrong row. It is marked instead. */
.settings-fields-inactive .settings-switch-row {
  opacity: 1;
}

/* The markets panel is reference material under the fields, not the next field.
   Without the gap it read as part of the form above it. Carries body.solution-b
   because the rule that sets the panel's margin does, and a shorthand margin
   there resets the top back to zero. */
body.solution-b .component-card-fields + .markets-info {
  margin-top: 22px;
}

/* ---- Project settings: sections flow down two columns ----
   They used to be paired into rows of two, which made every row as tall as its
   taller half: a short section left a column of air beside a long one, and the
   two sections that fold away became short on demand, so no pairing could have
   been right in both states. Flowed and packed instead, with each section kept
   whole. */
.settings-columns {
  column-count: 2;
  column-gap: 24px;
}
/* The gap below a section is padding, not margin, and it is the only source of
   space between sections. Margins were giving three different gaps for one
   rule: they collapse against the margin the last field row already carries,
   they collapse with the next section's, and a column break drops them
   altogether. Padding does none of that, so every section ends the same
   distance from the next whether it is open, closed, or first in a column. */
.settings-columns .settings-section {
  break-inside: avoid;
  page-break-inside: avoid;
  margin: 0;
  padding: 0 0 28px;
}
.settings-columns .settings-section > *:last-child,
.settings-columns .settings-foldaway__body > *:last-child {
  margin-bottom: 0;
}
/* On a closed section the hidden body is the last child, so the rule above it
   is not — and its own bottom margin was landing on top of the padding, giving
   closed sections a wider gap than open ones. */
.settings-columns .settings-foldaway[data-open="false"] .settings-section-hr {
  margin-bottom: 0;
}
/* A foldaway is rendered inside the section above it rather than beside it, so
   the padding that separates one section from the next never applies between
   the last field of that section and the foldaway's own heading -- two pixels,
   which read as a mistake. Give it the gap here instead. */
.settings-columns .settings-section .settings-foldaway {
  margin-top: 26px;
}
.settings-columns .settings-section .settings-foldaway + .settings-foldaway {
  margin-top: 18px;
}
@media (max-width: 991px) {
  .settings-columns {
    column-count: 1;
  }
  /* The grid on #location-row replaces the col-lg-6 stacking, so it has to
     collapse at the same breakpoint the sections do. */
  #location-row {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 28px;
  }
}

/* ==================== The manual, inside the application ====================
   Two indexes rather than one: the chapters, so a reader can see the shape of
   the book, and the current chapter's own headings, so a long list of
   parameters is navigable without scrolling through it. */
:root {
  /* The manual's prose. Everything in a chapter that is not a heading. */
  --docs-prose: rgba(255, 255, 255, 0.8);
}
.docs {
  display: flex;
  align-items: flex-start;
  gap: 40px;
  max-width: 1240px;
  margin: 0 auto;
  padding: 24px 24px 80px;
}
.docs__index {
  flex: 0 0 260px;
  position: sticky;
  top: 24px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  font-size: 0.8125rem;
}
.docs__index-title {
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 12px;
}
/* ---- Searching the manual ----
   The box sits above the chapter list and its results replace nothing: the
   panel opens under the box and the chapters stay where they are, so a reader
   who searches by accident has not lost their place. */
.docs__search {
  max-width: 230px;
  margin-bottom: 16px;
}
.docs__search-input {
  font-size: 0.75rem;
  padding: 6px 10px;
  height: auto;
  background-color: transparent;
  color: var(--fc-kpi);
}
.docs__search-input::placeholder {
  color: var(--fc-faint);
}
.docs__results {
  list-style: none;
  margin: 8px 0 0;
  padding: 6px;
  background: var(--panel-bg);
  border-radius: 6px;
}
.docs__result + .docs__result {
  margin-top: 2px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.docs__result > a {
  display: block;
  padding: 7px 8px;
  border-radius: 4px;
  text-decoration: none;
}
.docs__result > a:hover,
.docs__result > a.is-selected {
  background: rgba(255, 255, 255, 0.05);
  text-decoration: none;
}
.docs__result > a.is-selected {
  outline: 1px solid var(--accent);
}
.docs__result-where {
  display: block;
  font-size: 0.75rem;
  color: var(--accent);
  margin-bottom: 2px;
  /* A workbook column is one long unbroken word -- it has to break somewhere
     or it runs out of the panel. */
  overflow-wrap: anywhere;
}
.docs__result-sep {
  color: var(--fc-faint);
}
/* What kind of thing was found. A chapter, a section, a field of the interface
   or a column of the workbook are different answers to the same word, and the
   tag is what separates them without a sentence of explanation. */
.docs__result-tags {
  display: block;
  margin: 3px 0 3px;
  line-height: 1;
}
.docs__result-tags:empty {
  display: none;
}
.docs__tag {
  display: inline-block;
  padding: 2px 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.08);
  font-size: 0.5625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fc-muted);
}
/* The words the reader typed, shown where they were found. Colour rather than
   a block of highlight: the panel is dark and a yellow block on it is a shout. */
.docs__results mark {
  background: transparent;
  color: var(--accent);
  font-weight: 600;
  padding: 0;
}
.docs__result-snippet mark {
  color: #fff;
}
.docs__result-in {
  font-size: 0.625rem;
  color: var(--fc-faint);
}
.docs__result-snippet {
  display: block;
  font-size: 0.6875rem;
  line-height: 1.45;
  color: var(--fc-muted);
}
.docs__results-empty {
  margin: 8px 0 0;
  font-size: 0.6875rem;
  color: var(--fc-faint);
}

.docs__chapters {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: none;
}
/* The parts of the manual, as headings inside the chapter list. They are list
   items so the list stays one <ol>, but they carry no link and no number —
   the chapter numbers are rendered from the data, not from a counter, so a
   heading between them does not disturb the sequence. */
.docs__part {
  list-style: none;
  margin: 18px 0 6px;
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fc-faint);
}
.docs__part:first-child {
  margin-top: 0;
}
.docs__chapter > a {
  display: flex;
  gap: 10px;
  padding: 6px 0;
  color: var(--fc-muted);
}
.docs__chapter > a:hover {
  color: #fff;
  text-decoration: none;
}
.docs__chapter.is-current > a {
  color: #fff;
  font-weight: 600;
}
.docs__chapter-number {
  flex: 0 0 18px;
  color: var(--fc-faint);
  text-align: right;
}
.docs__sections {
  list-style: none;
  margin: 2px 0 10px 28px;
  padding: 0 0 0 12px;
  border-left: 1px solid rgba(255, 255, 255, 0.12);
}
.docs__section a {
  display: block;
  padding: 3px 0;
  color: var(--fc-muted);
  font-size: 0.75rem;
}
.docs__section a:hover {
  color: var(--accent);
  text-decoration: none;
}
.docs__section--l3 a {
  padding-left: 12px;
  color: var(--fc-faint);
}
.docs__body {
  flex: 1 1 0;
  min-width: 0;
  max-width: 78ch;
}
.docs__kicker {
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 6px;
}
.docs__title {
  font-size: 1.75rem;
  font-weight: 600;
  margin: 0 0 28px;
}
.docs__missing {
  color: var(--fc-faint);
  font-style: italic;
}
/* The chapter text. Set for reading rather than for scanning: a measure that
   stops at 78 characters, and headings that separate rather than shout. */
.docs__content {
  /* Poppins at 400 reads heavy over a page of prose, and at full muted white
     the bold runs stop standing out. Light and a shade softer, the way the
     index beside it reads, with the emphasis carried by weight and colour
     together rather than by weight alone. */
  /* One value for every kind of prose in a chapter, restated on the elements
     themselves because the theme carries bare `p { color: … }` and
     `ol li, ul li { color: … }` rules -- an element selector beats an
     inherited colour however weak it is, which is how paragraphs and bullets
     came to differ. */
  color: var(--docs-prose);
  font-weight: 300;
  line-height: 1.5;
}
.docs__content p,
.docs__content li,
.docs__content td,
.docs__content blockquote {
  color: var(--docs-prose);
}
.docs__content strong,
.docs__content b {
  font-weight: 600;
  color: var(--fc-heading);
}
.docs__content h2 {
  font-size: 1.125rem;
  font-weight: 600;
  color: #fff;
  margin: 40px 0 4px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.docs__content h3 {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--fc-heading);
  margin: 28px 0 6px;
}
.docs__content h4 {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--accent);
  margin: 22px 0 4px;
}
/* A short note under a chart, saying what the chart does not cover. */
.chart-note {
  margin: 10px 18px 0;
  font-size: 0.75rem;
  font-weight: 300;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.55);
}

.docs__content p,
.docs__content li {
  font-size: 0.8125rem;
}
/* Prose is set quiet and tight, so paragraphs need the space between them to
   do the separating that the leading no longer does. */
.docs__content p {
  margin-bottom: 14px;
}
.docs__content ul,
.docs__content ol {
  padding-left: 20px;
}
.docs__content li {
  margin-bottom: 4px;
}
.docs__content code {
  background: rgba(255, 255, 255, 0.07);
  padding: 1px 5px;
  border-radius: 3px;
  color: var(--fc-heading);
  font-size: 0.8125rem;
}
.docs__content pre {
  background: var(--panel-bg);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 4px;
  padding: 14px 16px;
  overflow-x: auto;
}
.docs__content pre code {
  background: none;
  padding: 0;
}
.docs__content table {
  width: 100%;
  border-collapse: collapse;
  margin: 16px 0 24px;
  font-size: 0.8125rem;
}
.docs__content td {
  font-weight: 300;
}
.docs__content th {
  text-align: left;
  color: #fff;
  background: var(--panel-bg);
  padding: 8px 10px;
}
/* A table of a short key against a long description: let the description have
   the room. Without this the browser shares the width evenly and the first
   column, holding a sheet or column name, is far wider than it needs while the
   text beside it wraps to many lines. */
.docs__content table th:first-child,
.docs__content table td:first-child {
  width: 1%;
  white-space: nowrap;
}
.docs__content td {
  padding: 7px 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  vertical-align: top;
}
.docs__content blockquote {
  margin: 16px 0;
  padding: 2px 0 2px 16px;
  border-left: 2px solid var(--accent);
  color: var(--fc-heading);
}
.docs__content hr {
  border-color: rgba(255, 255, 255, 0.1);
  margin: 32px 0;
}
/* A screenshot and what it shows. The picture is captured against the same
   dark interface, so it needs a border rather than a background to sit on. */
.docs__figure {
  margin: 24px 0 28px;
}
.docs__figure img {
  display: block;
  width: 100%;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 6px;
}
/* A diagram taken from a paper or a data sheet, drawn on white. Given its own
   plate rather than dropped straight onto the dark page, so it reads as a
   figure rather than as a hole in the layout. */
.docs__figure img.docs-plate {
  background: #fff;
  padding: 16px;
  max-width: 100%;
  width: auto;
  margin: 0 auto;
}
/* An equation lifted from the old documents: typeset on white, and read as
   part of the sentence around it rather than as a figure of its own. */
.docs__figure img.docs-equation {
  background: #fff;
  padding: 10px 14px;
  border-radius: 4px;
  width: auto;
  max-width: 100%;
}
.docs__figure figcaption {
  margin-top: 8px;
  font-size: 0.75rem;
  color: var(--fc-faint);
}
.docs__pager {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-top: 56px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.docs__pager-link {
  display: block;
  color: var(--fc-muted);
}
.docs__pager-link--next {
  text-align: right;
}
.docs__pager-link:hover {
  color: #fff;
  text-decoration: none;
}
.docs__pager-label {
  display: block;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--fc-faint);
}
.docs__pager-title {
  display: block;
  font-size: 0.875rem;
}
@media (max-width: 991px) {
  .docs {
    flex-direction: column;
  }
  .docs__index {
    position: static;
    flex: 1 1 auto;
    max-height: none;
  }
}
