/* Design tokens live in tokens.css — the seed of the shared @hotelshift/design-tokens.
   See PLATFORM.md sections 3.4 + 8.1 Step 1. Keep token names stable across the platform.
   Add/extend tokens there; do NOT introduce new hard-coded hex in component CSS. */
@import url("tokens.css");

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;        /* prevent iOS Safari auto-resizing fonts on rotate */
}

body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--text);
  background: var(--bg);
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
}

header {
  padding: 1.75rem 1.25rem 0.75rem;
  text-align: center;
}

header h1 {
  margin: 0;
  font-size: clamp(1.6rem, 2.5vw, 2.2rem);
}

header p {
  color: var(--muted);
  font-size: var(--fs-base);
  margin-top: 0.25rem;
}

.header-nav {
  margin-top: 0.6rem !important;
}
.header-nav a {
  display: inline-block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  padding: 0.3rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  transition: background 120ms ease;
}
.header-nav a:hover {
  background: var(--accent-light);
}
.header-nav a + a {
  margin-left: 0.4rem;
}

.panel {
  max-width: 1140px;
  margin: 0 auto 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1.5rem;
}

.hidden { display: none !important; }

.input-tabs {
  display: flex;
  gap: 0.4rem;
  border-bottom: 1px solid var(--border);
  margin: 0 -1.5rem 1rem;
  padding: 0 1.5rem;
}

.input-tab {
  background: none;
  color: var(--muted);
  border: 0;
  border-radius: 0;
  padding: 0.6rem 1rem;
  margin-bottom: -1px;
  font-weight: 600;
  font-size: var(--fs-sm);
  border-bottom: 2px solid transparent;
  cursor: pointer;
}

.input-tab:hover { color: var(--text); background: none; }

/* ===== API Usage monitoring tab ===== */
.mon-head { display: flex; justify-content: space-between; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
.mon-controls { display: flex; gap: 8px; align-items: flex-end; }
.mon-headline { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin: 8px 0 20px; }
.mon-metric { display: flex; flex-direction: column; gap: 2px; padding: 14px 16px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; }
.mon-metric-value { font-size: 1.6rem; font-weight: 600; color: var(--text); line-height: 1.1; }
.mon-metric-label { font-size: 0.8rem; color: var(--muted, #6b7280); }
.mon-metric-sub { margin-top: 4px; }
.mon-subhead { margin: 22px 0 8px; }
.mon-table-wrap { width: 100%; overflow: auto; border: 1px solid var(--border); border-radius: 8px; }
.mon-table { width: 100%; min-width: 0; table-layout: fixed; border-collapse: collapse; font-size: 0.9rem; }
.mon-table th, .mon-table td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; overflow: hidden; text-overflow: ellipsis; }
.mon-table th { font-weight: 600; color: var(--muted, #6b7280); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.03em; }
.mon-table td code { font-size: 0.82rem; }
.mon-num { text-align: right; font-variant-numeric: tabular-nums; }
.mon-when { white-space: nowrap; color: var(--muted, #6b7280); }
.mon-pill { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 0.72rem; font-weight: 600; }
.mon-pill--prod { background: #dbeafe; color: #1e40af; }
.mon-pill--local { background: #f3f4f6; color: #4b5563; }
.mon-recent-wrap { max-height: 420px; }
.mon-recent-wrap .mon-table th { position: sticky; top: 0; background: var(--surface); z-index: 1; }
.mon-note { margin-top: 14px; }

@media (max-width: 700px) {
  .mon-table-wrap {
    max-height: 70vh;
    touch-action: none;
    overscroll-behavior: contain;
  }

  .mon-table {
    min-width: 680px;
    table-layout: auto;
  }

  .mon-table th,
  .mon-table td {
    overflow: visible;
    text-overflow: clip;
    white-space: nowrap;
  }

  .mon-table thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--surface);
  }

  .mon-table th:first-child,
  .mon-table td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    min-width: 180px;
    max-width: 220px;
    white-space: normal;
    overflow-wrap: anywhere;
    background: var(--surface);
    box-shadow: inset -1px 0 0 var(--border);
  }

  .mon-table thead th:first-child {
    z-index: 4;
  }
}

.input-tab--active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  background: none;
}

/* On the Batch tab, force-hide every single-asset result section. They
   live outside #input-step and are revealed by a single search, so
   without this they bleed into the Batch view. !important + the
   body.batch-mode scope beats any stray `hidden`-class state. */
body.batch-mode #dashboard-step,
body.batch-mode #prescreening-step,
body.batch-mode #underwriting-section,
body.batch-mode #offer-section,
body.lihtc-mode #dashboard-step,
body.lihtc-mode #prescreening-step,
body.lihtc-mode #underwriting-section,
body.lihtc-mode #offer-section,
body.detailed-mode #dashboard-step,
body.detailed-mode #prescreening-step,
body.detailed-mode #underwriting-section,
body.monitoring-mode #dashboard-step,
body.monitoring-mode #prescreening-step,
body.monitoring-mode #underwriting-section,
body.monitoring-mode #offer-section,
body.detailed-mode #offer-section {
  display: none !important;
}

.lihtc-intro {
  margin-bottom: 1rem;
}

.lihtc-intro h3 {
  margin-bottom: 0.35rem;
}

.lihtc-intro p {
  margin: 0;
}

.lihtc-calculator-frame {
  display: block;
  width: 100%;
  min-height: 78vh;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
}

/* ----- Detailed Underwriting (lease-up) ----- */

.du-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.du-headline {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.du-metric {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.du-metric-label {
  font-size: var(--fs-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.du-metric-value {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 700;
}

.du-metric--hero {
  background: var(--accent-light);
  border-color: var(--accent);
  grid-column: 1 / -1;
}

.du-metric--hero .du-metric-value {
  font-size: var(--fs-3xl);
  color: var(--accent);
}

.du-schedule-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
/* Lease-up modeling table: a vertical scroll box so the sticky month-header row
   stays fixed while the (many) account rows scroll under it. */
#du-results .du-schedule-wrap {
  max-height: 70vh;
  overflow-y: auto;
}

.du-schedule {
  border-collapse: collapse;
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.du-schedule th,
.du-schedule td {
  padding: 0.35rem 0.6rem;
  border-bottom: 1px solid var(--border);
  text-align: right;
}

.du-schedule thead th {
  position: sticky;
  top: 0;
  background: var(--bg);
  color: var(--muted);
  font-weight: 600;
  z-index: 2;   /* keep the month-header row above the rows scrolling under it */
}

.du-schedule tbody th {
  position: sticky;
  left: 0;
  background: var(--surface);
  text-align: left;
  font-weight: 600;
  z-index: 1;
}

.du-schedule thead th:first-child {
  left: 0;
  z-index: 3;   /* top-left corner sits above both the sticky header row and first column */
}

.du-schedule .du-neg {
  color: var(--danger);
}

/* Lease-UP statement structure (mirrors the workbook tab) */
.du-schedule tr.du-sched-section th {
  text-transform: uppercase;
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  color: var(--muted);
  background: var(--bg);
  padding-top: 0.5rem;
}
.du-schedule tr.du-sub th {
  padding-left: 1.5rem;
  font-weight: 400;
}
.du-schedule tr.du-bold th,
.du-schedule tr.du-bold td { font-weight: 700; }
.du-schedule tr.du-strong th,
.du-schedule tr.du-strong td { background: var(--accent-light); }
/* deeper indent for waterfall sub-items (LP pref / capital return, GP catch-up, tranche lines) */
.du-schedule tr.du-indent th { padding-left: 2.5rem; font-weight: 400; }
/* section divider rows span the row, not just the sticky label cell */
.du-schedule tr.du-sched-section td { background: var(--bg); }
/* Collapsible Debt Schedule / Capital Accounts under the monthly cash flow */
#input-detailed-pane .du-cf-detail { margin-top: 0.8rem; border: 1px solid var(--du-line); border-radius: 2px; background: #fff; }
#input-detailed-pane .du-cf-detail > summary {
  cursor: pointer; padding: 0.5rem 0.75rem; font-size: var(--fs-xs); font-weight: 700;
  color: var(--du-ink-soft); list-style: none; user-select: none;
}
#input-detailed-pane .du-cf-detail > summary::-webkit-details-marker { display: none; }
#input-detailed-pane .du-cf-detail > summary::before { content: "\25B8\00a0"; color: var(--accent); }
#input-detailed-pane .du-cf-detail[open] > summary::before { content: "\25BE\00a0"; }
#input-detailed-pane .du-cf-detail > summary .muted { font-weight: 400; }
#input-detailed-pane .du-cf-detail .du-schedule-wrap { border: none; margin: 0; }

/* Editable grid cells — the input fills the cell and looks flat until focused */
.du-schedule td.du-cell {
  padding: 0;
  min-width: 5.75rem;
  position: relative;
}
.du-cell-input {
  width: 100%;
  box-sizing: border-box;
  padding: 0.35rem 0.6rem;
  border: 1px solid transparent;
  border-radius: 0;
  background: transparent;
  font: inherit;
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: inherit;
}
.du-cell-input:hover { background: var(--bg); }
.du-cell-input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface);
}
.du-schedule td.du-cell.du-pinned { background: var(--accent-light); }
.du-schedule td.du-cell.du-pinned .du-cell-input {
  color: var(--accent);
  font-weight: 600;
}
.du-schedule td.du-cell.du-neg .du-cell-input { color: var(--danger); }
/* Editable cells read as a financial model: flat (no box) + BLUE = editable input,
   so they're distinguished from black CALCULATED cells by colour, not by box size.
   The input fills its cell so its value aligns with the calculated columns. */
#input-detailed-pane .du-schedule .du-cell-input {
  width: 100%; min-width: 0; max-width: none; margin: 0;
  border: none; background: transparent; box-shadow: none;
  color: var(--accent); font-weight: 500; text-align: right;
}
#input-detailed-pane .du-schedule td.du-cell.du-neg .du-cell-input { color: var(--danger); }
#input-detailed-pane .du-schedule .du-cell-input:hover { background: var(--du-band); }
#input-detailed-pane .du-schedule .du-cell-input:focus { background: var(--surface); box-shadow: inset 0 0 0 1px var(--accent); }
#input-detailed-pane .du-schedule td.du-cell.du-pinned .du-cell-input { color: var(--accent); font-weight: 700; }
/* Excel-like fill handle (shown on the focused cell) + drag-right copy range */
.du-fill-handle {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 8px;
  height: 8px;
  background: var(--accent);
  border: 1px solid #fff;
  border-radius: 1px;
  cursor: crosshair;
  z-index: 3;
  display: none;
}
.du-schedule td.du-cell:focus-within .du-fill-handle { display: block; }
.du-schedule td.du-fill-target {
  background: var(--accent-light);
  box-shadow: inset 0 0 0 1px var(--accent);
}
body.du-fill-dragging, body.du-fill-dragging * { cursor: crosshair !important; user-select: none !important; }

/* Lease-Up results header (title + reset) + edit hint */
.du-results-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.du-edit-hint { margin: 0 0 0.75rem; font-size: var(--fs-xs); }

/* Calculate button flags unapplied edits (manual recalc) */
#du-calc-btn.du-calc-btn--pending {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

/* Operating-expense schedule: Line | Rate (+unit) | Floor, each line one row
   so the floor sits right next to its rate. */
.du-opex-grid {
  display: grid;
  grid-template-columns: max-content max-content max-content;
  gap: 0.4rem 1.75rem;
  align-items: baseline;
  margin-top: 0.4rem;
}
/* Cross-section alignment: in the lease-up left column, let the line-name column
   FILL so the rate + floor input columns push to the right — the Floor column then
   lines up vertically under the Lease-Up Timing input column above. */
.du-cols--leaseup-opex .du-opex-grid {
  grid-template-columns: minmax(0, 1fr) max-content max-content;
  column-gap: 1rem;
}
/* Right-align the Floor input within its (header-sized) column so its right edge
   lands on the column edge — lining up vertically with the Lease-Up Timing input
   above. */
.du-cols--leaseup-opex .du-opex-floor { justify-self: stretch; text-align: right; }
/* Stabilized opex is now FOUR columns: Category · Annual · Per unit · % of EGI. */
.du-stab-grid {
  /* Category sized to its content (not 1fr) so the Annual / Per-unit / %-EGI
     inputs sit right after the labels instead of being shoved to the far right. */
  grid-template-columns: max-content 7rem 7rem 6rem;
  column-gap: 1.25rem;
  justify-content: start;
}
.du-stab-grid input { width: 100%; }
/* The total row's three cells are editable OVERRIDE inputs (bold, like the old
   total text); the placeholder shows the computed Σ of the line items. */
.du-stab-total-in {
  width: 100%;
  padding: 0.25rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 700;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.du-stab-total-in::placeholder { font-weight: 600; color: var(--muted); opacity: 0.8; }
.du-linkbtn {
  border: none; background: none; color: var(--accent, #2c6ecb);
  cursor: pointer; padding: 0; font-size: var(--fs-xs); text-decoration: underline;
}
.du-linkbtn.hidden { display: none; }
/* "State OPEX defaults" button inline in the Lease-Up Operating Expenses heading */
.du-opex-defaults-btn {
  margin-left: 0.6rem; padding: 0.15rem 0.55rem;
  font-size: var(--fs-xs); font-weight: 500; vertical-align: middle;
}
/* State code parsed from the address — shows which state's OPEX defaults the
   button will load (e.g. "MN"). Hidden until a state is detected. */
.du-opex-state {
  display: inline-block; margin-left: 0.4rem; padding: 0.06rem 0.42rem;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.04em;
  color: var(--accent); background: var(--accent-light);
  border: 1px solid var(--accent); border-radius: 3px;
  vertical-align: middle; white-space: nowrap;
}
.du-opex-state[hidden] { display: none; }
.du-opex-h {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding-bottom: 0.1rem;
}
.du-opex-name { font-size: var(--fs-xs); color: var(--text); }
.du-opex-rate { display: inline-flex; align-items: baseline; gap: 0.35rem; }
.du-opex-rate .du-unit { font-size: var(--fs-xs); color: var(--muted); white-space: nowrap; }
.du-opex-grid input {
  width: 4.5rem;
  padding: 0.25rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--text);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.du-opex-grid input.du-money { width: 5.5rem; }
.du-opex-nofloor { color: var(--muted); }
/* Lease-up floor binding: the floor (monthly minimum) is the active driver, so the
   rate has no effect during lease-up — grey the rate, amber the floor (the driver). */
.du-opex-grid input.du-rate-inactive { opacity: 0.45; }
.du-opex-grid input.du-floor-active { background: #fff8e6; box-shadow: inset 2px 0 0 #e0a800; }
/* Small legend for the amber floor-binding highlight (non-intrusive, inline in the note). */
.du-floor-legend { white-space: nowrap; }
.du-floor-chip { display: inline-block; width: 0.72em; height: 0.72em; margin-right: 0.32em; vertical-align: -0.06em; background: #fff8e6; box-shadow: inset 2px 0 0 #e0a800; border: 1px solid #e7d9a8; border-radius: 1px; }

/* Stabilized-opex schedule: wider inputs (annual $) + bold total row */
.du-stab-grid input { width: 7rem; }
.du-opex-grid .du-opex-total {
  border-top: 1.5px solid var(--border);
  padding-top: 0.35rem;
  margin-top: 0.1rem;
  font-weight: 700;
  color: var(--text);
}
.du-opex-grid span.du-opex-total:not(.du-opex-name) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* Development-budget table: line · amount · ×. Constrained to the left column
   width (the masonry above uses a 2.5rem gap → each column is 50% − 1.25rem) so
   it lines up under Closing & Financing Costs, with the amount input the same
   7.5rem as the rest of the form (no ballooning into the next column). */
.du-input-table.du-devcost-table { max-width: none; width: calc(50% - 1.25rem); }
.du-devcost-table th:nth-child(2),
.du-devcost-table td:nth-child(2) { width: 7.5rem; }
.du-devcost-table th:last-child,
.du-devcost-table td:last-child { width: 1.5rem; }
.du-opex-ratioval { text-align: right; font-weight: 600; color: var(--accent); }

/* Address bar (top of Detailed Underwriting) */
.du-address-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin: 0.75rem 0;
  padding: 0.75rem 1rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.du-address-bar label { display: inline; font-size: var(--fs-sm); font-weight: 600; color: var(--text); white-space: nowrap; }
.du-address-bar .du-req { display: inline; color: var(--danger); }
.du-address-bar #du-address {
  flex: 1 1 14rem;
  min-width: 10rem;
  max-width: 38rem;
  height: 2.25rem;
  padding: 0 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
}
.du-address-bar #du-load-saved {
  height: 2.25rem;
  padding: 0 0.75rem;
  font-size: var(--fs-sm);
}
.du-saved-hint { flex-basis: 100%; font-size: var(--fs-xs); }

/* Save-to-DB section */
.du-save-notes { display: flex; flex-direction: column; gap: 0.4rem; margin: 0.75rem 0; }
.du-save-notes label { font-size: var(--fs-sm); font-weight: 600; }
.du-save-notes textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
  line-height: 1.5;
  resize: vertical;
}
.du-save-name-input {
  box-sizing: border-box;
  max-width: 28rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 500;
}
.du-save-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 1rem; }
.du-save-status { font-size: var(--fs-sm); }
.du-save-status.success { color: var(--accent); }
.du-save-status.error { color: var(--danger); }
/* A known, unsupported configuration (e.g. a deeply-junior deal the workbook
   can't model yet) — informational, not a failure: calm muted grey, not red. */
.du-save-status.notice { color: var(--muted); }
.du-save-req-hint { font-size: var(--fs-xs); margin-top: 0.4rem; }

/* Version picker modal */
.du-versions-list { display: flex; flex-direction: column; gap: 0.6rem; max-height: 60vh; overflow-y: auto; }
.du-version {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.7rem 0.85rem;
  background: var(--surface);
}
.du-version--newest { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.du-version-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.du-version-badge {
  font-size: var(--fs-xs);
  background: var(--accent);
  color: #fff;
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
}
.du-version-name { font-size: var(--fs-sm); margin-top: 0.15rem; }
.du-version-meta { font-size: var(--fs-xs); margin-top: 0.15rem; }
.du-version-metrics { font-size: var(--fs-sm); margin: 0.3rem 0; font-variant-numeric: tabular-nums; }
.du-version-note {
  font-size: var(--fs-xs);
  color: var(--text);
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: 0.4rem 0.55rem;
  margin: 0.3rem 0;
  white-space: pre-wrap;
}
.du-version-load { margin-top: 0.4rem; }

.du-versions-group { margin-bottom: 1rem; }
.du-versions-grouphead { margin: 0 0 0.2rem; font-size: var(--fs-sm); }
.du-versions-groupsub { font-size: var(--fs-xs); margin: 0 0 0.5rem; }
.du-version--prefill { border-style: dashed; }
.du-version--stale { border-color: #fcd34d; }
.du-prefill-apply { margin-top: 0.4rem; }
/* Rent-cache freshness callouts in the Load-saved picker */
.du-rent-stale {
  font-size: var(--fs-xs);
  color: #92400e;
  background: #fef3c7;
  border: 1px solid #fcd34d;
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.6rem;
  margin: 0.35rem 0 0.1rem;
  line-height: 1.4;
}
.du-rent-fresh { font-size: var(--fs-xs); margin: 0.3rem 0 0.1rem; }
.du-versions-empty { font-size: var(--fs-sm); margin: 0.2rem 0 0.5rem; }

.du-subhead {
  margin: 1.5rem 0 0.6rem;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.du-subhead .muted {
  text-transform: none;
  letter-spacing: 0;
}

.du-input-table {
  width: 100%;
  min-width: 0;          /* override global table { min-width: 1250px } — this is a compact form table, not a wide data grid */
  table-layout: fixed;   /* even, predictable columns so the number inputs don't balloon */
  border-collapse: collapse;
}

/* Cancel the global data-grid chrome (th,td border + th bg/uppercase) that leaks in */
.du-input-table th,
.du-input-table td {
  border-bottom: none;
}

.du-input-table thead th {
  background: none;
  text-transform: none;
}

.du-input-table th {
  text-align: right;
  font-size: var(--fs-xs);
  color: var(--muted);
  font-weight: 600;
  padding: 0 0.5rem 0.35rem;
}

.du-input-table th:first-child {
  text-align: left;
}

.du-input-table td {
  padding: 0.2rem 0.5rem 0.2rem 0;
}

.du-input-table input {
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.du-input-table .du-um-label,
.du-input-table .du-dc-label {
  text-align: left;
}

.du-input-table th:last-child,
.du-input-table td:last-child {
  width: 2.4rem;
}

.du-um-remove,
.du-dc-remove {
  border: none;
  background: none;
  color: var(--muted);
  font-size: var(--fs-lg);
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem 0.45rem;
  border-radius: var(--radius-sm);
}

.du-um-remove:hover,
.du-dc-remove:hover {
  color: var(--danger);
  background: var(--danger-bg);
}

.du-tot {
  font-weight: 700;
  font-size: var(--fs-sm);
  padding-top: 0.6rem !important;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Stabilized analysis — Excel "Stable Monthly" numbered sections */
.du-stmt-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
}
.du-stmt-sec {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.85rem 1rem;
  background: var(--surface);
}
.du-stmt-head {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 700;
  margin-bottom: 0.5rem;
}
.du-stmt-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.25rem 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.du-stmt-row span:last-child { font-weight: 600; }
.du-stmt-strong {
  border-top: 1px solid var(--border);
  margin-top: 0.25rem;
  padding-top: 0.4rem;
  font-weight: 700;
}

.du-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.3rem 1.5rem;
}

/* Place related input groups SIDE-BY-SIDE in responsive columns, so the page
   reads as dense vertical categories instead of long horizontal rows. Each
   child .du-group is one category (subhead + its inputs). Collapses to fewer
   columns on narrow viewports. Scoped to .du-cols so un-grouped sections and
   all OUTPUT tables (monthly cash flow) are unaffected. */
.du-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 0.4rem 2.5rem;
  align-items: start;
}
.du-group { min-width: 0; }
.du-group > .du-subhead:first-child { margin-top: 0.4rem; }
/* A group can stack several subhead+fields blocks (masonry): keep later subheads
   spaced so two categories read as distinct within one column. */
.du-group > .du-subhead:not(:first-child) { margin-top: 1.1rem; }
/* Inside a group, inputs stack VERTICALLY (column) — fast to scan top-to-bottom. */
.du-cols .du-fields {
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 0.35rem;
}
/* CONSISTENT ALIGNMENT — inside a column every field is a 2-col grid: a flexible
   label on the left and a FIXED-WIDTH input on the right, so all inputs share the
   same width and align on a common right edge (clean & intentional, not scattered).
   Checkboxes keep their inline layout. */
.du-cols .du-fields label:not(.du-check) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 7.5rem;
  align-items: center;
  gap: 0.1rem 0.6rem;
  width: 100%;
}
/* Selects show their option text left-aligned (numbers stay right-aligned). */
.du-cols .du-fields label:not(.du-check) > select { text-align: left; }
.du-cols .du-fields label:not(.du-check) > input,
.du-cols .du-fields label:not(.du-check) > select {
  width: 100%;
  min-width: 0;
  justify-self: end;
}
.du-cols .du-fields label.du-check { width: 100%; }
/* Required-field marker (Unit Mix). */
.du-req { color: #c0392b; font-weight: 700; }
/* Uniform numeric inputs across the form: NO spinner steppers (they shift the
   value left and break alignment) and values right-aligned like the money fields,
   so every input box reads identically. */
.du-fields input[type="number"],
.du-input-table input[type="number"],
.du-opex-grid input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
  text-align: right;
}
.du-fields input[type="number"]::-webkit-outer-spin-button,
.du-fields input[type="number"]::-webkit-inner-spin-button,
.du-input-table input[type="number"]::-webkit-outer-spin-button,
.du-input-table input[type="number"]::-webkit-inner-spin-button,
.du-opex-grid input[type="number"]::-webkit-outer-spin-button,
.du-opex-grid input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
/* The lease-up operating-expense TABLE needs more width than the short "other
   assumptions" column beside it — give the left column the lion's share. */
.du-cols--leaseup-opex {
  grid-template-columns: minmax(340px, 1.6fr) minmax(220px, 1fr);
}
/* Two numbered stages (Capital Events | Returns & Waterfall) side by side. */
.du-cols--stages { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.du-cols--stages .du-stage { margin: 0.25rem 0 0; }

/* Month-column headers in the schedules: "Month N" with an optional calendar
   month beneath (from the "Model start" picker), so the wide monthly grids stay
   scannable. Scoped to the output schedule tables. */
.du-schedule th.du-mhdr { white-space: nowrap; text-align: right; }
.du-mhdr-n { display: block; }
.du-mhdr-cal { display: block; font-size: 0.78em; font-weight: 400; color: var(--muted); opacity: 0.85; }

/* Compact assumptions: each label+value pair is only as wide as its content,
   packed left and wrapping within its category section — no dead space. */
.du-fields label {
  display: inline-grid;
  grid-template-columns: max-content auto;   /* label (never wraps) · value on row 1 */
  align-items: baseline;
  gap: 0.15rem 0.4rem;
  padding: 0.25rem 0;
  font-size: var(--fs-xs);
  color: var(--text);
}

.du-hint { font-size: var(--fs-xs); color: var(--muted); font-weight: 400; opacity: 0.85; }
/* A field the engine is currently IGNORING because an override supersedes it
   (e.g. Loan-to-Cost while a Senior loan override is set). Visibly inert but
   still editable — clearing the override restores it. */
.du-input-overridden { opacity: 0.4; text-decoration: line-through; }
.du-fields .du-hint { grid-column: 1 / -1; max-width: 15rem; text-align: left; }   /* hint on its own row, below label·value */
.du-fields > .du-hint { flex-basis: 100%; max-width: 100%; }   /* a standalone note (e.g. floors) spans the full row */

/* Inline checkbox field (e.g. "Finance interest reserve") */
.du-fields label.du-check {
  gap: 0.45rem;
  color: var(--text);
}
.du-fields label.du-check input { width: auto; flex: none; margin: 0; }
.du-derived { margin: 0.6rem 0 0; font-size: var(--fs-sm); color: var(--text); }

/* Prominent alert banner (e.g. cash-in refinance required) — full-width, hard to
   miss; never buried in the assumptions since it changes investor economics. */
.du-alert {
  margin: 0 0 1rem;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  font-size: var(--fs-sm);
  line-height: 1.45;
}
.du-alert.hidden { display: none; }
.du-alert--danger {
  background: #fdecea;
  border: 1px solid #f5c6cb;
  border-left: 4px solid #c0392b;
  color: #7d2018;
}
.du-alert--warn {
  background: #fff6e9;
  border: 1px solid #f0d8b0;
  border-left: 4px solid #b35900;
  color: #7a4a00;
}

/* Subordinate-tranche stack: each cloned row is a bordered card; the whole stack
   lives inside one .du-group column. */
.du-sp-tranche {
  border: 1px solid var(--border, #e2e6ea);
  border-left: 3px solid #9aa7b4;
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.65rem 0.35rem;
  margin: 0 0 0.6rem;
  background: #fafbfc;
}
.du-sp-tranche-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 0.25rem;
}
.du-sp-tranche-title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-muted, #51616f);
  letter-spacing: 0.01em;
}
.du-sp-remove {
  border: none;
  background: transparent;
  color: #b03a2e;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.15rem 0.35rem;
  border-radius: var(--radius-sm);
}
.du-sp-remove:hover { background: #fdecea; }
.du-add-tranche {
  border: 1px dashed #9aa7b4;
  background: #fff;
  color: #2c3e50;
  font-size: var(--fs-sm);
  cursor: pointer;
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-sm);
}
.du-add-tranche:hover { background: #f1f4f7; border-color: #6b7b8a; }

.du-fields input,
.du-fields select {
  flex: 0 0 auto;
  padding: 0.25rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--text);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Inputs sized to their content type so there's no dead space */
.du-fields input.du-money { width: 6.5rem; }
.du-fields input[type="number"] { width: 4rem; }
.du-fields select {
  width: auto;
  min-width: 7rem;
  text-align: left;
  background: var(--surface);
}

.du-section-title {
  margin: 0 0 1rem;
  font-size: var(--fs-lg);
}
/* ── Numbered underwriting-stage spine: gives the long Detailed-UW tab a clear
   Excel-model flow (deal setup → capitalization → operations → returns) and
   makes the input stages legible at a glance. ──────────────────────────────── */
.du-stage {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 2rem 0 0.9rem;
  padding: 0.5rem 0.8rem;
  background: var(--accent-light);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
}
.du-stage--head { margin: 0; }   /* sits inside .du-head, beside the Calculate button */
.du-stage-num {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-sm);
}
.du-stage-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-base);
  color: var(--text);
}
.du-stage-sub {
  font-family: inherit;
  font-weight: 400;
  font-size: var(--fs-xs);
  color: var(--muted);
}
/* Computed-output sections read distinct from input cards (like Excel output cells) */
.du-outzone { border-left: 3px solid var(--accent); }
/* Global model action bar — the Calculate button drives the WHOLE model, so it
   sits above all stages (not inside Stage 1 Unit Mix) to read as model-wide. */
.du-actionbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 0 0 1rem;
  padding: 0.7rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.du-actionbar-label { font-size: var(--fs-sm); color: var(--muted); }
.form-section > .du-stage:first-child { margin-top: 0.2rem; }

/* Sensitivity analysis matrix */
.du-sens-axis { margin-bottom: 1.25rem; }
.du-sens-table {
  border-collapse: collapse;
  width: 100%;
  min-width: 0;          /* override the global table { min-width: 1250px } that forced overflow */
  max-width: 720px;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}
.du-sens-table th, .du-sens-table td {
  padding: 0.35rem 0.7rem;
  border-bottom: 1px solid var(--border);
  text-align: right;
}
.du-sens-table thead th { color: var(--muted); font-weight: 600; font-size: var(--fs-xs); }
.du-sens-table th:first-child { text-align: left; font-weight: 500; }
.du-sens-table tbody tr.du-sens-base { background: var(--accent-light); }
.du-sens-table tbody tr.du-sens-base th,
.du-sens-table tbody tr.du-sens-base td { font-weight: 700; }
.du-sens-up { color: #15803d; }
.du-sens-down { color: var(--danger); }
/* "— Scenario N" badge on the Sensitivity header: which unit-mix scenario the table ran against. */
.du-sens-scenario { margin-left: .45rem; font-size: var(--fs-sm); font-weight: 400; color: var(--muted); }

.du-su {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin-top: 0.5rem;
}

.du-su-head {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.4rem;
}

.du-su-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.3rem 0;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

.du-su-row span:first-child { color: var(--muted); }

.du-su-strong {
  font-weight: 700;
  border-top: 1px solid var(--border);
  margin-top: 0.2rem;
}

.du-su-strong span:first-child { color: var(--text); }

.du-su-note { margin-top: 1rem; font-size: var(--fs-xs); }

.du-more {
  margin-top: 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.du-more summary {
  padding: 0.5rem 0.75rem;
  font-size: var(--fs-xs);
  color: var(--muted);
  cursor: pointer;
  user-select: none;
}

.du-more summary:hover {
  color: var(--accent);
}

.du-more[open] summary {
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.5rem;
}

.du-more .du-fields {
  padding: 0 0.75rem 0.75rem;
}

/* ----- Batch UI ----- */

.muted { color: var(--muted); }

.batch-section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.batch-section-head h3 { margin: 0; }

.batch-textarea {
  width: 100%;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  resize: vertical;
  padding: 0.65rem 0.75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  transition: border-color 0.15s, box-shadow 0.15s;
}

.batch-upload-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

.batch-upload-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.85rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
}

.batch-upload-btn:hover {
  background: #f3f4f6;
  border-color: var(--accent);
}

.batch-drop-active {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 3px rgba(19, 76, 168, 0.15);
  background: var(--accent-light);
}

.batch-modes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.5rem 1rem;
}

.batch-modes label {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--text);
  font-weight: 500;
  font-size: var(--fs-sm);
}

/* A disabled mode (e.g. Underwriting when Rent is off) greys its whole
   row so the dependency reads at a glance. */
.batch-modes label:has(input:disabled) {
  opacity: 0.5;
}

.batch-modes input[type="checkbox"] {
  width: auto;
  padding: 0;
  margin: 0;
}

/* ── Cache mode radio group (2026-05-29) ──────────────────────────── */
/* Three mutually-exclusive cache modes (Rerun / Rescore / Force
   Refresh) — same conceptual model as the Recent Batches buttons,
   exposed here for new-batch submissions. */
.batch-cache-mode {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.batch-cache-mode label {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--fs-sm);
  line-height: 1.4;
}
.batch-cache-mode label:has(input:checked) {
  background: #eff6ff;
  border-color: var(--accent);
}
.batch-cache-mode input[type="radio"] {
  width: auto;
  margin: 0.18rem 0 0 0;
  flex-shrink: 0;
}
.batch-cache-mode .cache-mode-help {
  color: var(--muted);
  font-weight: 400;
}

.batch-progress-bar {
  position: relative;
  height: 10px;
  background: #f3f4f6;
  border-radius: 5px;
  overflow: hidden;
  margin: 0.5rem 0;
}

.batch-progress-bar-fill {
  height: 100%;
  background: var(--accent);
  transition: width 200ms ease;
}

.batch-progress-meta {
  margin: 0.4rem 0 0;
  font-size: var(--fs-sm);
}

.batch-error-count { color: #b91c1c; font-weight: 600; }

/* Read-only batch UI for non-admins (guests + non-AUTH_BATCH_ADMINS
   logged-in users). Banner above the disabled composer explains
   why the Run / Re-run / Force-refresh controls are hidden. */
.batch-readonly-banner {
  margin: 0 0 0.75rem;
  padding: 0.7rem 0.95rem;
  background: #fff7ed;
  border: 1px solid #fdba74;
  border-radius: 6px;
  color: #7c2d12;
  font-size: var(--fs-sm);
  line-height: 1.45;
}

.batch-readonly-banner strong { font-weight: 700; }

.batch-admin-locked {
  opacity: 0.55;
  pointer-events: none;
  filter: grayscale(0.4);
}

/* Weekly batch-quota usage indicator + hard-block notice (company-domain
   users). See static/js/batch.js. */
.batch-quota-bar {
  margin: 0 0 0.75rem;
  padding: 0.5rem 0.85rem;
  background: var(--surface-2, #f6f8fa);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--slate);
  font-size: var(--fs-sm);
  line-height: 1.4;
}
/* Running low — reuse the "metered API" amber from the read-only banner. */
.batch-quota-bar.low {
  background: #fff7ed;
  border-color: #fdba74;
  color: #7c2d12;
}
.batch-quota-bar strong { font-weight: 700; }

.batch-quota-block {
  margin: 0 0 0.75rem;
  padding: 0.7rem 0.95rem;
  background: var(--danger-bg);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-sm);
  color: var(--danger);
  font-size: var(--fs-sm);
  line-height: 1.45;
}
.batch-quota-block strong { font-weight: 700; }
.batch-quota-block button { margin-left: 0.4rem; }
.batch-quota-ack {
  margin-top: 0.5rem;
  color: var(--success);
  font-weight: 600;
}

/* ── Owner-only quota admin panel (quota_admin.js) ── */
.batch-quota-admin .qa-block { margin: 0 0 1.1rem; }
.batch-quota-admin .qa-block:last-child { margin-bottom: 0; }
.batch-quota-admin h4 {
  margin: 0 0 0.5rem;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--slate);
}
.batch-quota-admin .qa-req-list { list-style: none; margin: 0; padding: 0; }
.batch-quota-admin .qa-req {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.25rem 0.75rem;
  align-items: center;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 0.5rem;
}
.batch-quota-admin .qa-req-meta { grid-column: 1; font-size: 0.8em; }
.batch-quota-admin .qa-req-actions {
  grid-column: 2; grid-row: 1 / span 2;
  display: flex; gap: 0.4rem; align-items: center;
}
.batch-quota-admin .qa-note { color: var(--muted); }
.batch-quota-admin .qa-grant-input,
.batch-quota-admin .qa-manual-limit { width: 4.5rem; }
.batch-quota-admin .qa-manual {
  display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center;
}
.batch-quota-admin .qa-manual-email { flex: 1 1 16rem; min-width: 12rem; }
.batch-quota-admin .qa-hint { margin: 0.4rem 0 0; }
.batch-quota-admin .qa-table {
  width: 100%; border-collapse: collapse; font-size: var(--fs-sm);
}
.batch-quota-admin .qa-table th,
.batch-quota-admin .qa-table td {
  text-align: left; padding: 0.35rem 0.5rem;
  border-bottom: 1px solid var(--border);
}
.batch-quota-admin .qa-table th { color: var(--muted); font-weight: 600; }
.batch-quota-admin .qa-num { text-align: right; font-variant-numeric: tabular-nums; }
.batch-quota-admin .qa-table tr.qa-low td { background: #fff7ed; }
.batch-quota-admin .qa-tag {
  display: inline-block; margin-left: 0.25rem; padding: 0.05rem 0.4rem;
  font-size: 0.78em; border-radius: 999px;
  background: var(--border); color: var(--slate);
}
.batch-quota-admin-err { color: var(--danger); }
.batch-quota-admin input[type="date"] { padding: 0.25rem 0.4rem; font-size: var(--fs-sm); }
.batch-quota-admin .qa-tag.qa-exp { background: #eef2ff; color: #3730a3; }
.batch-quota-admin .qa-tag.qa-tag-exp { background: #fee2e2; color: #991b1b; }
.batch-quota-admin .qa-table tr.qa-expired td { opacity: 0.5; }

.batch-actions-inline {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.batch-actions-inline button {
  padding: 0.4rem 0.75rem;
  font-size: var(--fs-sm);
}

.batch-recent-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.65rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 0.4rem;
  background: #fcfcfd;
}

.batch-recent-meta {
  display: flex;
  gap: 0.65rem;
  align-items: center;
  flex-wrap: wrap;
  font-size: var(--fs-sm);
}

/* Per-row Force-refresh button inside the batch results table. Tiny,
   icon-only, only fires for one row at a time (cost: ~$3-5 vs ~$55-90
   for the whole-batch Force refresh). */
.batch-row-refresh-cell {
  text-align: center;
  padding: 0;
}
.batch-row-refresh-btn {
  font-size: 1rem;
  padding: 0.15rem 0.4rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--muted);
}
.batch-row-refresh-btn:hover:not(:disabled) {
  background: var(--accent-bg, #f3f4f6);
  color: var(--text);
}
.batch-row-refresh-btn:disabled {
  opacity: 0.6;
  cursor: wait;
}

/* Loading state — the ⟳ glyph spins while the per-row refresh is in
   flight, so the user has a clear "yes, it's running" signal during
   the ~10-20 sec wait. ``display: inline-block`` is required for the
   rotate transform to apply to the text/glyph. */
@keyframes batch-row-refresh-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
.batch-row-refresh-btn.refreshing {
  display: inline-block;
  animation: batch-row-refresh-spin 1s linear infinite;
  color: var(--accent);
  border-color: var(--accent);
}

/* Row-level dim while a per-row refresh is in flight — saves the user
   from having to scan back to find which small ⟳ is spinning. */
.batch-results-table tr.batch-row-refreshing {
  background: #fff7ed;
  opacity: 0.85;
  transition: background 120ms ease;
}

/* Brief green flash on the refreshed row when it lands. Confirms
   "yes, the data updated" — without this, an in-place row swap looks
   identical to no-op (same row, just different numbers in cells the
   user might not be staring at). The CSS animation fades from a soft
   green back to transparent over ~1.5s. */
@keyframes batch-row-refresh-success {
  0%   { background: #d1fae5; }
  50%  { background: #d1fae5; }
  100% { background: transparent; }
}
.batch-results-table tr.batch-row-refresh-success {
  animation: batch-row-refresh-success 1.5s ease-out;
}

/* Pager below the recent-batches list. Compact, centered, only renders
   when there are pages to navigate to (no clutter when history fits on
   one page). */
.batch-recent-pager {
  display: flex;
  gap: 0.65rem;
  align-items: center;
  justify-content: center;
  margin-top: 0.75rem;
  padding: 0.5rem;
  font-size: var(--fs-sm);
}

/* Per-address results table — shared by the live batch progress panel
   and the expandable Recent Batches rows. ``max-width: 100%`` keeps
   the table within its parent and lets ``overflow-x: auto`` add an
   inner horizontal scrollbar when columns exceed the parent's width
   (instead of expanding the row outside the website frame, which is
   what was happening once the new ⟳ per-row column landed). */
.batch-results-wrap {
  margin-top: 0.6rem;
  overflow-x: auto;
  max-width: 100%;
}

.batch-results-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.batch-results-table th,
.batch-results-table td {
  padding: 0.32rem 0.55rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.batch-results-table th {
  color: var(--muted);
  font-weight: 600;
}

.batch-results-table .batch-res-addr {
  white-space: normal;
  min-width: 190px;
}

.batch-ok { color: #15803d; font-weight: 600; }

/* On its own full-width line under the meta + action buttons.
   ``min-width: 0`` is the critical bit — without it, the flex item's
   default ``min-width: auto`` lets it grow to fit the inner table's
   intrinsic width, which then pushes the whole row past the website
   frame. With min-width:0, the inner ``.batch-results-wrap`` handles
   overflow with its own horizontal scrollbar instead. */
.batch-recent-details {
  flex-basis: 100%;
  min-width: 0;
}

.batch-recent-details summary {
  cursor: pointer;
  color: var(--accent);
  font-weight: 600;
  font-size: var(--fs-sm);
  padding: 0.2rem 0;
}

/* Batch Screenings history page — one collapsible section per batch. */
.screening-batch {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fcfcfd;
  margin-bottom: 0.6rem;
}
.screening-batch summary {
  cursor: pointer;
  padding: 0.6rem 0.8rem;
  font-size: var(--fs-sm);
  color: var(--text);
}
.screening-batch summary code { color: var(--muted); }
.screening-batch .batch-results-wrap {
  margin-top: 0;
  padding: 0 0.8rem 0.7rem;
}

.batch-status-tag {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid transparent;
}

.batch-status-tag--queued,
.batch-status-tag--running {
  background: #eff6ff;
  color: var(--accent);
  border-color: #bfdbfe;
}

.batch-status-tag--completed {
  background: #f0fdf4;
  color: #166534;
  border-color: #bbf7d0;
}

.batch-status-tag--cancelled {
  background: #f3f4f6;
  color: #6b7280;
  border-color: #d1d5db;
}

.batch-status-tag--failed,
.batch-status-tag--interrupted {
  background: #fef2f2;
  color: #b91c1c;
  border-color: #fecaca;
}

.batch-status-tag--stopped_quota_low {
  background: #fffbeb;
  color: #b45309;
  border-color: #fde68a;
}

.auth-panel {
  display: grid;
  place-items: center;
  min-height: 300px;
  background:
    radial-gradient(circle at top left, rgba(19, 76, 168, 0.08), transparent 30%),
    linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
}

.auth-card {
  width: min(480px, 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.6rem;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: var(--shadow-lg);
  text-align: center;
}

.auth-kicker {
  display: inline-block;
  margin-bottom: 0.65rem;
  color: var(--accent);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.auth-card h2 {
  margin: 0 0 0.55rem;
  font-size: clamp(1.35rem, 3vw, 1.8rem);
}

.auth-card p {
  margin: 0;
  color: var(--muted);
  line-height: 1.5;
}

.google-signin-slot {
  display: flex;
  justify-content: center;
  min-height: 44px;
  margin: 1.25rem 0 0.75rem;
}

.auth-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1rem;
  padding-bottom: 1rem;
}

.auth-status-copy {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.auth-status-label {
  color: var(--muted);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

form {
  display: grid;
  gap: 1rem;
}

.form-section {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.9rem 1rem;
  background: #fcfcfd;
}

.form-section h3 {
  margin: 0 0 0.7rem;
  font-size: var(--fs-base);
}

.fields-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem 1.25rem;
  align-items: end;
}

.fields-grid--2col {
  grid-template-columns: repeat(2, 1fr);
}

.field-full {
  grid-column: 1 / -1;
}

.form-actions {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  padding-top: 0.25rem;
}

.include-2b-field {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  justify-content: flex-end;
  padding-top: 0.5rem;
  font-size: var(--fs-lg);
  color: var(--muted);
}

.include-2b-field input[type="checkbox"] {
  margin: 0;
}

label {
  display: grid;
  gap: 0.4rem;
  color: var(--muted);
  font-size: var(--fs-base);
  font-weight: 500;
}

.req {
  color: #e53e3e;
  font-weight: 600;
}

.label-inline {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.tooltip-wrap {
  position: relative;
  display: inline-flex;
}

.info-tip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1rem;
  height: 1rem;
  border-radius: 999px;
  background: var(--accent-light);
  color: var(--accent);
  font-size: var(--fs-xs);
  cursor: help;
  border: 0;
  padding: 0;
}

.tooltip-box {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 280px;
  background: var(--text);
  color: #fff !important;
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.65rem;
  font-size: var(--fs-sm);
  line-height: 1.35;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 120ms ease, transform 120ms ease;
  z-index: 1200;
}

.tooltip-box * {
  color: #fff !important;
}

/* Tooltip copy must read as uniform body text regardless of the chip/header it
   lives in. Some containers (e.g. .prescreen-score-header) set uppercase + a
   3xl <strong> for their headline number; without these resets that styling
   leaked in and rendered the word "not" in the HeatMap-rank caveat huge and
   shouty. The chip label (.prescreen-market-tier-label) also sets
   white-space: nowrap, which inherits in and forced the multi-line HeatMap
   caveat onto one giant line that overflowed the 280px card — so reset that
   too, letting the copy wrap inside the box. The chip is also text-align:right,
   which leaked in and rendered the tooltip paragraph ragged-left; reset it to
   left so the copy reads as a normal body paragraph. !important mirrors the
   colour reset just above (same leak-defence). */
.tooltip-box,
.tooltip-box * {
  text-transform: none !important;
  letter-spacing: normal !important;
  white-space: normal !important;
  text-align: left !important;
}

.tooltip-box strong {
  font-size: inherit !important;
  font-weight: 600 !important;
  line-height: inherit !important;
  white-space: normal !important;
}

/* The HeatMap-rank chip is the rightmost item in the space-between score header,
   so its tooltip — anchored left:0 — ran 280px to the right, off the panel and
   the viewport edge. Anchor the rightmost score-header chip's tooltip to the
   right so the card opens leftward into the panel and stays fully visible. */
.prescreen-score-header > .prescreen-market-tier:last-child .tooltip-box {
  left: auto;
  right: 0;
}

.tooltip-box--list ul {
  margin: 0;
  padding-left: 1rem;
}

.tooltip-box--list li + li {
  margin-top: 0.25rem;
}

.tooltip-wrap:hover .tooltip-box,
.tooltip-wrap:focus-within .tooltip-box {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

input, button, select {
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  padding: 0.6rem 0.75rem;
  font-size: var(--fs-base);
  font-family: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input:focus, select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(19,76,168,0.1);
}

button {
  background: var(--accent);
  color: white;
  border: 0;
  cursor: pointer;
  font-weight: 500;
  transition: background 0.15s ease;
}

button:hover { background: var(--accent-hover); }
button:disabled { opacity: 0.6; cursor: not-allowed; }

.secondary-btn {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
}

.secondary-btn:hover {
  background: #f3f4f6;
}

.error { color: #b91c1c; min-height: 1.2rem; }
.progress-panel { margin-top: 1rem; }
.progress-panel h3 { margin: 0 0 0.5rem 0; font-size: var(--fs-base); }
#progress-log {
  margin: 0;
  padding: 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #f9fafb;
  max-height: 240px;
  overflow: auto;
  white-space: pre-wrap;
  font-size: var(--fs-sm);
  line-height: 1.4;
  font-family: var(--font-mono);
}

.prescreening-wrap {
  margin: 0.9rem 0;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 1rem 1.25rem;
  background: var(--surface);
}

.prescreening-wrap h3 {
  margin: 0 0 0.75rem;
  font-size: var(--fs-base);
}

.prescreening-wrap h4 {
  margin: 0 0 0.65rem;
  font-size: var(--fs-base);
}

/* Push-to-pipeline action at the bottom of the scorecard. */
.prescreen-pipeline-row {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
}
.prescreen-pipeline-help {
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.4;
}
.prescreen-pipeline-wrap .underwriting-save-status { margin: 0.5rem 0 0; }

.prescreening-head {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.75rem;
}

.prescreening-head h3 {
  margin: 0;
}

.tooltip-box--wide {
  width: min(360px, 86vw);
}

/* Inline info mark next to "Buyer IRR" / "Yield on Cost" labels.
   Pairs with .tooltip-wrap to surface a hover/focus tooltip
   explaining the metric's assumptions or formula. */
.offer-info-mark {
  display: inline-block;
  margin-left: 0.25rem;
  width: 1.05em;
  height: 1.05em;
  line-height: 1em;
  text-align: center;
  border-radius: 50%;
  background: #e2e8f0;
  color: #475569;
  font-size: 0.78em;
  font-weight: 700;
  cursor: help;
  vertical-align: text-top;
}
.tooltip-wrap:hover .offer-info-mark,
.tooltip-wrap:focus-within .offer-info-mark {
  background: #cbd5e1;
  color: #1e293b;
}

/* "Solve max offer at: [dropdown]" row inside the offer actions. */
.offer-price-mode-row {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-right: 0.75rem;
  font-size: var(--fs-sm);
}

.offer-price-mode-row select {
  padding: 0.35rem 0.55rem;
  font-size: var(--fs-sm);
}

.prescreen-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
}

.prescreen-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.95rem 1rem;
  background: #fcfcfd;
}

.prescreen-card--pass {
  border-color: #bbf7d0;
  background: #f0fdf4;
}

.prescreen-card--fail {
  border-color: #fecaca;
  background: #fef2f2;
}

.prescreen-card--empty {
  grid-column: 1 / -1;
  color: var(--muted);
}

.prescreen-card__label {
  display: block;
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.prescreen-card__value {
  display: block;
  margin-top: 0.35rem;
  font-size: var(--fs-lg);
  font-family: var(--font-display);
}

.prescreen-card__meta {
  margin-top: 0.45rem;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.4;
}

.prescreen-map-layout {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(240px, 0.85fr);
  gap: 1rem;
  align-items: stretch;
}

#prescreen-map {
  min-height: 430px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #eef2f7;
}

.prescreen-map-empty {
  display: grid;
  min-height: 430px;
  place-items: center;
  color: var(--muted);
}

.prescreen-map-side {
  display: grid;
  align-content: start;
  gap: 0.85rem;
}

.prescreen-map-legend,
.prescreen-map-badges {
  display: grid;
  gap: 0.7rem;
}

.prescreen-map-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 0.7rem;
}

.prescreen-legend-item {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.prescreen-legend-swatch {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05rem;
  height: 1.05rem;
  border: 1px solid color-mix(in srgb, var(--layer-color) 55%, #ffffff);
  border-radius: 50%;
  background: color-mix(in srgb, var(--layer-color) 16%, #ffffff);
  color: var(--layer-color);
  flex: 0 0 auto;
  font-size: var(--fs-2xs);
  font-weight: 800;
  line-height: 1;
}

.prescreen-legend-swatch--center {
  border-color: transparent;
  background: transparent;
  color: #111827;
  font-size: var(--fs-base);
}

.prescreen-legend-swatch--threshold {
  border-radius: 4px;
}

.prescreen-map-section-group {
  display: grid;
  gap: 0.55rem;
}

.prescreen-map-section-group h4 {
  margin: 0.35rem 0 0.1rem;
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.prescreen-map-section {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.78rem 0.8rem 0.55rem;
  background: #fcfcfd;
  transition: border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease;
}

.prescreen-map-section.is-active {
  border-color: color-mix(in srgb, var(--layer-color) 58%, #ffffff);
  box-shadow: 0 8px 22px color-mix(in srgb, var(--layer-color) 14%, transparent);
  transform: translateY(-1px);
}

.prescreen-map-section--threshold {
  background: linear-gradient(180deg, #fffaf7 0%, #ffffff 100%);
}

.prescreen-map-section__main {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.75rem;
  align-items: start;
}

.prescreen-section-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.35rem;
  height: 2.35rem;
  border: 1px solid color-mix(in srgb, var(--layer-color) 34%, #ffffff);
  border-radius: 999px;
  background: color-mix(in srgb, var(--layer-color) 13%, #ffffff);
  color: color-mix(in srgb, var(--layer-color) 86%, #111827);
  cursor: default;
  font-size: var(--fs-base);
  font-weight: 900;
  line-height: 1;
  transition: background 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease;
}

.prescreen-section-icon:hover,
.prescreen-section-icon.is-active {
  border-color: var(--layer-color);
  background: color-mix(in srgb, var(--layer-color) 24%, #ffffff);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--layer-color) 12%, transparent);
  transform: scale(1.04);
}

.prescreen-section-icon--threshold {
  border-radius: 7px;
}

.prescreen-map-section__content {
  min-width: 0;
}

.prescreen-map-section__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.65rem;
}

.prescreen-map-section__head strong {
  color: var(--text);
  font-size: var(--fs-base);
  line-height: 1.22;
}

.prescreen-map-badge__info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
  border: 0;
  border-radius: 999px;
  padding: 0;
  background: var(--accent-light);
  color: var(--accent);
  cursor: pointer;
  font-size: var(--fs-xs);
  font-weight: 700;
}

.prescreen-map-section__metric {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.55rem;
  margin-top: 0.35rem;
}

.prescreen-map-section__raw {
  display: inline-flex;
  align-items: center;
  min-width: 0;
  gap: 0.32rem;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.25;
}

.prescreen-map-section__score {
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--fs-base);
  font-weight: 800;
  line-height: 1.1;
}

.prescreen-map-section__meta {
  margin-top: 0.38rem;
  color: var(--muted);
  font-size: var(--fs-xs);
  line-height: 1.35;
}

.prescreen-map-section__expand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  width: 100%;
  margin-top: 0.6rem;
  border: 0;
  border-top: 1px solid var(--border);
  padding: 0.48rem 0 0;
  background: transparent;
  color: color-mix(in srgb, var(--layer-color) 78%, var(--muted));
  cursor: pointer;
  font-size: var(--fs-xs);
  font-weight: 800;
}

.prescreen-map-section__expand:hover {
  color: var(--layer-color);
}

.prescreen-map-badge__places {
  margin-top: 0.45rem;
  border-top: 1px dashed var(--border);
  padding-top: 0.55rem;
}

.prescreen-map-badge__places ul {
  display: grid;
  gap: 0.45rem;
  max-height: 180px;
  overflow: auto;
  margin: 0;
  padding-left: 1rem;
}

.prescreen-map-badge__places p {
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.prescreen-map-badge__places li {
  color: var(--text);
  font-size: var(--fs-sm);
  line-height: 1.35;
}

.prescreen-map-badge__places li strong {
  display: inline;
  margin: 0;
  font-size: var(--fs-sm);
}

.prescreen-map-badge__places li span {
  display: inline;
  color: var(--muted);
  font-size: var(--fs-xs);
}

.prescreen-map-hard-filters {
  margin-top: 1rem;
  border-top: 1px solid var(--border);
  padding-top: 0.9rem;
}

.prescreen-map-count-icon {
  background: transparent;
  border: 0;
}

.prescreen-map-count-icon span {
  display: grid;
  gap: 0.04rem;
  max-width: 126px;
  overflow: hidden;
  border: 1px solid var(--layer-color);
  border-radius: 8px;
  padding: 0.22rem 0.42rem;
  /* lower opacity so the map underneath is still readable */
  background: rgba(255, 255, 255, 0.58);
  backdrop-filter: blur(1px);
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.14);
  color: var(--text);
  text-align: center;
  line-height: 1.08;
  transition: box-shadow 0.16s ease, transform 0.16s ease, background 0.16s ease;
}

/* on hover / when the user is interacting, raise opacity so the text is fully readable */
.prescreen-map-count-icon:hover span,
.prescreen-map-count-icon.is-highlighted span {
  background: rgba(255, 255, 255, 0.94);
}

.prescreen-map-count-icon strong,
.prescreen-map-count-icon em {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.prescreen-map-count-icon strong {
  color: var(--text);
  font-size: var(--fs-2xs);
  font-style: normal;
  font-weight: 900;
}

.prescreen-map-count-icon em {
  color: var(--muted);
  font-size: var(--fs-2xs);
  font-style: normal;
  font-weight: 800;
}

.prescreen-map-count-icon.is-highlighted span {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--layer-color) 16%, transparent), var(--shadow-lg);
  transform: translateY(-1px);
}

.prescreen-map-place-icon {
  background: transparent;
  border: 0;
}

.prescreen-map-place-icon span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 0.85rem;
  height: 0.85rem;
  border: 2px solid #ffffff;
  border-radius: 999px;
  background: var(--layer-color);
  box-shadow: 0 1px 4px rgba(17, 24, 39, 0.28);
  color: #ffffff;
  line-height: 1;
  transition: box-shadow 0.16s ease, transform 0.16s ease;
}

.prescreen-map-place-icon--threshold span {
  border-radius: 5px;
}

.prescreen-map-place-icon.is-highlighted span {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--layer-color) 20%, transparent), 0 3px 10px rgba(17, 24, 39, 0.3);
  transform: scale(1.25);
}

.prescreen-map-center-icon {
  background: transparent;
  border: 0;
}

.prescreen-map-center-icon span {
  display: block;
  width: 1.8rem;
  height: 1.8rem;
  filter: drop-shadow(0 2px 4px rgba(17, 24, 39, 0.28));
  font-size: var(--fs-2xl);
  line-height: 1;
  text-align: center;
}

/* Overview hazard cell — compact 4-up grid of risk badges */
.prescreen-cell-label {
  display: block;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-bottom: 0.4rem;
}

.prescreen-hazard-summary,
.prescreen-oz-summary {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.7rem;
  background: #fcfcfd;
  height: 100%;
}

.prescreen-hazard-items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: auto auto;
  column-gap: 1.2rem;
  row-gap: 0.3rem;
  justify-content: start;
}

.prescreen-hazard-items li {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.prescreen-hazard-name {
  flex: 0 0 auto;
  min-width: 4.5rem;
  color: var(--muted);
  font-weight: 500;
  font-size: var(--fs-sm);
}

.prescreen-hazard-badge {
  font-weight: 700;
  font-size: var(--fs-sm);
  padding: 0.05rem 0.45rem;
  border-radius: 4px;
  border: 1px solid transparent;
  letter-spacing: 0.03em;
}

.prescreen-hazard-badge--go {
  background: #f0fdf4;
  color: #166534;
  border-color: #bbf7d0;
}

.prescreen-hazard-badge--caution {
  background: #fffbeb;
  color: #b45309;
  border-color: #fde68a;
}

.prescreen-hazard-badge--extreme-caution {
  background: #fef2f2;
  color: #b91c1c;
  border-color: #fecaca;
}

.prescreen-hazard-badge--unknown {
  background: #f3f4f6;
  color: #6b7280;
  border-color: #d1d5db;
}

/* OZ summary box — colored container, big YES/NO/UNKNOWN word */
.prescreen-oz-summary {
  align-items: flex-start;
}

.prescreen-oz-summary--go {
  background: #f0fdf4;
  border-color: #bbf7d0;
}

.prescreen-oz-summary--caution {
  background: #fffbeb;
  border-color: #fde68a;
}

.prescreen-oz-summary--unknown {
  background: #f3f4f6;
  border-color: #d1d5db;
}

.prescreen-oz-summary strong {
  font-size: var(--fs-2xl);
  font-weight: 800;
  letter-spacing: 0.04em;
  margin-top: 0.1rem;
}

.prescreen-oz-summary--go strong { color: #166534; }
.prescreen-oz-summary--caution strong { color: #b45309; }
.prescreen-oz-summary--unknown strong { color: #6b7280; }

/* Governing land-use jurisdiction chip — who actually sets zoning /
   parking / impact fees (incorporated city vs unincorporated county).
   Non-scoring; amber mirrors the OZ "caution" palette for county deals. */
.prescreen-jurisdiction-chip {
  display: inline-flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0 0 0.65rem;
  padding: 0.3rem 0.62rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  line-height: 1.3;
}
.prescreen-jurisdiction-chip .prescreen-jurisdiction-label { color: var(--muted); }
.prescreen-jurisdiction-chip .prescreen-jurisdiction-hint {
  flex-basis: 100%;
  color: var(--muted);
  font-size: var(--fs-xs);
}
.prescreen-jurisdiction-chip--city {
  background: #f8fafc;
  border-color: #e2e8f0;
}
.prescreen-jurisdiction-chip--city strong { color: #334155; }
.prescreen-jurisdiction-chip--county {
  background: #fffbeb;
  border-color: #fde68a;
}
.prescreen-jurisdiction-chip--county strong { color: #b45309; }

.prescreen-decision-panel {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  gap: 0.65rem;
  align-items: stretch;
}

.prescreen-final-decision {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.65rem 0.8rem;
  background: #fcfcfd;
}

.prescreen-final-decision span,
.prescreen-final-decision small {
  display: block;
  color: var(--muted);
  font-size: var(--fs-xs);
}

.prescreen-final-decision strong {
  display: block;
  margin: 0.25rem 0;
  font-size: var(--fs-xl);
}

.prescreen-score-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}

.prescreen-score-header > div {
  display: flex;
  flex-direction: column;
}

.prescreen-score-header > div:first-child {
  flex-shrink: 0;
}

.prescreen-score-header span {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.prescreen-score-header strong {
  font-size: var(--fs-3xl);
  white-space: nowrap;
  line-height: 1.1;
}

.prescreen-market-tier {
  align-items: flex-end;
  text-align: right;
  padding: 0.5rem 0.7rem;
  border: 1px solid transparent;
  border-radius: 6px;
}

.prescreen-market-tier--go {
  background: #f0fdf4;
  border-color: #bbf7d0;
}

.prescreen-market-tier--caution {
  background: #fffbeb;
  border-color: #fde68a;
}

.prescreen-market-tier--extreme-caution {
  background: #fef2f2;
  border-color: #fecaca;
}

.prescreen-market-tier--unknown {
  background: #f3f4f6;
  border-color: #d1d5db;
}

.prescreen-market-tier-label {
  display: inline-flex !important;
  align-items: center;
  gap: 0.3rem;
  white-space: nowrap;
}

/* HeatMap-rank chip label is a link to the HeatMap dashboard (new tab). Inherit
   the chip's text colour so it reads as part of the chip, not a stock blue link. */
.heatmap-rank-link {
  color: inherit;
  text-decoration: none;
}

.heatmap-rank-link:hover,
.heatmap-rank-link:focus-visible {
  text-decoration: underline;
}

.prescreen-market-tier small {
  display: block;
  margin-top: 0.3rem;
  color: var(--muted);
  font-size: var(--fs-xs);
}

.prescreen-factor-summary {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: auto auto;
  grid-template-rows: repeat(4, auto);
  grid-auto-flow: column;
  column-gap: 1.5rem;
  row-gap: 0.28rem;
  justify-content: start;
  font-size: var(--fs-sm);
}

.prescreen-factor-summary li {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.prescreen-factor-name {
  flex: 0 0 auto;
  min-width: 11rem;
  color: var(--muted);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}

.prescreen-factor-score {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: var(--fs-base);
  color: var(--text);
}

.prescreen-score-bar {
  position: relative;
  height: 14px;
  border-radius: 8px;
  background: linear-gradient(90deg, #fecaca 0%, #fde68a 50%, #bbf7d0 100%);
}

.prescreen-score-bar-marker {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 3px;
  background: #1f2937;
  border-radius: 1.5px;
  transform: translateX(-50%);
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
}

.prescreen-score-bar-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 0.4rem;
  color: var(--muted);
  font-size: var(--fs-2xs);
}

/* Environmental Adjusted Score — additive block under the score bar.
   Total Score stays the positive sum; this shows the hazard penalty
   and the separate Adjusted Score (may go negative). */
.prescreen-adjusted {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.6rem;
  margin-top: 0.6rem;
  padding-top: 0.55rem;
  border-top: 1px dashed var(--border);
}

.prescreen-adjusted-row {
  display: flex;
  flex-direction: column;
}

.prescreen-adjusted-row--right {
  text-align: right;
}

.prescreen-final-decision .prescreen-adjusted-penalty {
  color: #b91c1c;
}

/* OZ bonus (+25) line in the adjusted-score breakdown — paired with
   the penalty styling; green for "this helps you" vs red penalty. */
.prescreen-final-decision .prescreen-adjusted-bonus {
  color: #047857;
}

.prescreen-final-decision .prescreen-adjusted-value {
  font-size: var(--fs-2xl);
}

.prescreen-final-decision .prescreen-adjusted-value--negative {
  color: #b91c1c;
}

.prescreen-decision-detail {
  display: grid;
  gap: 0.75rem;
  height: 100%;
}

.prescreen-reason-block {
  height: 100%;
  width: fit-content;
  justify-self: start;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.65rem;
  background: #fcfcfd;
}

.prescreen-reason-block > span {
  display: block;
  margin-bottom: 0.45rem;
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.prescreen-decision-reasons {
  margin: 0;
  padding-left: 1.1rem;
  line-height: 1.45;
}

.prescreen-decision-reasons li + li {
  margin-top: 0.35rem;
}

.prescreen-decision--good,
.prescreen-decision--pass {
  color: #166534;
}

.prescreen-decision--review {
  color: #b45309;
}

.prescreen-decision--reject {
  color: #b91c1c;
}

.prescreen-warning-list {
  margin: 0;
  padding-left: 1.25rem;
  color: var(--text);
}

.prescreen-warning-list li + li {
  margin-top: 0.4rem;
}

.dashboard-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}

.dashboard-head h2 {
  flex: 1;
  min-width: 0;          /* let long addresses wrap instead of overflowing */
  word-break: break-word;
}

.dashboard-actions {
  display: flex;
  gap: 0.6rem;
  flex-shrink: 0;
}

.hotel-info-wrap {
  margin: 0.9rem 0;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 1rem 1.25rem;
  background: var(--surface);
}

.hotel-info-wrap h3 {
  margin: 0 0 0.55rem 0;
  font-size: var(--fs-base);
}

.hotel-info-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.55rem;
}

.hotel-info-head h3 {
  margin: 0;
}

.hotel-info-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.5rem 1.5rem;
}

.hotel-info-sections {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem;
}

.hotel-info-subsection {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.75rem;
  background: #fcfcfd;
}

.hotel-info-subsection h4 {
  margin: 0 0 0.55rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.hotel-info-wrap a {
  color: var(--accent);
  text-decoration: none;
}

.hotel-info-head .btn-link {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
}

.hotel-info-head .btn-link:hover {
  background: #f3f4f6;
}

.hotel-info-wrap a:hover {
  text-decoration: underline;
}

.btn-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  border: none;
  padding: 0.5rem 0.9rem;
  font-size: var(--fs-base);
  font-weight: 500;
  text-decoration: none;
  background: var(--accent);
  color: #fff;
  font-family: inherit;
  transition: background 0.15s ease;
}

.btn-link:hover {
  background: var(--accent-hover);
}

.btn-link.unavailable {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
}

.stats {
  margin: 1rem 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.75rem;
}

.stat-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1rem;
  background: var(--surface);
}

.stat-card span {
  display: block;
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.stat-card strong {
  font-size: var(--fs-xl);
  font-family: var(--font-display);
  margin-top: 0.25rem;
  display: block;
}

.stat-card .label-inline > span {
  display: inline;
}

.est-rent-section {
  margin: 1rem 0;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 1rem 1.25rem;
  background: var(--surface);
}

.est-rent-section h3 {
  margin: 0 0 0.5rem;
  font-size: var(--fs-base);
  color: var(--text);
}

.est-rent-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

.est-rent-head h3 {
  margin: 0;
}

.est-rent-control {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-width: 210px;
  margin-left: auto;
}

.est-rent-control .label-inline {
  justify-content: flex-start;
}

.est-rent-control select:disabled {
  opacity: 0.7;
  cursor: wait;
}

.est-rent-feedback-control .secondary-btn {
  width: 100%;
}

.est-rent-feedback-control {
  margin-left: -0.35rem;
}

/* --- rent range bar legend --- */
.rent-bar-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem 1rem;
  margin-bottom: 0.75rem;
  font-size: var(--fs-xs);
  color: var(--muted);
}

.rent-bar-legend span {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}

.legend-swatch--class {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--muted); opacity: 0.55;
}
.legend-swatch--range {
  width: 16px; height: 8px; border-radius: 2px;
  background: rgba(19, 76, 168, 0.22);
}
.legend-swatch--blended {
  width: 8px; height: 8px; border-radius: 50%;
  background: #f59e0b;
}
.legend-swatch--final {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 1.5px var(--surface), 0 0 0 3px var(--accent);
}

.est-rent-error {
  background: rgba(245, 158, 11, 0.12);
  border: 1px solid rgba(245, 158, 11, 0.4);
  border-radius: 6px;
  color: #b45309;
  font-size: var(--fs-sm);
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.5rem;
}

/* --- rent range bar component --- */
.est-rent-bars {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.rent-bar-group {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.75rem 1rem;
  background: var(--surface);
}

.rent-bar-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.rent-bar-title {
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.rent-bar-value {
  font-size: var(--fs-xl);
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--accent);
}

/* Large-room studio premium callout — shown under the Studio bar only when
   the +5% premium was applied, so the user knows the number isn't a
   standard-288-SF estimate. */
.rent-studio-premium-note {
  margin: 0.5rem 0 0;
  font-size: var(--fs-sm);
  line-height: 1.35;
  color: var(--accent);
  background: rgba(37, 99, 235, 0.08);
  border-left: 3px solid var(--accent);
  border-radius: 4px;
  padding: 0.4rem 0.6rem;
}

.rent-2b-note {
  margin: 0.5rem 0 0;
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.4;
}

.rent-2b-note--fallback {
  color: #b45309;
  font-style: italic;
}

/* Incremental "Pull 2-bed comps" control under the rent bars. Emphasized
   (filled) when the model infers the hotel has 2-bed units. */
.pull-2b-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.75rem;
  flex-wrap: wrap;
}
.pull-2b-btn {
  border: 1px solid var(--accent);
  background: #fff;
  color: var(--accent);
  border-radius: 6px;
  padding: 0.4rem 0.85rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
}
.pull-2b-btn:hover { background: rgba(37, 99, 235, 0.08); }
.pull-2b-btn:disabled { opacity: 0.6; cursor: default; }
.pull-2b-btn--emphasized {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 1px 4px rgba(37, 99, 235, 0.35);
}
.pull-2b-btn--emphasized:hover { background: var(--accent-hover); }
.pull-2b-hint { font-size: var(--fs-sm); color: var(--muted); }
.pull-2b-hint--alert { color: #b45309; font-weight: 600; }

/* Short-term / Airbnb rows in the Unit-Level table. Faint orange wash
   + italics so the user can tell at a glance which rows the rent
   estimator dropped. */
tr.row--short-term {
  background: rgba(251, 191, 36, 0.10);
  color: var(--muted);
  font-style: italic;
}
tr.row--short-term td {
  color: var(--muted);
}

/* Income-restricted / affordable-housing rows — same idea, but a
   distinct faint purple so the user can tell which filter caught the
   row. Age-restricted gets cyan. Tooltip explains the exclusion.
     orange (amber) → short-term
     purple         → income-restricted (affordable / LIHTC / Section 8)
     cyan           → age-restricted (55+ / senior / active adult)
   Combined-class rows blend into a gradient. */
tr.row--income-restricted {
  background: rgba(168, 85, 247, 0.10);
  color: var(--muted);
  font-style: italic;
}
tr.row--income-restricted td {
  color: var(--muted);
}
tr.row--age-restricted {
  background: rgba(14, 165, 233, 0.10);
  color: var(--muted);
  font-style: italic;
}
tr.row--age-restricted td {
  color: var(--muted);
}
tr.row--unlocatable {
  background: rgba(100, 116, 139, 0.10);
  color: var(--muted);
  font-style: italic;
}
tr.row--unlocatable td {
  color: var(--muted);
}
/* Two-class combos — slight gradients so users can see both filters
   fired. Three-class combos fall through to cascade order; the
   tooltip still lists every reason. */
tr.row--short-term.row--income-restricted {
  background: linear-gradient(
    90deg,
    rgba(251, 191, 36, 0.14) 0%,
    rgba(168, 85, 247, 0.14) 100%
  );
}
tr.row--short-term.row--age-restricted {
  background: linear-gradient(
    90deg,
    rgba(251, 191, 36, 0.14) 0%,
    rgba(14, 165, 233, 0.14) 100%
  );
}
tr.row--income-restricted.row--age-restricted {
  background: linear-gradient(
    90deg,
    rgba(168, 85, 247, 0.14) 0%,
    rgba(14, 165, 233, 0.14) 100%
  );
}

/* "Needs review" rows — restriction status could NOT be verified (incomplete
   listing data). Unlike the filters above, these rows are KEPT in the estimate,
   so the text stays full-strength (not muted/italic); a saturated-orange wash +
   left accent bar just flags them for a manual eyeball. */
tr.row--needs-review {
  background: rgba(249, 115, 22, 0.12);
  box-shadow: inset 3px 0 0 0 rgba(249, 115, 22, 0.85);
}
tr.row--needs-review td:first-child {
  position: relative;
}

/* --- Quick Underwriting Valuation --- */
.underwriting-intro {
  margin: 0 0 0.85rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.4;
}

.uw-scenarios {
  display: grid;
  gap: 0.85rem;
}

.uw-scenario-card {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 0.85rem 1rem;
  background: var(--surface);
  transition: box-shadow 150ms ease, border-color 150ms ease;
}

.uw-scenario-card--selected {
  border-left-width: 4px;
  box-shadow: 0 0 0 1px var(--accent), 0 4px 14px rgba(19, 76, 168, 0.10);
}

.uw-scenario-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 0.65rem;
}

.uw-scenario-select {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  background: var(--bg);
}
.uw-scenario-select input[type="radio"] {
  margin: 0;
  cursor: pointer;
}
.uw-scenario-card--selected .uw-scenario-select {
  background: var(--accent-light);
  color: var(--accent);
  border-color: var(--accent);
}

.uw-scenario-name {
  flex: 1;
  min-width: 0;
  padding: 0.35rem 0.55rem;
  font-size: var(--fs-base);
  font-weight: 700;
  font-family: var(--font-display);
  background: transparent;
  border: 1px dashed transparent;
  border-radius: var(--radius-sm);
  color: var(--text);
}
.uw-scenario-name:hover,
.uw-scenario-name:focus {
  border-color: var(--border);
  background: var(--bg);
  outline: none;
}

.uw-scenario-remove {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  padding: 0.25rem 0.55rem;
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
  cursor: pointer;
}
.uw-scenario-remove:hover {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: var(--danger-border);
}

.uw-scenario-inputs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.6rem 0.85rem;
}

.uw-scenario-inputs .uw-input-group {
  display: grid;
  gap: 0.35rem;
  min-width: 0;
}

.uw-scenario-inputs .uw-input-group-title {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}

.uw-scenario-inputs label {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.uw-scenario-inputs input[type="number"] {
  padding: 0.32rem 0.5rem;
  font-size: var(--fs-sm);
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  min-width: 0;
}

.uw-scenario-output {
  margin-top: 0.85rem;
  padding: 0.55rem 0.75rem;
  background: var(--accent-light);
  border: 1px solid rgba(19, 76, 168, 0.25);
  border-radius: var(--radius-sm);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
}

.uw-scenario-output .uw-out-cell {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.uw-scenario-output .uw-out-cell span {
  font-size: var(--fs-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.uw-scenario-output .uw-out-cell strong {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
/* Editable "Other income ($)" — matches the footer value type but with a dashed
   underline to signal it's editable (defaults to 5% of gross rent). */
.uw-scenario-output .uw-out-cell input.uw-oi-dollar {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  width: 9ch;
  max-width: 100%;
  border: none;
  border-bottom: 1px dashed rgba(19, 76, 168, 0.55);
  background: transparent;
  padding: 0;
  line-height: 1.2;
}
.uw-scenario-output .uw-out-cell input.uw-oi-dollar:focus {
  outline: none;
  border-bottom-color: var(--accent);
}
/* All scenario-output cells (Gross Annual / NOI / Valuation / Per unit)
   share one size — Valuation no longer scales up vs the others. */

.underwriting-launch {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
}

.underwriting-launch button {
  font-weight: 700;
}

.underwriting-launch-help {
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.4;
}

.underwriting-panel {
  margin-top: 1rem;
  padding: 1.1rem 1.25rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.underwriting-panel h3 {
  margin: 0 0 0.75rem;
  font-size: var(--fs-lg);
}

/* "Quick Underwriting" header row — h3 on the left, Sync button on
   the right. Mirrors the offer-subsection-head pattern used in the
   offer panel. */
.underwriting-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}
.underwriting-header h3 { margin: 0; }
.uw-sync-rents-btn {
  font-size: var(--fs-sm);
  white-space: nowrap;
}

.underwriting-inputs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

.underwriting-inputs fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.75rem 0.75rem;
  display: grid;
  gap: 0.5rem;
  min-width: 0;
}

.underwriting-inputs legend {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0 0.35rem;
}

.underwriting-inputs label {
  display: grid;
  gap: 0.25rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.underwriting-inputs input[type="number"] {
  width: 100%;
  padding: 0.4rem 0.55rem;
  font-size: var(--fs-base);
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
}

.underwriting-actions {
  margin-top: 0.9rem;
  display: flex;
  justify-content: flex-end;
}

.underwriting-output {
  margin-top: 1rem;
  display: grid;
  gap: 0.4rem;
}

.uw-out-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.45rem 0.65rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  font-size: var(--fs-base);
}

.uw-out-row span { color: var(--muted); }
.uw-out-row strong {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-lg);
}

.uw-out-row--highlight {
  background: var(--accent-light);
  border: 1px solid rgba(19, 76, 168, 0.25);
}

.uw-out-row--highlight strong {
  color: var(--accent);
  font-size: var(--fs-2xl);
}

.underwriting-formula {
  margin: 0.85rem 0 0;
  font-size: var(--fs-xs);
  color: var(--muted);
  text-align: right;
}
.underwriting-formula code {
  background: var(--bg);
  padding: 0.15rem 0.4rem;
  border-radius: 4px;
}

.underwriting-save-status {
  margin: 0.5rem 0 0;
  font-size: var(--fs-sm);
  min-height: 1.2rem;
  color: var(--muted);
}
.underwriting-save-status[data-kind="success"] { color: var(--success); }
.underwriting-save-status[data-kind="error"]   { color: var(--danger); }
.underwriting-save-status[data-kind="info"]    { color: var(--accent); }

/* --- Offer Price Calculation --- */
.offer-launch {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
}
.offer-launch button { font-weight: 700; }
.offer-launch-help {
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.4;
}

.offer-panel {
  margin-top: 1rem;
  padding: 1.1rem 1.25rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--surface);
}
.offer-panel h3 { margin: 0 0 0.75rem; font-size: var(--fs-lg); }
.offer-panel h4 {
  margin: 0 0 0.5rem;
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}
.offer-subhelp {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
  margin-left: 0.5rem;
}

.offer-subsection {
  margin-bottom: 1rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px dashed var(--border);
}
.offer-subsection:last-of-type { border-bottom: 0; padding-bottom: 0; }

.offer-subsection-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}
.offer-subsection-head h4 { margin: 0; }
.offer-sync-btn {
  padding: 0.3rem 0.7rem;
  font-size: var(--fs-xs);
}

.offer-save-row {
  margin-top: 1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
}
.offer-save-row .underwriting-save-status { margin: 0; }
/* Optional human-friendly label, inline at the head of the action row. */
.uw-save-name-field {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.uw-save-name-input {
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 500;
  min-width: 15rem;
}

/* ── LOI generation modal ─────────────────────────────────────── */
.loi-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.loi-modal.hidden { display: none; }
.loi-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  backdrop-filter: blur(2px);
}
.loi-modal-card {
  position: relative;
  width: 100%;
  max-width: 520px;
  background: var(--surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-height: 90vh;
}
.loi-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1.1rem;
  border-bottom: 1px solid var(--border);
}
.loi-modal-head h3 { margin: 0; font-size: var(--fs-lg); }
.loi-modal-close {
  background: transparent;
  border: 0;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
}
.loi-modal-close:hover { background: var(--bg); color: var(--text); }
.loi-modal-body {
  padding: 1rem 1.1rem;
  overflow-y: auto;
}
.loi-modal-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.6rem;
  padding: 0.75rem 1.1rem;
  border-top: 1px solid var(--border);
  background: var(--bg);
}
.loi-fields {
  display: grid;
  gap: 0.75rem;
}
.loi-fields > label {
  display: grid;
  gap: 0.25rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.loi-fields input[type="text"],
.loi-fields input[type="number"] {
  padding: 0.4rem 0.55rem;
  font-size: var(--fs-base);
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
}
.loi-help {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-weight: 400;
}
/* Price-guard note under the LOI purchase price (QA M-3): neutral when there's
   no computed offer to compare against, amber when the typed price differs
   from the last computed offer. */
.loi-price-guard { display: block; margin-top: 0.2rem; }
.loi-price-guard--warn { color: #b45309; font-weight: 600; }
.loi-checkbox-label {
  display: flex !important;
  flex-direction: row !important;
  align-items: flex-start !important;
  gap: 0.5rem !important;
  cursor: pointer;
  color: var(--text) !important;
}
.loi-checkbox-label input[type="checkbox"] {
  margin: 0.2rem 0 0 0;
  width: 1rem;
  height: 1rem;
  cursor: pointer;
  flex-shrink: 0;
}
.loi-status {
  margin: 0.85rem 0 0;
  min-height: 1.2em;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.loi-status[data-kind="error"]   { color: var(--danger); }
.loi-status[data-kind="success"] { color: var(--success); }
.loi-status[data-kind="info"]    { color: var(--accent); }

/* Footer holds 3–4 buttons at 520px — let it wrap instead of overflowing. */
.loi-modal-foot { flex-wrap: wrap; }

/* Recipient row — shared by the params and live-edit views. */
.loi-recipient {
  display: grid;
  gap: 0.25rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-top: 0.85rem;
}
.loi-recipient input,
.loi-fields input[type="email"] {
  padding: 0.4rem 0.55rem;
  font-size: var(--fs-base);
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
}

/* Live-edit preview — one editable field per LOI body section. */
.loi-edit-note {
  margin: 0 0 0.75rem;
  font-size: var(--fs-xs);
  color: var(--muted);
}
#loi-edit-blocks {
  display: grid;
  gap: 0.7rem;
}
.loi-edit-field {
  display: grid;
  gap: 0.25rem;
}
.loi-edit-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.loi-edit-label em {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
}
.loi-edit-text {
  width: 100%;
  box-sizing: border-box;
  padding: 0.45rem 0.55rem;
  font-size: var(--fs-sm);
  font-family: inherit;
  line-height: 1.4;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  background: var(--surface);
  resize: vertical;
}
.loi-edit-text:focus {
  outline: none;
  border-color: var(--accent);
}

/* Underwriting Notes modal — reuses .loi-modal frame. */
.uw-notes-help {
  margin: 0 0 0.6rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  line-height: 1.4;
}
.uw-notes-textarea {
  width: 100%;
  min-height: 12rem;
  padding: 0.6rem 0.7rem;
  font-size: var(--fs-base);
  font-family: var(--font-sans);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  background: var(--surface);
  resize: vertical;
}
.uw-notes-textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.offer-recap {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0.5rem 0.85rem;
}
.offer-recap > div { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.offer-recap span { font-size: var(--fs-xs); color: var(--muted); }
.offer-recap strong {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-base);
  color: var(--text);
}

.offer-inputs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.6rem 0.85rem;
}

/* Grouped underwriting-assumptions sections (2026-05-28). Each
   .offer-input-group wraps a small uppercase label + its inner
   .offer-inputs-grid, so related inputs (return targets / senior
   debt / seller finance / refi / growth / other costs) cluster
   visually instead of being a flat 16-input grid. */
.offer-input-group + .offer-input-group {
  margin-top: 0.9rem;
}
.offer-input-group-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--muted);
  text-transform: uppercase;
  padding-bottom: 0.3rem;
  margin-bottom: 0.4rem;
  border-bottom: 1px dashed var(--border);
}
.offer-inputs-grid label {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  min-width: 0;
}
.offer-inputs-grid input[type="number"],
.offer-inputs-grid input[type="text"] {
  padding: 0.32rem 0.5rem;
  font-size: var(--fs-sm);
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  min-width: 0;
}
/* <select> defaults to sizing to its widest option's text, which can
   overflow the 1fr grid cell when option labels are long (e.g. the
   Refi financing type dropdown). Force it to honor the grid column
   like the inputs do — overflow text gets clipped/ellipsised by the
   browser, full text still visible when the picker opens. */
.offer-inputs-grid select {
  padding: 0.32rem 0.5rem;
  font-size: var(--fs-sm);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  background: #fff;
  min-width: 0;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
}

.offer-toggle-row {
  margin-top: 0.7rem;
  font-size: var(--fs-sm);
  color: var(--text);
}
.offer-toggle-row label {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.45rem;
  cursor: pointer;
}
.offer-toggle-row input[type="checkbox"] {
  margin: 0;
  width: 1rem;
  height: 1rem;
  cursor: pointer;
}

.offer-refi-routes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  margin-bottom: 0.6rem;
  font-size: var(--fs-sm);
  color: var(--text);
}
.offer-refi-routes label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  cursor: pointer;
}
.offer-refi-routes input {
  width: 1rem;
  height: 1rem;
  margin: 0;
}
.offer-refi-route-table {
  display: grid;
  gap: 0.45rem;
}
.offer-refi-route-row {
  display: grid;
  grid-template-columns: minmax(150px, 1.1fr) repeat(5, minmax(68px, 0.72fr));
  gap: 0.45rem 0.7rem;
  align-items: end;
  padding: 0.55rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}
.offer-refi-route-name {
  display: grid;
  gap: 0.12rem;
  min-width: 0;
}
.offer-refi-route-name label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-weight: 700;
  color: var(--text);
}
.offer-refi-route-name span {
  color: var(--muted);
  font-size: var(--fs-xs);
  line-height: 1.25;
}
.offer-refi-route-row > label {
  display: grid;
  gap: 0.2rem;
  color: var(--muted);
  font-size: var(--fs-xs);
  min-width: 0;
}
.offer-refi-route-row input[type="number"] {
  padding: 0.32rem 0.5rem;
  font-size: var(--fs-sm);
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  min-width: 0;
}
@media (max-width: 760px) {
  .offer-refi-route-row {
    grid-template-columns: 1fr;
  }
}

.offer-actions {
  margin: 0.9rem 0 0.5rem;
  display: flex;
  justify-content: flex-end;
}

/* ── Calc-button feedback (Recalculate All · Calculate Offer Price · Solve · Compute)
   A click can be instant or a server round-trip; without a cue the user can't tell
   it registered vs. is still computing. `.is-calculating` = a visible "working"
   state (pulse + spinner + progress cursor) held while the work runs; `.calc-done`
   = a brief success flash when it lands. Generic so it applies to any wrapped
   button. ───────────────────────────────────────────────────────────────────── */
button.is-calculating {
  cursor: progress;
  animation: calc-busy-pulse 0.9s ease-in-out infinite;
}
button.is-calculating::after {
  content: "";
  display: inline-block;
  width: 0.72em;
  height: 0.72em;
  margin-left: 0.5em;
  vertical-align: -0.08em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: calc-busy-spin 0.6s linear infinite;
}
button.calc-done {
  animation: calc-done-flash 0.7s ease-out;
}
@keyframes calc-busy-spin { to { transform: rotate(360deg); } }
@keyframes calc-busy-pulse { 50% { opacity: 0.62; } }
@keyframes calc-done-flash {
  0%   { box-shadow: 0 0 0 0 rgba(34, 160, 90, 0.55); }
  100% { box-shadow: 0 0 0 9px rgba(34, 160, 90, 0); }
}
@media (prefers-reduced-motion: reduce) {
  button.is-calculating,
  button.is-calculating::after,
  button.calc-done { animation: none; }
  button.is-calculating { opacity: 0.7; }
}

.offer-or-divider {
  margin: 0.4rem 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--muted);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.offer-or-divider::before,
.offer-or-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.offer-recompute-row {
  margin: 0.4rem 0 1rem;
  display: flex;
  align-items: end;
  gap: 0.75rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.offer-recompute-label {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  flex: 1 1 220px;
  min-width: 0;
}
.offer-recompute-label input {
  padding: 0.32rem 0.5rem;
  font-size: var(--fs-sm);
  font-family: var(--font-mono);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
}

.offer-output {
  display: grid;
  gap: 1.1rem;
}

.offer-route-comparison {
  overflow-x: auto;
  max-width: 100%;
  min-width: 0;
}
.offer-route-matrix-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
}
.offer-route-matrix {
  display: grid;
  grid-template-columns: minmax(12.5rem, 0.8fr) repeat(var(--offer-route-count, 2), minmax(0, 1fr));
  font-size: var(--fs-xs);
  min-width: 0;
}
.offer-route-matrix-head,
.offer-route-matrix-label,
.offer-route-matrix-value,
.offer-route-matrix-section {
  box-sizing: border-box;
  min-width: 0;
  border-bottom: 1px solid var(--border);
  padding: 0.38rem 0.45rem;
}
.offer-route-matrix-head {
  background: var(--bg-hover);
  color: var(--text);
  font-weight: 700;
  overflow: hidden;
}
.offer-route-matrix-metric {
  text-align: left;
}
.offer-route-matrix-route {
  text-align: right;
}
.offer-route-matrix-label {
  color: var(--muted);
  font-weight: 600;
  line-height: 1.22;
  overflow-wrap: anywhere;
  white-space: normal;
}
.offer-route-matrix-value {
  color: var(--text);
  text-align: right;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.offer-route-matrix-section {
  grid-column: 1 / -1;
  background: var(--bg-hover);
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: left;
  border-top: 2px solid var(--accent);
}
.offer-route-matrix-section:last-child,
.offer-route-matrix-label:last-child,
.offer-route-matrix-value:last-child {
  border-bottom: 0;
}
.offer-route-matrix-selected {
  background: var(--accent-light);
}
.offer-route-matrix-use {
  display: inline-flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.3rem;
  max-width: 100%;
  white-space: nowrap;
}
.offer-route-matrix-use input {
  margin: 0;
}
.offer-route-matrix-use span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.offer-route-matrix-head small {
  display: block;
  margin-top: 0.12rem;
  color: var(--muted);
  font-weight: 400;
  line-height: 1.2;
  white-space: normal;
}
@media (max-width: 760px) {
  .offer-route-matrix-wrap {
    min-width: min(620px, calc(100vw - 2rem));
  }
  .offer-route-matrix {
    grid-template-columns: minmax(11rem, 0.8fr) repeat(var(--offer-route-count, 2), minmax(8.5rem, 1fr));
  }
}

/* Grouped output sections — "Returns", "Property economics", "Capital stack".
   Group label sits on a thin border-bottom; rows inside the group are
   separated by hairlines, no row-level background fill. The result is a
   much calmer scan compared with the old striped look. */
.offer-out-group {
  display: grid;
  gap: 0;
}
.offer-out-group-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0 0.15rem 0.35rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.1rem;
}
.offer-out-group .offer-out-row {
  background: transparent;
  border-radius: 0;
  padding: 0.5rem 0.15rem;
}
.offer-out-group .offer-out-row:not(:last-child) {
  border-bottom: 1px solid var(--border);
}
/* Returns group gets accent-colored values to draw the eye to the
   punchline metrics (IRR / YoC / Cap Delta). */
.offer-out-group--returns .offer-out-row strong { color: var(--accent); }

/* Subtle inline help text (e.g. "DSCR cap", "YoC − cap rate"). */
.offer-out-row .offer-subhelp {
  font-size: var(--fs-xs);
}

/* "Cash Needed to Close" — soft callout at the end of the capital stack. */
.offer-out-group .offer-out-row--emphasized {
  margin-top: 0.25rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--accent);
}
.offer-out-row--emphasized strong { color: var(--accent); }

/* Cash-in-refi warning row — only rendered when bridge + seller finance
   payoff exceeds refi capacity at Y2 (sponsor must contribute equity).
   Amber tint to signal "heads up, but not a deal-killer". */
.offer-out-row--warning {
  background: #fff4e0;
  border: 1px solid #f0c47a;
}
.offer-out-row--warning strong { color: #b35900; }

/* ── Construction Budget Calculator (offer panel) ───────────────── */
/* Lives inside .offer-subsection.construction-budget — a compact
   dashboard that shows live cost breakdown computed via JS-ported
   expert-input model. See computeConstructionCost in rent_parser.js. */
.construction-budget .cc-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.85rem;
  align-items: center;
  margin: 0.4rem 0 0.6rem;
}
.construction-budget .cc-chips label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.construction-budget .cc-chips select,
.construction-budget .cc-chips input[type="text"] {
  font-size: var(--fs-sm);
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  min-width: 0;
  max-width: 160px;
}
.cc-strict-badge {
  display: inline-block;
  font-size: var(--fs-xs);
  background: #fff4e0;
  color: #b35900;
  padding: 0.15rem 0.45rem;
  border-radius: var(--radius-sm);
  border: 1px solid #f0c47a;
}
.construction-budget .cc-toggles {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  margin: 0.3rem 0 0.6rem;
}
.cc-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--fs-sm);
  cursor: pointer;
}
.cc-toggle .offer-subhelp { font-size: var(--fs-xs); margin-left: 0.25rem; }
.cc-wd-subinput {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-left: 1.5rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.cc-wd-subinput input[type="number"] {
  width: 5.5rem;
  padding: 0.2rem 0.35rem;
  font-size: var(--fs-sm);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}
.cc-mini-btn {
  font-size: var(--fs-xs);
  padding: 0.15rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--muted);
  cursor: pointer;
}
.cc-mini-btn:hover { background: var(--bg-hover); color: var(--text); }

.cc-breakdown {
  display: grid;
  gap: 0.2rem;
  margin: 0.5rem 0;
}
.cc-row {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.5rem;
  padding: 0.3rem 0.5rem;
  font-size: var(--fs-sm);
  border-radius: var(--radius-sm);
  background: var(--bg);
}
.cc-row .cc-row-per-unit, .cc-row .cc-row-total {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.cc-row .cc-row-per-unit { color: var(--muted); }
.cc-row-sub { color: var(--muted); font-size: var(--fs-xs); margin-left: 0.3rem; }
.cc-row--adder .cc-row-label { color: var(--muted); }
.cc-row--headline {
  margin-top: 0.25rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--accent);
  font-weight: 600;
}
.cc-row--headline .cc-row-total { color: var(--accent); }
.cc-row-blended { color: var(--muted); font-size: var(--fs-xs); font-weight: 400; }

.cc-totals-grid {
  margin-top: 0.6rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--border);
}

.offer-out-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 0.45rem 0.65rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  font-size: var(--fs-base);
}
.offer-out-row span { color: var(--muted); }
.offer-out-row strong {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-lg);
}
.offer-out-row--primary {
  background: var(--accent-light);
  border: 1px solid rgba(19, 76, 168, 0.25);
  padding: 0.65rem 0.85rem;
}
.offer-out-row--primary strong {
  color: var(--accent);
  font-size: var(--fs-2xl);
}

@media (max-width: 760px) {
  .offer-recap { grid-template-columns: repeat(2, 1fr); }
  .offer-inputs-grid { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
  .uw-scenario-inputs { grid-template-columns: 1fr; }
}

.rent-bar-track {
  position: relative;
  height: 28px;
  margin-top: 2.2rem;
  background: var(--bg);
  border-radius: 6px;
  border: 1px solid var(--border);
  overflow: visible;
}

.rent-bar-track-inner {
  position: relative;
  width: calc(100% - 16px);
  height: 100%;
  margin: 0 8px;
}

/* class avg rent dot (small grey) */
.rent-bar-dot--class {
  position: absolute;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(107, 114, 128, 0.55);
  border: 1.5px solid var(--surface);
  transform: translate(-50%, -50%);
  cursor: pointer;
  z-index: 2;
}

/* highlighted range band (estYb to estReno) — sits below all dots */
.rent-bar-range {
  position: absolute;
  top: 4px;
  height: 20px;
  background: rgba(19, 76, 168, 0.22);
  border-radius: 4px;
  z-index: 0;
  cursor: pointer;
  transition: background 120ms ease;
}
.rent-bar-range:hover { background: rgba(19, 76, 168, 0.35); }

/* blended est rent dot (small orange) */
.rent-bar-dot--blended {
  position: absolute;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #f59e0b;
  border: 1.5px solid var(--surface);
  transform: translate(-50%, -50%);
  cursor: pointer;
  z-index: 4;
}

/* final est rent dot (large, prominent) */
.rent-bar-dot--final {
  position: absolute;
  top: 50%;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--accent);
  border: 2.5px solid var(--surface);
  box-shadow: 0 0 0 2.5px var(--accent);
  transform: translate(-50%, -50%);
  cursor: pointer;
  z-index: 5;
}

/* floating value label above the final dot */
.rent-bar-val-label {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 700;
  padding: 0.25rem 0.6rem;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.12);
  white-space: nowrap;
  pointer-events: none;
  z-index: 6;
}
.rent-bar-val-label::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--surface);
}

/* hide the right-aligned value when inline label is active */
.rent-bar-value--inline { display: none; }

/* hover tooltip */
.rent-bar-tip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  background: var(--text);
  color: #fff;
  font-size: var(--fs-xs);
  line-height: 1.35;
  padding: 0.3rem 0.5rem;
  border-radius: 6px;
  box-shadow: var(--shadow);
  opacity: 0;
  visibility: hidden;
  transition: opacity 120ms ease;
  pointer-events: none;
  z-index: 30;
}

.rent-bar-tip--left { left: 0; transform: none; }
.rent-bar-tip--right { left: auto; right: 0; transform: none; }

/* wider tooltip for final dot breakdown table */
.rent-bar-tip--wide {
  white-space: normal;
  width: 600px;
  line-height: 1.4;
}

.rent-bar-dot--class:hover .rent-bar-tip,
.rent-bar-dot--final:hover .rent-bar-tip,
.rent-bar-dot--blended:hover .rent-bar-tip,
.rent-bar-range:hover .rent-bar-tip {
  opacity: 1;
  visibility: visible;
}

/* raise hovered non-final elements above the final dot's stacking context
   so their tooltips paint over the floating val-label (which lives inside z-index:5) */
.rent-bar-dot--class:hover,
.rent-bar-dot--blended:hover,
.rent-bar-dot--core:hover {
  z-index: 10;
}

/* v2 uncertainty band (±5yr core perturbation) */
.rent-bar-band--uncertainty {
  position: absolute;
  top: 50%;
  height: 14px;
  transform: translateY(-50%);
  background: rgba(245, 158, 11, 0.14);
  border: 1px dashed rgba(245, 158, 11, 0.55);
  border-radius: 3px;
  z-index: 2;
  cursor: help;
}

/* v2 core estimate marker */
.rent-bar-dot--core {
  position: absolute;
  top: 50%;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: #f59e0b;
  border: 1.5px solid var(--surface);
  transform: translate(-50%, -50%);
  cursor: pointer;
  z-index: 4;
  box-shadow: 0 0 0 1px rgba(245, 158, 11, 0.35);
}

.rent-bar-dot--core:hover .rent-bar-tip,
.rent-bar-band--uncertainty:hover .rent-bar-tip {
  opacity: 1;
  visibility: visible;
}

/* v2 tooltip variant — share the existing --wide layout, just mark for targeting */
.rent-bar-tip--v2 {
  width: 560px;
}
.rent-bar-tip--v2 .v2-section-title {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #f5d491;
  margin: 0.35rem 0 0.15rem;
  border-top: 1px solid rgba(255,255,255,0.12);
  padding-top: 0.35rem;
}
.rent-bar-tip--v2 .v2-section-title:first-child {
  border-top: none;
  padding-top: 0;
  margin-top: 0;
}
.rent-bar-tip--v2 .v2-grid {
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  column-gap: 0.6rem;
  row-gap: 0.1rem;
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
}
.rent-bar-tip--v2 .v2-kv {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.5rem;
  font-size: var(--fs-xs);
}
.rent-bar-tip--v2 .v2-accent { color: #fbbf24; font-weight: 600; }
.rent-bar-tip--v2 .v2-muted { color: rgba(255,255,255,0.55); }
.rent-bar-tip--v2 .v2-strike { text-decoration: line-through; color: rgba(255,255,255,0.55); }

/* model version badge next to section title */
.model-badge {
  display: inline-flex;
  align-items: center;
  margin-left: 0.55rem;
  padding: 0.1rem 0.45rem;
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  border-radius: 4px;
  vertical-align: middle;
  line-height: 1.2;
}
.model-badge--v1 {
  background: rgba(100, 116, 139, 0.12);
  color: #475569;
  border: 1px solid rgba(100, 116, 139, 0.3);
}
.model-badge--v2 {
  background: rgba(245, 158, 11, 0.12);
  color: #b45309;
  border: 1px solid rgba(245, 158, 11, 0.4);
}

/* scale labels */
.rent-bar-scale {
  display: flex;
  justify-content: space-between;
  margin-top: 0.2rem;
  font-size: var(--fs-2xs);
  color: var(--muted);
}

/* notes beneath bar */
.rent-bar-notes {
  margin-top: 0.3rem;
  font-size: var(--fs-xs);
  color: var(--muted);
}

.rent-bar-notes .note-cap { color: #e67e22; }

.est-feedback-panel {
  margin-top: 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fcfcfd;
  padding: 0.75rem;
}

.est-feedback-panel h4 {
  margin: 0 0 0.45rem;
  font-size: var(--fs-base);
}

.feedback-context {
  margin: 0 0 0.6rem;
  color: var(--muted);
  font-size: var(--fs-sm);
}

#estimation-feedback-form {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.6rem 0.8rem;
}

#estimation-feedback-form label:last-of-type {
  grid-column: 1 / -1;
}

#estimation-feedback-form textarea {
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  padding: 0.55rem 0.65rem;
  font: inherit;
  resize: vertical;
}

.feedback-actions {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
  gap: 0.55rem;
}

.feedback-status {
  grid-column: 1 / -1;
  margin: 0;
  min-height: 1.1rem;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.feedback-flash {
  margin: 0.6rem 0 0;
  color: #166534;
  font-size: var(--fs-sm);
  font-weight: 500;
}

#map {
  height: 480px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  overflow: hidden;
}

.histogram-wrap {
  margin-top: 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1rem 1.25rem;
}

.histogram-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.8rem;
}

.histogram-controls {
  display: flex;
  gap: 0.65rem;
}

.histogram-controls label {
  font-size: var(--fs-sm);
}

.histogram-controls select {
  font-size: var(--fs-sm);
  padding: 0.4rem 0.6rem;
}

#histogram-canvas {
  margin-top: 0.7rem;
  max-height: 320px;
}

.table-wrap {
  margin-top: 1rem;
  overflow: auto;
  /* Viewport-relative so the actual comp rows get much more room when there are
     many comps — was a fixed 560px, which squeezed a ~50-building comp set to
     ~2-3 visible rows. max-height (not height) still collapses to content for
     small comp sets, and the building checklist stays sticky at the top. */
  max-height: 80vh;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  --rent-table-headline-height: 0px;
  --rent-table-building-panel-height: 0px;
  --rent-table-raw-head-height: 0px;
}

.table-headline {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 0.6rem 0.7rem;
}

.table-headline h3 {
  margin: 0;
}

.table-controls {
  display: flex;
  align-items: stretch;   /* every control shares the row height → equal-height buttons */
  gap: 0.5rem;
}

.table-controls button {
  padding: 0.5rem 0.9rem;
  font-size: var(--fs-base);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.table-controls input {
  width: 180px;           /* shorter quick-search bar */
  min-width: 0;
  padding: 0.45rem 0.55rem;
  font-size: var(--fs-base);
}

#row-count {
  color: var(--muted);
  font-size: var(--fs-base);
  align-self: center;     /* keep "N rows" centered in the stretched controls row */
  white-space: nowrap;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-base);
  min-width: 1250px;
}

th, td {
  text-align: left;
  padding: 0.55rem;
  border-bottom: 1px solid var(--border);
}

th {
  background: #f9fafb;
  color: var(--text);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

#raw-table thead th {
  position: sticky;
  z-index: 3;
}

#raw-head th {
  top: calc(var(--rent-table-headline-height) + var(--rent-table-building-panel-height));
}

#raw-filters th {
  top: calc(var(--rent-table-headline-height) + var(--rent-table-building-panel-height) + var(--rent-table-raw-head-height));
  z-index: 2;
}

th.sortable {
  cursor: pointer;
}

th.sorted-asc::after { content: ' \25B2'; }
th.sorted-desc::after { content: ' \25BC'; }

#raw-filters input {
  width: 100%;
  min-width: 90px;
  padding: 0.35rem 0.45rem;
  font-size: var(--fs-sm);
}

/* AI badge */
.ai-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-left: 0.6rem;
  padding: 0.2rem 0.6rem;
  font-size: var(--fs-2xs);
  font-weight: 600;
  font-family: var(--font-sans);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  background: var(--accent-light);
  border: 1px solid rgba(19,76,168,0.15);
  border-radius: 100px;
  vertical-align: middle;
  position: relative;
  overflow: hidden;
}

.ai-sparkle {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  animation: sparkle-pulse 2s ease-in-out infinite;
}

.ai-badge::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: var(--ai-shimmer);
  animation: shimmer-sweep 3s ease-in-out infinite;
}

@keyframes sparkle-pulse {
  0%, 100% { opacity: 0.7; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.15); }
}

@keyframes shimmer-sweep {
  0% { transform: translateX(-200%); }
  50%, 100% { transform: translateX(200%); }
}

/* Responsive */
@media (max-width: 900px) {
  .auth-status {
    flex-direction: column;
    align-items: flex-start;
  }

  .fields-grid { grid-template-columns: repeat(2, 1fr); }
  .fields-grid--2col { grid-template-columns: repeat(2, 1fr); }
  .hotel-info-sections { grid-template-columns: 1fr; }
  .prescreen-map-layout,
  .prescreen-decision-panel { grid-template-columns: 1fr; }
  .prescreen-map-side { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 760px) {
  /* Constrain html/body to the visible viewport only on mobile, so a
     rogue wide child (like the 1250px Unit-Level table) can't force
     Safari iOS to scale the whole page down. Desktop is untouched
     because the @media query doesn't match there. */
  html, body {
    max-width: 100vw;
    /* `clip` (not `hidden`): still clips a rogue wide child, but does NOT turn
       <body> into a scroll container the way `overflow-x: hidden` does — on iOS
       Safari that scroll-port makes vertical touch-scrolling stick/jank on the
       plain form views. `hidden` first as the pre-Safari-16 fallback; browsers
       that understand `clip` use the second (no scroll-port ⇒ no jank). */
    overflow-x: hidden;
    overflow-x: clip;
  }
  .panel {
    margin: 0.75rem !important;
    padding: 1rem;
    max-width: none !important;
    width: calc(100% - 1.5rem) !important;
    box-sizing: border-box;
  }
  /* Unit-Level table normally sets min-width: 1250px so the dashboard
     can scroll horizontally on desktop. On phones we instead let it
     wrap/shrink, with the wrap providing horizontal scroll if needed. */
  #raw-table { min-width: 0 !important; }
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  #map,
  #prescreen-map { height: 300px; min-height: 300px; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .prescreen-grid { grid-template-columns: 1fr; }
  .prescreen-map-side { grid-template-columns: 1fr; }
  .histogram-head,
  .table-headline { flex-direction: column; align-items: stretch; }
  .table-controls input { min-width: 150px; }
  .rent-bar-group { padding: 0.625rem 0.75rem; }
  .rent-bar-dot--final { width: 14px; height: 14px; }
  .rent-bar-val-label { font-size: var(--fs-base); }
  #estimation-feedback-form { grid-template-columns: 1fr; }

  /* Dashboard heading: stack address + button on narrow screens so
     long addresses wrap cleanly above a full-width Edit Search button. */
  .dashboard-head {
    flex-direction: column;
    align-items: stretch;
    gap: 0.6rem;
  }
  .dashboard-head h2 {
    margin: 0;
    font-size: var(--fs-lg);
    line-height: 1.3;
  }
  .dashboard-actions {
    justify-content: flex-end;
  }
}

@media (max-width: 560px) {
  .fields-grid { grid-template-columns: 1fr; }
  .fields-grid--2col { grid-template-columns: 1fr; }
}

/* --- Hazard & OZ Screening --- */
.hazard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 0.75rem;
}
.hazard-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
}
.hazard-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.5rem;
}
.hazard-badge {
  padding: 0.2rem 0.6rem;
  border-radius: 4px;
  color: #fff;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.hazard-desc {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.oz-card {
  border-left: 3px solid #8e44ad;
}

/* ── HUD AMI sparkline gauges (rent lens, 2026-05-26) ────────
   Renders below the estimated-rent bars. One row per unit type
   (Studio, 1B, optional 2B). Each row:
     • horizontal track 0-100% (auto-extends if est > 100% AMI)
     • tick marks at 30 / 50 / 60 / 80% AMI bands
     • a labeled dot at the estimated rent's AMI %
     • $ labels under each tick (rent cap at that AMI band) */
.est-rent-ami {
  margin-top: 1.5rem;
}
.ami-gauge-title {
  margin: 0 0 0.25rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}
.ami-gauge-source {
  font-size: var(--fs-xs, 0.72rem);
  color: var(--muted);
  margin-bottom: 0.6rem;
}
.ami-gauge {
  margin: 0.75rem 0 2.2rem;
}
.ami-gauge-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: var(--fs-sm);
  margin-bottom: 0.25rem;
}
.ami-gauge-row-label {
  font-weight: 600;
  color: var(--text);
}
.ami-gauge-est-pct {
  font-weight: 600;
  color: var(--accent);
}
.ami-gauge-est-pct--missing {
  color: var(--muted);
  font-weight: 400;
}
.ami-gauge-track {
  position: relative;
  height: 8px;
  background: #e2e8f0;
  border-radius: 4px;
  margin-bottom: 0.35rem;
}
.ami-gauge-tick {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  background: #94a3b8;
  transform: translateX(-50%);
}
.ami-gauge-dot {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--accent);
  z-index: 2;
}
.ami-gauge-labels {
  position: relative;
  height: 2.1em;
  font-size: 0.7rem;
  color: var(--muted);
}
.ami-gauge-band-label {
  position: absolute;
  transform: translateX(-50%);
  text-align: center;
  line-height: 1.1;
  display: flex;
  flex-direction: column;
}
.ami-gauge-band-pct {
  font-weight: 600;
  color: #475569;
}
.ami-gauge-band-cap {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* High-risk hazard cards get a red left border + a callout block
   under the description explaining the conversion-specific
   implication. Only renders when risk_level === 'High'. */
.hazard-card--high {
  border-left: 3px solid #b91c1c;
}
.hazard-implication {
  margin-top: 0.6rem;
  padding: 0.55rem 0.7rem;
  background: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: 6px;
  font-size: var(--fs-sm);
  line-height: 1.4;
}
.hazard-implication-body {
  color: #7f1d1d;
}
.hazard-implication-action {
  margin-top: 0.4rem;
  color: #991b1b;
  font-weight: 600;
}

/* ── Underwriting History page (/history) ────────────────────── */
.history-main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 1.25rem 1rem 3rem;
  display: grid;
  gap: 1rem;
}
.history-back-link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
  margin-left: 0.5rem;
}
.history-back-link:hover { text-decoration: underline; }

.history-toolbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}
.history-search {
  flex: 1 1 240px;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  font-size: var(--fs-sm);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
}
.history-count {
  font-size: var(--fs-sm);
  color: var(--muted);
  white-space: nowrap;
}
/* Pager below the history table. Compact + centered so it doesn't
   compete with the table for visual weight. Empty when there's only
   one page (rendered as innerHTML=''). */
.history-pager {
  display: flex;
  gap: 0.65rem;
  align-items: center;
  justify-content: center;
  margin-top: 0.85rem;
  padding: 0.45rem;
  font-size: var(--fs-sm);
}
.history-pager:empty { display: none; }
.history-type-filter {
  padding: 0.45rem 0.5rem;
  font-size: var(--fs-sm);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  background: #fff;
}
/* Batch vs Manual row tag in the unified history table. */
.history-type-badge {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}
.history-type-badge--manual { background: #e0e7ff; color: #3730a3; }
.history-type-badge--batch  { background: #dcfce7; color: #166534; }
.history-type-badge--detailed { background: #fef3c7; color: #92400e; }
.history-detail-note { white-space: pre-wrap; font-size: var(--fs-sm); line-height: 1.5; margin: 0.3rem 0 0; }
.history-status {
  margin: 0 0 0.5rem;
  min-height: 1.2em;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.history-status[data-kind="error"] { color: var(--danger); }
.history-status[data-kind="info"]  { color: var(--accent); }

.history-table-wrap { overflow-x: auto; }
/* A second horizontal scrollbar mirrored ABOVE the table, so the wide table can
   be scrolled sideways without first scrolling down to the bottom one. JS keeps
   the inner spacer the same width as the table, syncs scroll position both ways,
   and hides it when the table doesn't overflow. */
.history-scroll-top { overflow-x: auto; overflow-y: hidden; }
.history-scroll-top-inner { height: 1px; }
.history-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.history-table th,
.history-table td {
  padding: 0.5rem 0.65rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.history-table th {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 700;
}
.history-table th.num,
.history-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.history-table tbody tr.history-row { cursor: pointer; }
.history-table tbody tr.history-row:hover { background: var(--accent-light); }

/* Phones: the global `table { min-width: 1250px }` (sized for the wide SAR comp
   grid) also applies to this table; with no mobile override it expanded the whole
   page so `body { overflow-x: clip }` cut off the right-hand columns (Offer Price /
   IRR / Note) — unreachable. Cap the wrap to the viewport so the wide table scrolls
   sideways INSIDE it instead of widening the page off-screen. */
@media (max-width: 760px) {
  .history-table-wrap,
  .history-scroll-top {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: calc(100vw - 3.5rem);
  }
}
/* Optional saved label leads the address cell; the address drops to a muted
   sub-line beneath it. Nameless rows keep the bare address (no extra markup). */
.history-name { font-weight: 600; }
.history-addr-sub { font-size: var(--fs-xs); color: var(--muted); }
.history-note-cell {
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--muted);
}
.history-empty {
  text-align: center;
  color: var(--muted);
  padding: 1.25rem;
}

.history-detail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.85rem;
}
.history-detail-head h3 { margin: 0; font-size: var(--fs-lg); }
/* "Open in Single Asset Run" action — leads the Manual (single-asset) detail panel. */
.history-detail-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem 0.85rem;
  margin: 0 0 1.1rem;
}
.history-load-sar-btn {
  padding: 0.5rem 0.95rem;
  border-radius: 6px;
  font-size: var(--fs-sm);
  white-space: nowrap;
}
.history-load-hint {
  font-size: var(--fs-xs);
  color: var(--muted);
}
.history-kv-block { margin-bottom: 1.1rem; }
.history-kv-block h4 {
  margin: 0 0 0.4rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.25rem;
}
.history-kv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.3rem 1.25rem;
}
.history-kv-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.25rem 0;
  border-bottom: 1px dashed var(--border);
}
.history-kv-row span { color: var(--muted); font-size: var(--fs-sm); }
.history-kv-row strong {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  color: var(--text);
}
.history-note-full {
  margin: 0;
  white-space: pre-wrap;
  font-size: var(--fs-sm);
  color: var(--text);
  line-height: 1.5;
}

/* Delete action (admin only) — trailing column in the history table. */
.history-action-cell { text-align: center; }
.history-del-btn {
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
  line-height: 1;
  padding: 0.2rem 0.4rem;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 120ms ease, background 120ms ease;
}
.history-del-btn:hover {
  opacity: 1;
  background: var(--danger-bg);
  border-color: var(--danger-border);
}

/* Comp-set variation warning — soft "check the map" banner shown when a
   room type's comps are both widely dispersed and include premium-view /
   waterfront listings on the upper half. Amber palette matches the other
   advisory surfaces. */
.comp-warning {
  margin: 12px 0 4px;
  padding: 12px 16px;
  border: 1px solid #f59e0b;
  border-left: 4px solid #f59e0b;
  border-radius: 8px;
  background: #fffbeb;
  color: #92400e;
  font-size: 14px;
  line-height: 1.55;
}
.comp-warning strong { color: #92400e; }

/* Pre-underwriting "pass on this deal" note → shared property_notes.
   Same visual family as .comp-warning (amber advisory), but it's an input
   panel: label + textarea + actions row. */
.reject-deal-panel {
  margin: 12px 0 4px;
  padding: 12px 16px;
  border: 1px solid #f59e0b;
  border-left: 4px solid #f59e0b;
  border-radius: 8px;
  background: #fffbeb;
  font-size: 14px;
}
.reject-deal-panel label { display: block; font-weight: 600; color: #92400e; margin-bottom: 6px; }
.reject-deal-panel label .muted { font-weight: 400; }
.reject-deal-panel textarea {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem;
  font: inherit;
}
.reject-deal-actions { display: flex; align-items: center; gap: 0.6rem; margin-top: 8px; flex-wrap: wrap; }
#reject-deal-status[data-kind="error"] { color: var(--danger); }
#reject-deal-status[data-kind="ok"] { color: #15803d; }
#reject-deal-btn.reject-deal-done { opacity: 0.75; }

/* Manual comp selection — "Update Rent Comp" button, buildings panel, and
   the leading per-unit checkbox column in the listing table. */
.update-rent-comp-btn {
  background: var(--accent);
  color: #fff;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  font-weight: 600;
  cursor: pointer;
}
.update-rent-comp-btn:hover { background: var(--accent-hover); }
.update-rent-comp-btn:disabled { opacity: 0.6; cursor: default; }

.building-panel {
  position: sticky;
  top: var(--rent-table-headline-height);
  z-index: 4;
  margin: 0 0 12px;
  padding: 10px 12px;
  border: 1px solid #e5e7eb;
  border-radius: 0;
  background: #f9fafb;
  box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06);
}
.building-panel-head {
  font-size: 13px;
  font-weight: 600;
  color: #374151;
  margin-bottom: 8px;
}
.building-panel-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  max-height: 160px;
  overflow-y: auto;
}
.building-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #1f2937;
  cursor: pointer;
  white-space: nowrap;
}
.building-chip input { cursor: pointer; }

/* Leading checkbox column in the unit table */
.comp-select-cell {
  width: 32px;
  text-align: center;
  padding: 0 4px;
}
.comp-select-cell input { cursor: pointer; }
.comp-select-cell input:disabled { cursor: not-allowed; }

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — "Institutional Workbook" skin · Slice 1/6
   FOUNDATION: flat chrome · density · tabular numerics · input-blue convention
   ---------------------------------------------------------------------------
   Scoped to #input-detailed-pane. PURE PRESENTATION — no markup, element IDs,
   data-* attributes, or JS touched, so the underwriting engine and every
   calculation are unchanged. Fully reversible: delete this block to restore the
   prior look exactly. The shared 12-col grid / cross-section alignment is
   intentionally deferred to Slice 2.
   ═══════════════════════════════════════════════════════════════════════════ */
#input-detailed-pane {
  --du-line: #d3d9e2;            /* hairline gridline */
  --du-band: #eef2f7;           /* flat section band */
  --du-input-ink: #0b53c0;      /* model convention: BLUE text = hard-keyed input */
  font-variant-numeric: tabular-nums;
}

/* — Flat chrome: square corners, hairline borders, no rounded cards/shadows — */
#input-detailed-pane .form-section { border-radius: 3px; background: #fff; box-shadow: none; }
#input-detailed-pane input,
#input-detailed-pane select,
#input-detailed-pane textarea {
  border-radius: 2px;
  border-color: var(--du-line);
  font-variant-numeric: tabular-nums;
}
#input-detailed-pane input:focus,
#input-detailed-pane select:focus,
#input-detailed-pane textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-light);
}
#input-detailed-pane .du-schedule-wrap { border-radius: 0; border-color: var(--du-line); }

/* — Numeric discipline: BLUE = hard-keyed input, BLACK = calculated/read-only — */
#input-detailed-pane .du-fields input:not([readonly]),
#input-detailed-pane .du-input-table input,
#input-detailed-pane .du-opex-grid input,
#input-detailed-pane .du-stab-grid input { color: var(--du-input-ink); }
#input-detailed-pane input[readonly] { color: var(--text); background: #f7f8fb; }

/* — Density: tighter input padding & vertical rhythm — */
#input-detailed-pane .du-fields input,
#input-detailed-pane .du-fields select { padding: 0.18rem 0.4rem; }
#input-detailed-pane .du-input-table td { padding: 0.15rem 0.5rem 0.15rem 0; }

/* — Checkbox option with an inline hint (e.g. GP catch-up / GP clawback): keep the
   box and its label tight together at the start of the row, then drop the muted
   hint to its own full-width line beneath. The base ".du-fields label" grid sizes
   its first column to max-content, so a long inline .du-hint inflates that column
   and stretches the checkbox toward the centre (label pushed right, dead space on
   the far edge). A simple flex row sidesteps that and matches the clean label-left
   rhythm of the surrounding rows. — */
#input-detailed-pane .du-fields label.du-check {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 0.45rem;
  row-gap: 0.15rem;
}
#input-detailed-pane .du-fields label.du-check .du-hint { flex: 0 0 100%; }

/* — Numbered stage: flat band (accent top rule) instead of a rounded accent pill — */
#input-detailed-pane .du-stage {
  margin: 1.3rem 0 0.6rem;
  padding: 0.4rem 0.6rem;
  background: var(--du-band);
  border-left: none;
  border-top: 2px solid var(--accent);
  border-bottom: 1px solid var(--du-line);
  border-radius: 0;
}
#input-detailed-pane .du-stage-num {
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 2px;             /* square chip, not a circle */
  font-size: var(--fs-xs);
}

/* — Group subhead: small-caps with a hairline underline (ledger header) — */
#input-detailed-pane .du-subhead {
  margin: 0.85rem 0 0.4rem;
  padding-bottom: 0.22rem;
  border-bottom: 1px solid var(--du-line);
}

/* — Schedules: hairline gridlines (full spreadsheet pass is Slice 5) — */
#input-detailed-pane .du-schedule th,
#input-detailed-pane .du-schedule td { border-color: var(--du-line); }

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — "Institutional Workbook" skin · Slices 2–6
   Builds on the Slice 1 foundation. Still PURE PRESENTATION, scoped to
   #input-detailed-pane — no markup, IDs, data-* attributes, or JS touched.
   3 · headline → KPI ribbon   5 · schedules as spreadsheets   6 · table polish
   2 · alignment & density     reversible: delete this block to revert.
   ═══════════════════════════════════════════════════════════════════════════ */
#input-detailed-pane {
  --du-line-2: #e6eaf0;
  --du-line-strong: #aeb6c4;
  --du-ink-soft: #55617a;
  --du-zebra: #f8fafc;
}

/* ── 3 · Headline metrics → a flat, connected KPI ribbon ────────────────── */
#input-detailed-pane .du-headline {
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0;
  border: 1px solid var(--du-line);
  border-radius: 3px;
  overflow: hidden;
  background: #fbfcfe;
  margin-bottom: 1rem;
}
#input-detailed-pane .du-metric {
  background: transparent;
  border: none;
  border-left: 1px solid var(--du-line-2);
  border-radius: 0;
  padding: 0.5rem 0.8rem;
  gap: 0.1rem;
}
#input-detailed-pane .du-metric:first-child { border-left: none; }
#input-detailed-pane .du-metric-label { font-size: var(--fs-2xs); }
#input-detailed-pane .du-metric-value { font-size: var(--fs-lg); font-variant-numeric: tabular-nums; }
#input-detailed-pane .du-metric--hero { grid-column: auto; background: var(--accent-light); border-color: var(--du-line-2); }
#input-detailed-pane .du-metric--hero .du-metric-value { font-size: var(--fs-xl); }
#input-detailed-pane .du-metric-info { display: inline-block; margin-left: .2rem; color: var(--muted); cursor: help; font-size: .85em; }
#input-detailed-pane .du-oz-result-badge { display: inline-flex; align-items: center; margin: 0 0 .5rem; padding: .2rem .55rem; border: 1px solid var(--gold); border-radius: var(--radius-lg); background: var(--gold-soft); color: var(--text); font-size: var(--fs-xs); font-weight: 700; }
#input-detailed-pane .du-oz-detected { display: flex; align-items: flex-start; flex-wrap: wrap; gap: .55rem .75rem; margin: .35rem 0 .65rem; padding: .55rem .65rem; border: 1px solid var(--gold); border-left: 3px solid var(--gold); background: var(--gold-soft); color: var(--text); font-size: var(--fs-xs); line-height: 1.35; }
#input-detailed-pane .du-oz-detected button { padding: .3rem .55rem; border: 1px solid var(--accent); background: var(--surface); color: var(--accent); font-size: var(--fs-xs); font-weight: 600; }
#input-detailed-pane .du-oz-detected button:hover { background: var(--accent-light); }

/* ── 5 · Output schedules → spreadsheet (header band · zebra · bold totals) ─ */
#input-detailed-pane .du-schedule { font-size: var(--fs-2xs); }
#input-detailed-pane .du-schedule th,
#input-detailed-pane .du-schedule td { padding: 0.25rem 0.55rem; border-right: 1px solid var(--du-line-2); }
#input-detailed-pane .du-schedule thead th { background: var(--du-band); color: var(--du-ink-soft); font-weight: 700; }
#input-detailed-pane .du-schedule tbody tr:nth-child(even) td { background: var(--du-zebra); }
#input-detailed-pane .du-schedule tbody tr:nth-child(even) th { background: #fbfcfe; }
#input-detailed-pane .du-schedule tr.du-sched-section th,
#input-detailed-pane .du-schedule tr.du-sched-section td { background: var(--du-band); color: var(--du-ink-soft); font-weight: 700; }
#input-detailed-pane .du-schedule tr.du-bold th,
#input-detailed-pane .du-schedule tr.du-bold td { border-top: 1.5px solid var(--du-line-strong); }

/* ── 6 · OPEX grids & input tables → table chrome (header band · zebra · total rule) ── */
#input-detailed-pane .du-opex-h { color: var(--du-ink-soft); font-weight: 700; text-transform: uppercase; font-size: var(--fs-2xs); letter-spacing: 0.04em; }
#input-detailed-pane .du-input-table thead th { background: var(--du-band); padding: 0.3rem 0.5rem; }
#input-detailed-pane .du-input-table tbody tr:nth-child(even) td { background: var(--du-zebra); }
#input-detailed-pane .du-tot,
#input-detailed-pane .du-opex-total { border-top: 1.5px solid var(--du-line-strong); }

/* ── 6 · Sensitivity tables → square hairline + header band (baseline highlight already present) ── */
#input-detailed-pane .du-sens-table th,
#input-detailed-pane .du-sens-table td { border: 1px solid var(--du-line-2); }
#input-detailed-pane .du-sens-table thead th { background: var(--du-band); text-transform: uppercase; font-size: var(--fs-2xs); letter-spacing: 0.04em; }

/* ── 6 · Save / versions / tranches / statement → flat & square ─────────── */
#input-detailed-pane .du-save-notes textarea { border-radius: 2px; border-color: var(--du-line); }
#input-detailed-pane .du-version { border-radius: 2px; border-color: var(--du-line); }
#input-detailed-pane .du-version--newest { box-shadow: none; border-left: 2px solid var(--accent); }
#input-detailed-pane .du-sp-tranche { border-radius: 2px; background: #fbfcfe; }
/* Static field help collapsed into a hover "?" badge (native title tooltip) so the
   tranche cards aren't crowded with always-on grey notes. Badge reuses .info-tip;
   native title is used (not the .tooltip-box popover) because #du-sp-tranches is a
   horizontal scroll lane (overflow-x:auto/overflow-y:hidden) that would clip a popover. */
#input-detailed-pane .du-sp-tranche .du-q,
#input-detailed-pane .du-fields .du-q {
  width: 0.95rem; height: 0.95rem; min-width: 0.95rem; font-size: 0.6rem; font-weight: 700;
  margin-left: 0.25rem; vertical-align: middle; cursor: help;
}
/* Keep the badge visually stable on focus/active (it was filling solid on click). */
#input-detailed-pane .du-q:focus,
#input-detailed-pane .du-q:active { outline: none; background: var(--accent-light); color: var(--accent); box-shadow: none; }
/* Help tooltip popover — position:fixed so it never clips inside a scroll lane. */
.du-tip-pop {
  position: fixed; z-index: 2000; display: none; max-width: 280px;
  padding: 0.5rem 0.65rem; background: var(--text); color: #fff;
  border-radius: var(--radius-sm); font-size: var(--fs-sm); line-height: 1.35;
  box-shadow: var(--shadow-lg); pointer-events: none;
}
.du-tip-pop, .du-tip-pop * { color: #fff; }
/* Unit-mix scenarios — all three side by side. Floor plan + Size are shared
   (left/right); each scenario owns a (# Units, Rent) column-pair. Click a scenario
   header to make it the ACTIVE rent roll (the one the engine underwrites). */
#input-detailed-pane .du-um-hint {
  font-size: var(--fs-2xs); color: var(--muted); font-weight: 500;
  letter-spacing: 0; text-transform: none; margin-left: 0.5rem;
}
#input-detailed-pane .du-um-grid { table-layout: auto; }
/* Scenario group header — clickable, segmented-control feel across its 2 columns. */
#input-detailed-pane .du-um-grid .du-um-sc {
  text-align: center; cursor: pointer; user-select: none;
  font-size: var(--fs-2xs); font-weight: 700; letter-spacing: 0.02em;
  color: var(--du-ink-soft); background: #f3f5f9;
  border: 1px solid var(--du-line); border-bottom: 2px solid var(--du-line);
  padding: 4px 8px; border-radius: 3px 3px 0 0;
}
#input-detailed-pane .du-um-grid .du-um-sc + .du-um-sc { margin-left: 2px; }
#input-detailed-pane .du-um-grid .du-um-sc:hover { background: #fff; color: var(--text); }
#input-detailed-pane .du-um-grid .du-um-sc--active {
  color: var(--accent); background: #eaf2fc;
  border-color: var(--accent); border-bottom-color: var(--accent);
}
/* Sub-headers (# Units / Rent) keep the table's muted right-aligned look. */
#input-detailed-pane .du-um-grid .du-um-sccol { text-align: right; }
/* Faint left rule starts each scenario group so the eye can separate them. */
#input-detailed-pane .du-um-grid .du-um-sccol[data-sc],
#input-detailed-pane .du-um-grid .du-um-sccell[data-sc] { }
#input-detailed-pane .du-um-grid td.du-um-sccell:nth-child(2n) { border-left: 1px solid var(--du-zebra); }
/* Active scenario's column cells — a faint tint so it's obvious which one is live. */
#input-detailed-pane .du-um-grid .du-um-sccell--active { background: #f1f6fd !important; }
#input-detailed-pane .du-um-grid .du-um-sccell--active input { background: transparent; }
#input-detailed-pane .du-um-grid .du-um-corner { vertical-align: bottom; }
#input-detailed-pane .du-um-grid tfoot .du-um-sccell { text-align: center; }
#input-detailed-pane .du-um-grid tfoot .du-um-sccell[data-sc-tot-gpr] { text-align: right; }
/* Repay-at-refi overrides both the payoff event and return priority → grey the
   (now-ignored) controls. Their explanations live in the "?" badge's hover tooltip. */
#input-detailed-pane .du-sp-tranche label.du-ctl-muted { color: var(--muted); }
#input-detailed-pane .du-sp-tranche label.du-ctl-muted > select { opacity: 0.5; }
#input-detailed-pane .du-stmt-sec { border-radius: 2px; border-color: var(--du-line); }
/* Returns + GP Economics as a compact side-by-side pair (each ~one grid column wide)
   at the end of the returns grid, so GP comp always reads beside §9 regardless of how
   many cards precede it. Spans two grid tracks; the inner two collapse on narrow widths. */
#input-detailed-pane .du-returns-pair {
  grid-column: span 2;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
  align-items: start;
}
#input-detailed-pane .secondary-btn { border-radius: 2px; }

/* ── 2 · Alignment & density: tighter column gaps ──────────────────────── */
#input-detailed-pane .du-cols { gap: 0.3rem 2rem; }

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — Workbook sticky header: sheet-tab nav + top KPI ribbon
   Adds markup (#du-topbar) + a little JS (renderTopbar / initWorkbookHeader);
   no engine input, no existing IDs changed.
   ═══════════════════════════════════════════════════════════════════════════ */
#input-detailed-pane .du-topbar {
  position: sticky; top: 0; z-index: 30;
  background: #fbfcfe;
  border: 1px solid var(--du-line);
  border-radius: 3px;
  margin-bottom: 0.85rem;
  overflow: hidden;
}
#input-detailed-pane .du-sheettabs {
  display: flex; gap: 0; overflow-x: auto;
  background: #f3f5f9; border-bottom: 1px solid var(--du-line);
}
#input-detailed-pane .du-sheettab {
  flex: none; padding: 6px 14px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--du-ink-soft);
  text-decoration: none; white-space: nowrap; cursor: pointer;
  border-right: 1px solid var(--du-line-2); border-bottom: 2px solid transparent;
}
#input-detailed-pane .du-sheettab b { color: var(--muted); font-weight: 700; margin-right: 5px; }
#input-detailed-pane .du-sheettab:hover { background: #fff; color: var(--text); }
#input-detailed-pane .du-sheettab--active { background: #fff; color: var(--accent); border-bottom-color: var(--accent); }
#input-detailed-pane .du-sheettab--active b { color: var(--accent); }
#input-detailed-pane .du-kpibar { display: flex; flex-wrap: wrap; align-items: stretch; }
#input-detailed-pane .du-kpibar-hint { padding: 8px 14px; font-size: var(--fs-xs); color: var(--muted); }
/* Size each cell to its (one-line) label so the value row aligns across all cells —
   a long label that wraps (e.g. "Capital Returned · refi") would otherwise drop its
   value to a lower row. Grow to fill the width; ellipsis (below) handles a too-narrow
   pane without clipping the ribbon. */
#input-detailed-pane .du-kpi {
  flex: 1 1 auto; min-width: 0;
  padding: 6px 14px; border-left: 1px solid var(--du-line-2);
  display: flex; flex-direction: column; gap: 1px; overflow: hidden;
}
#input-detailed-pane .du-kpi:first-child { border-left: none; }
#input-detailed-pane .du-kpi--hero { background: var(--accent-light); }
#input-detailed-pane .du-kpi-l { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#input-detailed-pane .du-kpi-v { font-size: var(--fs-lg); font-weight: 700; font-variant-numeric: tabular-nums; }
#input-detailed-pane .du-kpi--hero .du-kpi-v { color: var(--accent); }
/* stages clear the sticky header height when jumped-to via the tabs */
#input-detailed-pane .du-stage { scroll-margin-top: 92px; }

/* ═══════════════════════════════════════════════════════════════════════════
   DU workbook · #3 — one shared 12-column grid (cross-section alignment)
   Every .du-cols (incl. the --leaseup-opex 1.6:1 and --stages variants) becomes
   the SAME 12-col grid; its two groups span 6 each, so input right-edges line up
   at the page centre (col 6) and right (col 12) down EVERY section. Full-width
   tables/OPEX align trivially. Iteration 1: CSS-only, no markup/IDs/JS touched.
   ═══════════════════════════════════════════════════════════════════════════ */
#input-detailed-pane .du-cols,
#input-detailed-pane .du-cols--leaseup-opex {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.4rem 1.75rem;
  align-items: start;
}
#input-detailed-pane .du-cols > .du-group { min-width: 0; }
/* tighter input column so label+value sit close in the narrow columns */
#input-detailed-pane .du-cols .du-fields label:not(.du-check) {
  grid-template-columns: minmax(0, 1fr) 6.5rem;
}
/* Stage 5 + 6 as a unified 4-up: the two stage headers each span their half
   (cols 1-2 / 3-4), then Refinance | Exit | Waterfall | Return Summary below. */
#input-detailed-pane .du-cols--stages4 > .du-stage { grid-column: span 2; }

/* Inline derived 4th-column blocks (Reserve Result · Capitalization · NOI Bridge):
   computed summaries beside the inputs — black/accent values, distinct from blue inputs. */
#input-detailed-pane .du-deriv { display: flex; flex-direction: column; margin-top: 0.1rem; }
#input-detailed-pane .du-deriv-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding: 4px 1px; border-bottom: 1px solid var(--du-line-2);
  font-size: var(--fs-xs); color: var(--du-ink-soft);
}
#input-detailed-pane .du-deriv-row:last-child { border-bottom: none; }
#input-detailed-pane .du-deriv-row b { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
#input-detailed-pane .du-deriv-row:first-child b { color: var(--accent); }   /* hero value */

/* Ledger hairlines on the assumption rows — subtle spreadsheet structure for scanning. */
#input-detailed-pane .du-cols .du-fields label:not(.du-check) {
  border-bottom: 1px solid var(--du-line-2);
  padding-bottom: 3px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — Stage 3 "Sources & Uses" ledger (derived 4th column)
   Turns the old 5-line Capitalization summary into a tie-out ledger: Uses build
   up to Total Project Cost; Sources build up to the SAME total; then the senior
   loan ÷ total-cost ratio + a reserve-financing note. PURE PRESENTATION.
   ═══════════════════════════════════════════════════════════════════════════ */
/* NB: own class prefix (du-suledger-*). The legacy .du-su (line ~967) is a
   DIFFERENT, older block — a 2-col grid with gap:1.5rem; sharing its name
   loosened these rows to a 50px pitch. Decoupled here so the ledger matches the
   other derived blocks' tight ~26px rhythm (the .du-deriv row pitch, no gap). */
#input-detailed-pane .du-suledger { gap: 0; }
#input-detailed-pane .du-suledger .du-suledger-head {
  margin: 0.5rem 0 0; padding-bottom: 0.16rem;
  font-size: var(--fs-2xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--du-ink-soft); border-bottom: 1px solid var(--du-line);
}
#input-detailed-pane .du-suledger .du-suledger-head:first-child { margin-top: 0; }
/* Subtotal rules (Total project cost / Total sources): bold + ruled + accented,
   so the eye lands on them and the two EQUAL totals make the tie self-evident. */
#input-detailed-pane .du-suledger .du-suledger-total {
  border-top: 1.5px solid var(--du-line-strong); border-bottom: none;
  margin-top: 2px; padding-top: 4px;
}
#input-detailed-pane .du-suledger .du-suledger-total > span { font-weight: 700; color: var(--text); }
#input-detailed-pane .du-suledger .du-suledger-total b { color: var(--accent); font-size: var(--fs-sm); }
/* Loan ÷ cost ratio sits a touch apart from the Sources block. */
#input-detailed-pane .du-suledger .du-suledger-ratio {
  margin-top: 0.35rem; border-top: 1px solid var(--du-line-2); border-bottom: none;
}
#input-detailed-pane .du-suledger .du-suledger-sub { color: var(--muted); font-weight: 400; font-size: var(--fs-2xs); }
#input-detailed-pane .du-suledger-note {
  margin: 0.4rem 0 0; font-size: var(--fs-2xs); line-height: 1.35; color: var(--muted);
}

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — Stage 5 Capital Events: Refinance / Exit result blocks
   Derived outputs under the refi & exit inputs (same look as the other derived
   blocks; accent-ruled totals tie to the engine's gross / net proceeds).
   ═══════════════════════════════════════════════════════════════════════════ */
#input-detailed-pane .du-cap-deriv { margin-top: 0.55rem; }
#input-detailed-pane .du-cap-deriv .du-cap-sub {
  margin-bottom: 0.1rem; padding-bottom: 0.16rem;
  font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--du-ink-soft); border-bottom: 1px solid var(--du-line);
}
#input-detailed-pane .du-cap-deriv .du-cap-total {
  border-top: 1.5px solid var(--du-line-strong); border-bottom: none; margin-top: 2px; padding-top: 4px;
}
#input-detailed-pane .du-cap-deriv .du-cap-total > span { font-weight: 700; color: var(--text); }
#input-detailed-pane .du-cap-deriv .du-cap-total b { color: var(--accent); font-size: var(--fs-sm); }

/* ═══════════════════════════════════════════════════════════════════════════
   Stage 5 / 6 split: Capital Events keeps the 4-up (inputs left · derived right);
   Returns & Waterfall drops to its own full-width row below as a balanced 3-up.
   A stage header spans the whole row it heads. ═══════════════════════════════ */
#input-detailed-pane .du-stage--full { grid-column: 1 / -1; }
#input-detailed-pane .du-cols--ret3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#input-detailed-pane .du-ret-row { margin-top: 1.4rem; }

/* Subordinate tranches: lay the cards out horizontally and scroll between them
   (instead of stacking vertically, which made the section very tall). Each card
   is a fixed width; the lane scrolls when the cards exceed it. */
#input-detailed-pane #du-sp-tranches {
  display: flex; flex-wrap: nowrap; gap: 0.6rem;
  overflow-x: auto; overflow-y: hidden;
  padding-bottom: 0.45rem; scroll-snap-type: x proximity;
}
#input-detailed-pane #du-sp-tranches .du-sp-tranche {
  flex: 0 0 19rem; width: 19rem; margin: 0; scroll-snap-align: start;
}
#input-detailed-pane #du-sp-tranches::-webkit-scrollbar { height: 8px; }
#input-detailed-pane #du-sp-tranches::-webkit-scrollbar-thumb {
  background: var(--du-line-strong); border-radius: 4px;
}
#input-detailed-pane #du-sp-tranches::-webkit-scrollbar-track { background: var(--du-line-2); border-radius: 4px; }

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — Stabilized "Underwriting & Returns" headline ribbon
   Fixed 4-col grid so the 7 metrics line up in a clean 4 + 3 (returns row /
   operations row) instead of an uneven auto-fit wrap. Adds the horizontal rule
   between the two rows + a clean left edge per row. Scoped to #du-stable-headline
   so the lease-up headline (#du-headline) is untouched. PURE PRESENTATION.
   ═══════════════════════════════════════════════════════════════════════════ */
#input-detailed-pane #du-stable-headline { grid-template-columns: repeat(4, minmax(0, 1fr)); }
#input-detailed-pane #du-stable-headline .du-metric { border-top: 1px solid var(--du-line-2); }
#input-detailed-pane #du-stable-headline .du-metric:nth-child(-n+4) { border-top: none; }   /* row 1 */
#input-detailed-pane #du-stable-headline .du-metric:nth-child(4n+1) { border-left: none; }   /* col 1 starts clean */

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — Stage 3 compact layout (Acquisition & Capitalization)
   Subordinate Tranches (col 3) and Sources & Uses (col 4) are the two tall
   columns → pin them to span both rows on the right. Acquisition (col 1) and
   Closing (col 2) sit in row 1, and the Development Budget lifts up into row 2
   beneath them — filling what was a tall empty band and grouping the three
   input sections together. PURE PRESENTATION (placement only).
   ═══════════════════════════════════════════════════════════════════════════ */
/* Stage 3 has five blocks — one WIDE (the Development Budget table) and one TALL
   (Subordinate Tranches) — so a true 3-column layout fits it best (each column
   stays wide enough for the dev table to read):
     Col 1: Acquisition  ·  Development Budget
     Col 2: Closing       ·  Sources & Uses
     Col 3: Subordinate Tranches (spans both rows)
   This lifts the Development Budget up beside the inputs (no tall empty band) and
   balances the column heights. The long dev-budget note moves full-width below. */
#input-detailed-pane .du-cols--3up {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
}
#input-detailed-pane .du-cols--3up > .du-acq-fin   { grid-column: 1; grid-row: 1; }
#input-detailed-pane .du-cols--3up > .du-acq-dev   { grid-column: 1; grid-row: 2; margin-top: 0.55rem; }
#input-detailed-pane .du-cols--3up > .du-acq-close { grid-column: 2; grid-row: 1; }
#input-detailed-pane .du-cols--3up > .du-acq-su    { grid-column: 2; grid-row: 2; margin-top: 0.55rem; }
/* Subordinate Tranches drops to its own full-width row below the acquisition
   inputs, so the tranche cards lay out horizontally across the page and scroll
   (rather than stacking in the narrow 3rd column). The other four groups keep
   their 2×2 placement in columns 1–2. */
#input-detailed-pane .du-cols--3up > .du-acq-sub   { grid-column: 1 / -1; grid-row: 3; margin-top: 0.9rem; }
#input-detailed-pane .du-acq-devnote { margin-top: 0.4rem; }
/* The dev-budget table was hard-set to width:calc(50% - 1.25rem) for its old
   full-width spot; inside a single grid column that 50% collapses the (fixed-
   layout) cost-line column. Fill the column so the cost lines stay readable. */
#input-detailed-pane .du-acq-dev .du-devcost-table { width: 100%; }

/* ═══════════════════════════════════════════════════════════════════════════
   DETAILED UNDERWRITING — Stage 2 (Lease-Up) layout
   Top row is now 3-up (Timing | Hotel | Reserve Result). The Lease-Up Operating
   Expenses table and "Other Lease-Up Assumptions" sit SIDE BY SIDE below — the
   wide opex grid on the left, the short assumptions column filling the space to
   its right (it used to be stranded up in the top row). PURE PRESENTATION.
   ═══════════════════════════════════════════════════════════════════════════ */
#input-detailed-pane .du-cols--lu-top { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#input-detailed-pane .du-cols--lu-opex {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.6rem 2rem;
}
/* Opex column ≈ the line-item grid's own width (its 3 columns total ~28rem; the
   long header wraps inside it), so the assumptions column fits beside it on the
   1140px panel instead of being bumped to the next row. Assumptions grows into
   the remaining space, capped so its fields stay tight. */
#input-detailed-pane .du-cols--lu-opex > .du-group:first-child { flex: 0 0 32rem; }
#input-detailed-pane .du-cols--lu-opex > .du-group:first-child .du-opex-grid { width: max-content; }
#input-detailed-pane .du-cols--lu-opex > .du-group:last-child { flex: 1 1 18rem; max-width: 30rem; }

/* ═══════════════════════════════════════════════════════════════════════════
   SINGLE ASSET RUN — "Institutional Workbook" skin for the Offer panel
   ---------------------------------------------------------------------------
   Brings the quick-Offers underwriting-assumptions panel in line with the
   Detailed Underwriting (#input-detailed-pane) institutional look:
     · flat chrome (square corners, hairline gridlines — no rounded "website" card)
     · BLUE hard-keyed number inputs, BLACK selects/calculated (model convention)
     · tabular numerics, right-aligned values, ONE fixed value column → every
       input lines up in a spreadsheet-style column down the whole form
     · 4-tier hierarchy: panel title → section band → group subhead → ledger rows
     · tighter density / consistent spacing
   PURE PRESENTATION — scoped to #offer-panel. No markup, element IDs, data-*
   attributes, or JS touched, so every calculation, the solver, save/load, and
   all defaults are unchanged. Fully reversible: delete this block to restore the
   prior look exactly. Reuses the same token values as the DU reskin.
   ═══════════════════════════════════════════════════════════════════════════ */
#offer-panel {
  --du-line: #d3d9e2;            /* hairline gridline */
  --du-line-2: #e6eaf0;          /* lighter row hairline (ledger) */
  --du-line-strong: #aeb6c4;     /* bold rule (title / totals) */
  --du-band: #eef2f7;            /* flat section band */
  --du-ink-soft: #55617a;        /* soft label/header ink */
  --du-input-ink: #0b53c0;       /* model convention: BLUE = hard-keyed input */
  font-variant-numeric: tabular-nums;
}

/* — Flat panel chrome: drop the rounded card + 3px left accent bar for a square,
     hairline-bordered sheet. — */
#offer-panel.offer-panel {
  border: 1px solid var(--du-line);
  border-left: 1px solid var(--du-line);
  border-radius: 3px;
}
/* Panel title → workbook title with a strong bottom rule. */
#offer-panel h3 {
  padding-bottom: 0.5rem;
  margin: 0 0 0.95rem;
  border-bottom: 2px solid var(--du-line-strong);
}

/* — Flat chrome for every control: square corners, hairline borders, tabular nums
     (mirrors the DU foundation rule). The .offer-inputs-grid rules below layer the
     blue ink + right-alignment on top of this baseline. — */
#offer-panel input,
#offer-panel select,
#offer-panel textarea {
  border-radius: 2px;
  border-color: var(--du-line);
  font-variant-numeric: tabular-nums;
}
#offer-panel input:focus,
#offer-panel select:focus,
#offer-panel textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-light);
}
#offer-panel button { border-radius: 2px; }
/* Additional Capital Tranches cards clone the DU template, so their inputs use the
   `.du-fields` classes whose BLUE hard-keyed-input convention is scoped to
   #input-detailed-pane (out of reach here). Re-apply BLUE so tranche numbers match
   the rest of the panel's inputs. (Square chrome + right-align + tabular already come
   from the panel baseline above and the base `.du-fields input` rule.) */
#offer-panel .du-fields input:not([readonly]) { color: var(--du-input-ink); }

/* — Major section header (Selected Scenario · Construction Budget · Underwriting
     assumptions) → flat band with an accent top rule (the DU .du-stage look). — */
#offer-panel .offer-subsection > h4,
#offer-panel .offer-subsection-head {
  margin: 0 0 0.7rem;
  padding: 0.42rem 0.6rem;
  background: var(--du-band);
  border-top: 2px solid var(--accent);
  border-bottom: 1px solid var(--du-line);
  border-radius: 0;
  color: var(--du-ink-soft);
}
#offer-panel .offer-subsection-head { align-items: center; }
#offer-panel .offer-subsection-head h4 { color: var(--du-ink-soft); }
/* Section bands already separate the sub-sections — drop the dashed divider. */
#offer-panel .offer-subsection {
  border-bottom: none;
  padding-bottom: 0.35rem;
  margin-bottom: 0.55rem;
}

/* — Group subhead (Return targets · Senior debt · Preferred equity · …) → small-caps
     with a hairline underline (ledger header, the DU .du-subhead look). — */
#offer-panel .offer-input-group-label {
  font-weight: 700;
  color: var(--du-ink-soft);
  border-bottom: 1px solid var(--du-line);
  padding-bottom: 0.24rem;
  margin-bottom: 0.4rem;
}
#offer-panel .offer-input-group + .offer-input-group { margin-top: 0.85rem; }
/* Inline descriptive notes inside a subhead read as normal sentence case. */
#offer-panel .offer-input-group-label .muted,
#offer-panel .offer-input-group-label .offer-subhelp {
  text-transform: none; font-weight: 400; letter-spacing: 0; color: var(--muted);
}
/* Seller-JV enable: a tidy inline checkbox toggle that reads as a section header
   (was a checkbox floating above the label). */
#offer-panel .offer-input-group-label > label {
  display: inline-flex; align-items: center; gap: 0.45rem;
  margin: 0; cursor: pointer; color: inherit;
}
#offer-panel .offer-input-group-label > label input[type="checkbox"] {
  width: 0.95rem; height: 0.95rem; margin: 0; flex: none; cursor: pointer;
}

/* — The assumptions grid → a fixed 4-column spreadsheet. Each field is a flexible
     label + ONE fixed value column, so every input shares the same width and right
     edge down the entire form. Hairline under each row = ledger rhythm. — */
#offer-panel .offer-inputs-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.05rem 1.4rem;
  align-items: stretch;
}
#offer-panel .offer-inputs-grid label {
  grid-template-columns: minmax(0, 1fr) 7rem;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-xs);
  color: var(--du-ink-soft);
  border-bottom: 1px solid var(--du-line-2);
  padding: 0.3rem 0 0.28rem;
}
/* Number / money inputs: BLUE, right-aligned, tabular, fill the value column. */
#offer-panel .offer-inputs-grid input[type="number"],
#offer-panel .offer-inputs-grid input[type="text"],
#offer-panel .offer-recompute-label input {
  width: 100%;
  padding: 0.18rem 0.4rem;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  text-align: right;
  border: 1px solid var(--du-line);
  border-radius: 2px;
  color: var(--du-input-ink);
  background: #fff;
}
/* Selects: keep BLACK (calculated/choice convention) + left-aligned so long option
   labels read from the start; the value column clips with full text on open. */
#offer-panel .offer-inputs-grid select {
  width: 100%;
  padding: 0.18rem 0.4rem;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  text-align: left;
  border: 1px solid var(--du-line);
  border-radius: 2px;
  color: var(--text);
  background: #fff;
}
/* Drop spinner arrows so right-aligned figures sit clean (Excel-like). */
#offer-panel .offer-inputs-grid input[type="number"]::-webkit-outer-spin-button,
#offer-panel .offer-inputs-grid input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
#offer-panel .offer-inputs-grid input[type="number"] { -moz-appearance: textfield; }

/* Refinance route controls: visual-only normalization to match the rest of the
   Single Asset assumption rows. */
#offer-panel .offer-refi-routes {
  color: var(--du-ink-soft);
  font-size: var(--fs-xs);
}
#offer-panel .offer-refi-route-row {
  background: #fff;
}
#offer-panel .offer-refi-route-name label {
  color: var(--du-ink-soft);
  font-size: var(--fs-xs);
  font-weight: 600;
}
#offer-panel .offer-refi-route-name span {
  color: var(--du-ink-soft);
  font-size: var(--fs-xs);
  font-weight: 400;
}
#offer-panel .offer-refi-route-row > label {
  color: var(--du-ink-soft);
  font-size: var(--fs-xs);
  font-weight: 400;
}
#offer-panel .offer-refi-route-row input[type="number"] {
  background: #fff;
  color: var(--du-input-ink);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
}

/* OZ panel: only 3 fields, two with long labels ("Depreciation at sale (%)",
   "State cap-gains (%)"). The dense 4-column ledger grid crams them, so give this
   optional overlay its own 2-column rhythm. The vintage field spans the full row
   with a content-sized value track so the full vintage option ("OZ 1.0 (now–2026)")
   shows without opening the picker. */
#offer-panel #offer-oz-panel { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#offer-panel #offer-oz-panel label.oz-vintage-row {
  grid-column: span 2;
  grid-template-columns: minmax(0, auto) minmax(9rem, 1fr);
}
#offer-panel .offer-oz-detected {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0.15rem 0 0.65rem;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--gold);
  border-left: 3px solid var(--gold);
  background: var(--gold-soft);
  color: var(--text);
  font-size: var(--fs-sm);
}
#offer-panel .offer-oz-detected button {
  flex: none;
  padding: 0.35rem 0.65rem;
  border: 1px solid var(--accent);
  background: var(--surface);
  color: var(--accent);
  font-size: var(--fs-xs);
  font-weight: 600;
}
#offer-panel .offer-oz-detected button:hover {
  background: var(--accent-light);
}
@media (max-width: 700px) {
  #offer-panel .offer-oz-detected {
    align-items: flex-start;
    flex-direction: column;
  }
}

/* — Construction-budget override grid + recompute row align to the same look. — */
#offer-panel .cc-totals-grid { border-top: 1px solid var(--du-line); }
#offer-panel .offer-recompute-label input { max-width: 16rem; }

/* — Paired small sections: two single-/two-field groups sit side-by-side (each its
     own subhead + a 2-col field grid) so the form stays dense instead of leaving
     half-empty rows. More DU-like (groups in columns). — */
#offer-panel .offer-group-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.85rem 1.4rem;
  align-items: start;
}
#offer-panel .offer-group-row > .offer-input-group { margin-top: 0; }
#offer-panel .offer-group-row .offer-inputs-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#offer-panel .offer-input-group + .offer-group-row,
#offer-panel .offer-group-row + .offer-input-group { margin-top: 0.85rem; }

/* — Output → an institutional results statement. Each section gets the SAME flat
     band header as the input sections; rows are a tabular ledger aligned to the band
     edges; the Offer Price + cash-to-close read as the heroes (accent). — */
/* Offer Price → hero result banner, tied into the band system. */
#offer-panel .offer-out-row--primary {
  border: 1px solid var(--du-line);
  border-top: 2px solid var(--accent);
  border-radius: 3px;
  padding: 0.6rem 0.85rem;
}
/* Section headers (Returns · Property economics · Capital stack) → flat accent-top
   band, identical to the input sections. */
#offer-panel .offer-out-group-label {
  background: var(--du-band);
  border-top: 2px solid var(--accent);
  border-bottom: 1px solid var(--du-line);
  border-radius: 0;
  padding: 0.4rem 0.6rem;
  margin-bottom: 0;
  color: var(--du-ink-soft);
}
/* Ledger rows → align to the band's horizontal padding; lighter hairline rule. */
#offer-panel .offer-out-group .offer-out-row { padding: 0.44rem 0.6rem; }
#offer-panel .offer-out-group .offer-out-row:not(:last-child) {
  border-bottom: 1px solid var(--du-line-2);
}
#offer-panel .offer-out-row span { color: var(--du-ink-soft); }
#offer-panel .offer-out-row strong { font-variant-numeric: tabular-nums; }
/* Route comparison matrix: visual-only normalization so the multi-route output
   uses the same ink, band, and number typography as the standard output rows. */
#offer-panel .offer-route-matrix-wrap {
  background: #fff;
}
#offer-panel .offer-route-matrix-head {
  background: var(--du-band);
  color: var(--du-ink-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
}
#offer-panel .offer-route-matrix-section {
  background: var(--du-band);
  color: var(--du-ink-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
}
#offer-panel .offer-route-matrix-label {
  color: var(--du-ink-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  font-weight: 400;
}
#offer-panel .offer-route-matrix-value {
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
#offer-panel .offer-route-matrix-selected {
  background: transparent;
}
#offer-panel .offer-route-matrix-head small {
  color: var(--du-ink-soft);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 400;
}
/* Cash-to-close → a real statement total: strong top rule, accent figure. */
#offer-panel .offer-out-group .offer-out-row--emphasized {
  border-top: 1.5px solid var(--du-line-strong);
  margin-top: 0;
  padding-top: 0.5rem;
}
/* — Sources & Uses ledger: "Uses" / "Sources" sub-heads + the LTC ratio footer. — */
#offer-panel .offer-su-head {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--du-ink-soft);
  padding: 0.5rem 0.6rem 0.15rem;
}
#offer-panel .offer-out-group--su .offer-out-row--su-ratio { border-bottom: none; }
#offer-panel .offer-out-row--su-ratio span,
#offer-panel .offer-out-row--su-ratio strong {
  color: var(--du-ink-soft);
  font-size: var(--fs-sm);
  font-weight: 600;
}

/* — Responsive: the panel lives in the ~1140px .panel column; collapse the 4-up to
     2-up then 1-up on narrow viewports (own rules so they beat the #offer-panel
     specificity of the 4-col rule above). — */
@media (max-width: 900px) {
  #offer-panel .offer-inputs-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  #offer-panel .offer-group-row { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
  #offer-panel .offer-inputs-grid { grid-template-columns: 1fr; }
}

/* ── SAR Sensitivity Analysis (read-only Stabilized-Appraised-Value grid) ── */
.sar-sens { margin-top: 18px; }
.sar-sens-title { margin: 0 0 4px; font-size: 0.95rem; }
.sar-sens-meta { font-size: 0.78rem; color: var(--muted, #6b7280); margin-bottom: 8px; }
.sar-sens-scroll { overflow-x: auto; }
.sar-sens-table { border-collapse: collapse; font-size: 0.8rem; min-width: 560px; }
.sar-sens-table th, .sar-sens-table td {
  padding: 5px 10px; text-align: right; border-bottom: 1px solid var(--border, #e5e7eb);
  white-space: nowrap;
}
.sar-sens-table thead th { font-weight: 600; }
.sar-sens-table tbody th { text-align: left; font-weight: 600; }
.sar-sens-table .sar-sens-basecol { background: rgba(184, 134, 45, 0.08); }
.sar-sens-table th.sar-sens-baserow { color: var(--accent, #92610f); }
.sar-sens-table td.sar-sens-basecell {
  background: rgba(184, 134, 45, 0.85); color: #fff; font-weight: 700;
}
.sar-sens-loading, .sar-sens-error { font-size: 0.8rem; color: var(--muted, #6b7280); }
.sar-sens-error { color: #b91c1c; }
.sar-sens-note { font-size: 0.72rem; color: var(--muted, #6b7280); margin-top: 6px; }

/* ── CaaS proposal modal ── */
.caas-saved {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  background: rgba(184, 134, 45, 0.08); border-radius: 6px; font-size: 0.82rem;
}
.caas-upload-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.caas-adjustments summary { cursor: pointer; font-size: 0.85rem; color: var(--muted, #6b7280); }
.caas-adjustments[open] summary { margin-bottom: 6px; }
.caas-adjustments label { display: block; margin: 6px 0; font-size: 0.85rem; }

/* ── CaaS generation progress ── */
/* Post-generation review notes. A negative net owner value is the worst thing
   this deck can say, so warnings get their own bordered block — a run-on
   status line let it read like a chart placeholder. */
.caas-warnings {
  list-style: none; margin: 10px 0 6px; padding: 8px 10px;
  border: 1px solid #b91c1c; border-radius: 6px; background: #fef2f2;
  font-size: 0.82rem; line-height: 1.4; color: #7f1d1d;
}
.caas-warnings li { padding: 3px 0; }
.caas-warnings li + li { border-top: 1px solid #fecaca; }

/* Acknowledgement gate: the deck is generated and held in memory, never
   written to disk, until the user accepts the warning above it. */
.caas-confirm {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px; margin: 0 0 8px; padding: 10px;
  border: 1px solid #b91c1c; border-radius: 6px; background: #fff;
  font-size: 0.84rem; color: #7f1d1d;
}
.caas-confirm-actions { display: flex; gap: 8px; }

.caas-progress { margin: 10px 0 4px; }
.caas-progress-track {
  height: 6px; border-radius: 3px; background: var(--border, #e5e7eb); overflow: hidden;
}
.caas-progress-bar {
  height: 100%; width: 0; border-radius: 3px; background: var(--accent, #b8862d);
  transition: width 400ms ease;
}
.caas-progress-bar--failed { background: #b91c1c; }
/* Server-side work is unobservable from the browser, so it is shown as motion
   rather than a fake percentage (see rent_parser.js progress notes). */
.caas-progress-bar--indeterminate {
  background: linear-gradient(90deg, #e5e7eb 0%, #2563eb 40%, #2563eb 60%, #e5e7eb 100%);
  background-size: 250% 100%;
  animation: caas-progress-slide 1.4s linear infinite;
}
@keyframes caas-progress-slide {
  from { background-position: 150% 0; }
  to { background-position: -150% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .caas-progress-bar--indeterminate { animation: none; background: #2563eb; opacity: 0.55; }
}
.caas-progress-steps { list-style: none; margin: 8px 0 0; padding: 0; font-size: 0.78rem; }
.caas-step { padding: 2px 0; color: var(--muted, #6b7280); }
.caas-step span { display: inline-block; width: 1em; }
.caas-step--active { color: var(--ink, #1f2a37); font-weight: 600; }
.caas-step--done { color: var(--muted, #6b7280); }
.caas-step--failed { color: #b91c1c; font-weight: 600; }
