/* ==========================================================
   REUW Global Stylesheet
   Standardized typography and design tokens
   ========================================================== */

/* ---- System Font (Calibri) ---- */
/* No @import needed — Calibri is a system font */

/* ---- CSS Custom Properties ---- */
:root {
    /* Typography */
    --font-sans: 'Calibri', 'Segoe UI', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    --font-ui: 'Inter', 'Segoe UI', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    --font-mono: 'SF Mono', 'Fira Code', 'Cascadia Code', 'Consolas', monospace;

    /* REUW Institutional Color System */
    --bg-primary: #060d17;
    --bg-secondary: #122a48;
    --bg-tertiary: #1a3557;
    --primary-text: #e8edf4;
    --secondary-text: #8494ac;       /* AA on all three bg tiers (was #7888a0 — 3.9:1 on bg-tertiary) */
    --text-tertiary: #708299;        /* AA on bg-primary (was #5a6a80 — 3.3:1) */
    --border-color: #24395a;
    --border-secondary: #142236;
    --accent-color: #c9a84c;
    --accent-text: #c9a84c;          /* gold when used as TEXT — same as accent on dark, but
                                        darkened in light theme where #c9a84c/#b8923e fail AA
                                        on white. New text rules should use this, not accent. */
    --accent-color-hover: #a07e2e;   /* darker gold — pressed/standard hover */
    --accent-color-light: #d8bd66;   /* lighter gold — CTA "lift" hover (New Deal button, homepage primary) */
    --success-color: #10b981;
    --warning-color: #f59e0b;
    --danger-color: #f25555;         /* AA on card-bg (was #ef4444 — 4.35:1) */
    --info-color: #60a5fa;           /* blue status — AA (>=4.9:1) as text on all dark bg tiers */
    --card-bg: #122a48;
    --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);

    /* Surface radius tokens (Phase 0, Lane A). Standard card/panel vs small
       control. ADDITIVE — existing rules keep their literals until migrated
       tab-by-tab; nothing changes visually until a rule opts in via var(). */
    --radius: 0.5rem;       /* cards, panels */
    --radius-sm: 4px;       /* inputs, chips, small controls */

    /* Muted-accent for subtle decorations (e.g. text-shadow on dark cards) */
    --accent-subtle: #3d2e0f;

    /* ---- Z-Index Scale ----
       Replaces the ad-hoc 9998–10501 chaos. Use these tokens, not literals.
       Numbers are aligned with the existing app's stacking reality (the
       loading overlay sits at 99999, primary modals at 10000-10500). New
       code should use these tokens; old code can migrate one rule at a
       time. Modal-stacked is for one modal launched from another. */
    --z-dropdown:         1050;   /* form select dropdowns, etc. */
    --z-sticky:           1055;   /* sticky table headers, sticky footers */
    --z-app-header:       1100;   /* deal page top nav (logo + tab row) — above sticky thead, below datepickers/modals */
    --z-datepicker:       9990;   /* inline date pickers (above content, below modals) */
    --z-modal-backdrop:  10059;
    --z-modal:           10060;   /* matches existing #createNewDealModal */
    --z-modal-stacked:   10500;   /* matches existing #newDealTabs nested modal */
    --z-popover:         10600;   /* tooltips, hovercards above modals */
    --z-toast:           99999;   /* loading overlay, error overlay, toasts — top of all */

    /* ---- Layout dimensions ---- */
    --app-header-h:       96px;   /* fallback only — index_init.js keeps this synced to
                                     #reuw-top-nav's real height, which varies (the tab row
                                     wraps to 2+ rows at laptop widths; logo shrinks <=768px) */
}

/* The deal shell (index.html <body class="deal-shell">) renders in Inter:
   the font was loaded there for years but never applied — body copy and
   tables silently fell back to Calibri under Inter nav chrome. Scoped as a
   token flip so standalone legacy pages keep the Calibri default. */
body.deal-shell {
    --font-sans: var(--font-ui);
}

/* =====================================================================
   LIGHT THEME  (opt-in via <html data-theme="light">) — Lane A, 2026-06-28
   Token-flip only: every component reads these vars, so re-mapping them
   re-themes the whole app. DARK is the default (no attribute or
   data-theme="dark"). The toggle is persisted to localStorage by
   static/js/theme.js; a no-flash inline <head> snippet sets data-theme
   before first paint. FIRST PASS palette — will iterate on Carson's eye.
   ===================================================================== */
:root[data-theme="light"] {
    /* WHITE-dominant institutional light. Surfaces are neutral near-white (no
       blue cast); blue + gold appear only as ACCENTS (inputs, totals, labels). */
    --bg-primary:        #e8ebf0;   /* light-grey page so white containers read as panels (Carson 2026-07-13) */
    --bg-secondary:      #ffffff;   /* raised panels / inputs */
    --bg-tertiary:       #f2f3f5;   /* neutral light fills / hovers */
    --primary-text:      #18263c;   /* dark ink */
    --secondary-text:    #5c6675;   /* neutral slate */
    --text-tertiary:     #6d7480;   /* AA on near-white (was #8b929e — 3.05:1) */
    --border-color:      #d5dae1;   /* slightly stronger so container edges show */
    --border-secondary:  #eef0f2;
    --accent-color:      #b8923e;   /* gold accent — fills/borders only (2.9:1 as text on white) */
    --accent-text:       #8a6d2a;   /* gold as TEXT — AA (4.9:1) on the near-white surfaces */
    --accent-color-hover:#946f24;
    --accent-color-light:#c9a84c;
    --card-bg:           #ffffff;   /* white cards */
    --card-shadow:       0 1px 3px rgba(30, 41, 59, 0.07), 0 1px 2px rgba(30, 41, 59, 0.05);
    --accent-subtle:     #f6eccf;   /* light gold tint */
    /* Status colors as TEXT on white: the dark-theme #10b981/#f59e0b/#f25555
       sit below AA on a light surface. Darken for light mode (fills/borders
       that also use these read fine — the darker shades still contrast). */
    --success-color:     #0f8a5f;   /* AA on white (was #10b981 — 2.8:1) */
    --warning-color:     #b7791f;   /* AA on white (was #f59e0b — 2.1:1) */
    --danger-color:      #d13b3b;   /* AA on white (was #f25555 — 3.4:1) */
    --info-color:        #0b5ed7;   /* blue status — AA (>=5.3:1) as text on the near-white surfaces */
}

/* Light-theme shims: Bootstrap "light/white" text utilities mean "readable text"
   in this app — they must darken in light mode (else white-on-white). Bootstrap
   sets these with !important, so the override needs it too. */
:root[data-theme="light"] .text-light,
:root[data-theme="light"] .text-white { color: var(--primary-text) !important; }
:root[data-theme="light"] .text-muted { color: var(--secondary-text) !important; }
/* Safety net: pin the page + deal-content surfaces to the theme bg in light mode.
   The deal-shell wrappers are transparent over the body, so anything that left a
   dark surface behind the white cards now reads light. */
:root[data-theme="light"] body,
:root[data-theme="light"] #existing-deal-assumptions-root,
:root[data-theme="light"] #newDealTabsContent { background: var(--bg-primary); }
/* Dim the auth/settings gold geometric body overlays in light mode for a cleaner
   white (they read fine on dark; on white they add busy texture). */
:root[data-theme="light"] body::before,
:root[data-theme="light"] body::after { opacity: 0.05; }
/* Light-mode fixes (multi-agent audit 2026-06-28): components that kept a dark
   literal in light mode. Modal/card headers+footers use #081220 (dark) for the
   dark theme; give them a light surface in light. Button hover used a dark navy
   shadow. Dark theme unchanged (these are [data-theme=light]-scoped). */
:root[data-theme="light"] .modal-header,
:root[data-theme="light"] .modal-footer,
:root[data-theme="light"] .card-header,
:root[data-theme="light"] .card-footer { background: var(--bg-tertiary); color: var(--primary-text); }
:root[data-theme="light"] .btn-secondary:hover,
:root[data-theme="light"] .btn-outline-secondary:hover { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08); }
/* Light-mode fix (2026-07-06): the bare "Waterfall" <h5> (templates/tabs/
   waterfall.html) sets no color, so it inherits .tab-pane's dark-theme literal
   (#e2e8f0, further down this file) and reads ghost-white on the light page.
   Scope the pane's h5s back to ink; the .text-light h6s are handled by the
   shim above, and the modal titles inherit .modal-header's light color. */
:root[data-theme="light"] #tabpane-equity-waterfall h5 { color: var(--primary-text); }
/* Same fix for the Returns pane's "Returns" <h5> (templates/tabs/returns.html). */
:root[data-theme="light"] #tabpane-investment-summary h5 { color: var(--primary-text); }
/* Light-mode fix (2026-07-06): Bootstrap's btn-outline-light is built for dark
   surfaces; the app's base override (further down this file) keeps a white-alpha
   border + hover that vanish on the light theme's white panels. Give these
   buttons the app's .btn-outline-secondary look instead. Buttons on the legacy
   rent-roll module's stay-dark inline panels are excepted in tab-theme.css. */
:root[data-theme="light"] .btn-outline-light {
    background: var(--bg-tertiary);
    border-color: var(--border-color);
    color: var(--primary-text);
}
:root[data-theme="light"] .btn-outline-light:hover {
    background: var(--border-color);
    border-color: var(--accent-color);
    color: var(--primary-text);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}
/* Light-mode fix (2026-07-06): the dark-theme .btn-close inversion (further down
   this file) leaves every modal close X white — invisible once the modal
   header/footer surfaces flip light. Restore the dark X inside modals (covers
   .btn-close-white too — every close button here carries both classes, and this
   outranks Bootstrap 5.3.3's white-filter on specificity). Toasts stay excluded
   on purpose: their text-bg-* fills are saturated in both themes, so the white
   X is still right there. */
:root[data-theme="light"] .modal-content .btn-close { filter: none; }
/* EXCEPTION: the legacy floorplan-grouping modal (?rr_legacy=1,
   rentroll_legacy.js) pins its header dark with an inline background:#081220
   that no token flips — keep the inverted X on it (same filter literal as the
   dark-theme .btn-close rule below). */
:root[data-theme="light"] .modal-header[style*="#081220"] .btn-close {
    filter: invert(1) brightness(2);
}

/* ---- Base Typography ---- */
html, body {
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* Universal font reset */
*, *::before, *::after {
    font-family: inherit;
}

/* Headings */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-sans);
    font-weight: 600;
    letter-spacing: -0.01em;
}

/* Body text */
p, span, div, label, a, li, td, th, input, select, textarea, button, option {
    font-family: var(--font-sans);
}

/* ---- Tabular Numbers ----
   All numeric / financial data should use tabular-nums so columns align.
   Apply via class or automatically on number inputs. */
input[type="number"],
.numeric,
.money-field,
.data-value,
.tabular-nums,
table td:not(:first-child),
.form-control[readonly],
.financial-value {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    font-family: var(--font-sans);
}

/* ---- Monospace (intentional) ----
   Only dev consoles and actual code blocks should be monospace. */
code, pre, kbd, samp,
.font-mono,
.dev-console,
#dev-log {
    font-family: var(--font-mono);
}

/* ---- Form Controls ---- */
.form-control,
.form-select {
    font-family: var(--font-sans);
    font-size: 0.875rem;
}

/* ---- Bootstrap Overrides ---- */
.btn {
    font-family: var(--font-sans);
}

.table {
    font-family: var(--font-sans);
}

.modal-content {
    font-family: var(--font-sans);
}

.dropdown-menu,
.dropdown-item {
    font-family: var(--font-sans);
}

.nav-link,
.nav-pills .nav-link {
    font-family: var(--font-sans);
}

.badge {
    font-family: var(--font-sans);
    font-variant-numeric: tabular-nums;
}

/* ---- Number Input Spinner Removal ---- */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* ==========================================================
   Bootstrap Component Theming
   Relocated from templates/index.html inline <style> blocks.
   These rules paint Bootstrap components in the REUW
   institutional dark/gold palette globally.
   ========================================================== */

/* ---- Dropdowns ---- */
.dropdown-menu {
    background: linear-gradient(135deg, #2d5f8d 0%, #1e4366 100%);
    border: 2px solid var(--border-color);
    box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    border-radius: 3px;
}

.dropdown-item {
    color: var(--primary-text);
    padding: 0.5rem 1rem;
}

.dropdown-item:hover {
    background: rgba(126,200,255,0.2);
    color: var(--accent-color);
}

.dropdown-divider {
    border-top-color: rgba(255,255,255,0.2);
}

/* ---- List Groups ---- */
.list-group-item {
    background: rgba(255,255,255,0.05);
    border: 1px solid var(--border-color);
    color: var(--primary-text);
}

.list-group-item:hover {
    background: rgba(255,255,255,0.1);
}

.list-group-item.active {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: #0a2942;
}

/* ---- Table Containers ---- */
.table-responsive {
    background: rgba(26, 31, 40, 0.6);
    position: relative;
    z-index: 2;
}
/* Light mode: that dark charcoal fill would otherwise sit as a grey slab behind
   the transparent table rows on the white page — it was the "dashboard is grey,
   impossible to read" bug (the deal-row wrapper). Let the themed white surface
   (card/section) behind show through. Applies to every .table-responsive. */
:root[data-theme="light"] .table-responsive { background: transparent; }

/* ---- Modals ---- */
.modal-content {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.4);
    color: var(--primary-text);
}

.modal-header {
    background: #081220;
    border-bottom: 1px solid var(--border-color);
    color: var(--primary-text);
    padding: 1rem 1.25rem;
}

.modal-body {
    color: var(--primary-text);
    padding: 1.25rem;
}

.modal-footer {
    background: #081220;
    border-top: 1px solid var(--border-color);
    padding: 0.875rem 1.25rem;
}

.modal-title {
    color: var(--primary-text);
    font-weight: 600;
    text-transform: none;
    letter-spacing: normal;
    font-size: 1.125rem;
}

/* ---- Cards ---- */
.card {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.3);
    color: var(--primary-text);
    position: relative;
    z-index: 2;
}

.card-header {
    background: #081220;
    border-bottom: 1px solid var(--border-color);
    color: var(--primary-text);
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
    font-size: 0.875rem;
    padding: 0.75rem 1rem;
}

.card-body {
    color: var(--primary-text);
    padding: 1.25rem 1rem;
}

.card-footer {
    background: #081220;
    border-top: 1px solid var(--border-color);
    color: var(--secondary-text);
    padding: 0.75rem 1rem;
}

/* ---- Buttons ---- */
.btn {
    font-weight: 500;
    letter-spacing: normal;
    text-transform: none;
    padding: 0.625rem 1.25rem;
    border-radius: 6px;
    border-width: 1px;
    transition: all 0.15s ease;
    font-size: 0.875rem;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}

.btn-primary {
    background: #c9a84c;
    border-color: #c9a84c;
    color: #ffffff;
    font-weight: 500;
}

.btn-primary:hover {
    background: #a07e2e;
    border-color: #a07e2e;
    box-shadow: 0 2px 6px rgba(201, 168, 76, 0.15);
}

.btn-success {
    background: #10b981;
    border-color: #10b981;
    color: #ffffff;
    font-weight: 500;
}

.btn-success:hover {
    background: #059669;
    border-color: #059669;
    box-shadow: 0 2px 6px rgba(16, 185, 129, 0.4);
}

.btn-danger {
    background: #ef4444;
    border-color: #ef4444;
    color: #ffffff;
    font-weight: 500;
}

.btn-danger:hover {
    background: #dc2626;
    border-color: #dc2626;
    box-shadow: 0 2px 6px rgba(239, 68, 68, 0.4);
}

.btn-secondary, .btn-outline-secondary {
    background: var(--bg-tertiary);
    border-color: var(--border-color);
    color: var(--primary-text);
    font-weight: 500;
}

.btn-secondary:hover, .btn-outline-secondary:hover {
    background: var(--border-color);
    border-color: var(--accent-color);
    box-shadow: 0 2px 6px rgba(26, 42, 66, 0.4);
}

.btn-outline-primary {
    background: transparent;
    border-color: var(--accent-color);
    color: var(--accent-color);
}

.btn-outline-primary:hover {
    background: rgba(201, 168, 76, 0.1);
    border-color: #a07e2e;
}

/* ---- Gold accent CTA (canonical) ----
   ONE gold call-to-action. `.btn-accent` (fill) = gold bg + page-bg text
   (dark navy in dark theme, near-white in light — mirrors the app's gold-CTA
   convention). `.btn-accent-outline` = transparent bg, gold border + AA-gold
   text. Both read in either theme via tokens. Replaces the scattered
   id-scoped gold rules (#rr-floorplan-btn & siblings in tab-theme.css),
   .demo-analyze-btn, and .t12-empty-upload-submit. */
.btn-accent {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: var(--bg-primary);
    font-weight: 600;
}
.btn-accent:hover {
    background: var(--accent-color-hover);
    border-color: var(--accent-color-hover);
    color: var(--bg-primary);
    box-shadow: 0 2px 6px rgba(201, 168, 76, 0.15);
}
.btn-accent:focus-visible {
    outline: 2px solid var(--accent-color-light);
    outline-offset: 2px;
}
/* Light-mode ink (2026-07-06): `color: var(--bg-primary)` resolves to the
   near-white page bg here — 2.8:1 on the #b8923e gold fill, an AA fail. Use
   the theme's dark ink instead (5.2:1 on the gold — same dark-ink-on-gold
   look as dark theme). Hover keeps the ink and lifts to the LIGHTER gold
   (6.7:1; the app's existing CTA-lift hover, cf. --accent-color-light)
   because the darker #946f24 hover gold passes AA with neither ink (3.3:1)
   nor near-white (4.4:1). */
:root[data-theme="light"] .btn-accent {
    color: var(--primary-text);
}
:root[data-theme="light"] .btn-accent:hover {
    background: var(--accent-color-light);
    border-color: var(--accent-color-light);
    color: var(--primary-text);
}
.btn-accent-outline {
    background: transparent;
    border-color: var(--accent-color);
    color: var(--accent-text);
}
.btn-accent-outline:hover {
    background: rgba(201, 168, 76, 0.12);
    border-color: var(--accent-color);
    color: var(--accent-text);
}
.btn-accent-outline:focus-visible {
    outline: 2px solid var(--accent-color-light);
    outline-offset: 2px;
}

/* ---- Alerts ---- */
.alert {
    border: 2px solid;
    border-radius: 3px;
    font-weight: 500;
}

.alert-info {
    background: rgba(126,200,255,0.15);
    border-color: var(--accent-color);
    color: var(--accent-color);
}

.alert-success {
    background: rgba(102,255,153,0.15);
    border-color: var(--success-color);
    color: var(--success-color);
}

.alert-warning {
    background: rgba(255,217,102,0.15);
    border-color: var(--warning-color);
    color: var(--warning-color);
}

.alert-danger {
    background: rgba(255,107,107,0.15);
    border-color: var(--danger-color);
    color: var(--danger-color);
}

/* ==========================================================
   Bootstrap Component Theming (additional)
   Smaller / less-frequently-used Bootstrap components themed
   to the institutional dark/gold palette. Relocated from
   templates/index.html. All ID-scoped versions stay where they
   are (e.g. #deals-dashboard) — this section covers the bare
   class selectors that apply site-wide.
   ========================================================== */

/* Charts & Canvas */
canvas {
    background: rgba(0,0,0,0.2);
    border: 1px solid var(--border-color);
    border-radius: 3px;
}

/* Progress bars */
.progress {
    background: rgba(255,255,255,0.1);
    border: 1px solid var(--border-color);
    border-radius: 3px;
}
.progress-bar {
    background: var(--accent-color);
}

/* Breadcrumbs */
.breadcrumb {
    background: rgba(255,255,255,0.05);
    border: 1px solid var(--border-color);
    border-radius: 3px;
}
.breadcrumb-item {
    color: var(--secondary-text);
}
.breadcrumb-item.active {
    color: var(--accent-color);
}
.breadcrumb-item + .breadcrumb-item::before {
    color: var(--border-color);
}

/* Pagination */
.pagination .page-link {
    background: rgba(255,255,255,0.08);
    border: 2px solid var(--border-color);
    color: var(--primary-text);
    margin: 0 2px;
}
.pagination .page-link:hover {
    background: rgba(255,255,255,0.15);
    border-color: var(--accent-color);
    color: var(--accent-color);
}
.pagination .page-item.active .page-link {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: #0a2942;
}

/* Tooltips & Popovers */
.tooltip-inner {
    background: linear-gradient(135deg, #2d5f8d 0%, #1e4366 100%);
    border: 2px solid var(--border-color);
    color: var(--primary-text);
    font-weight: 500;
}
.popover {
    background: linear-gradient(135deg, #2d5f8d 0%, #1e4366 100%);
    border: 2px solid var(--border-color);
}
.popover-header {
    background: rgba(255,255,255,0.1);
    border-bottom: 2px solid var(--border-color);
    color: var(--primary-text);
}
.popover-body {
    color: var(--primary-text);
}

/* Input groups */
.input-group-text {
    background: rgba(255,255,255,0.1);
    border: 2px solid var(--border-color);
    color: var(--primary-text);
    font-weight: 500;
}

/* Accordion */
.accordion-item {
    background: rgba(255,255,255,0.05);
    border: 2px solid var(--border-color);
    margin-bottom: 0.5rem;
}
.accordion-button {
    background: rgba(255,255,255,0.08);
    color: var(--primary-text);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: 0.9rem;
}
.accordion-button:not(.collapsed) {
    background: rgba(126,200,255,0.15);
    color: var(--accent-color);
    box-shadow: none;
}
.accordion-button::after {
    filter: invert(1) brightness(2);
}
.accordion-body {
    background: rgba(255,255,255,0.03);
    color: var(--primary-text);
}

/* Offcanvas */
.offcanvas {
    background: linear-gradient(135deg, #2d5f8d 0%, #1e4366 100%);
    border-left: 2px solid var(--border-color);
}
.offcanvas-header {
    border-bottom: 2px solid var(--border-color);
}
.offcanvas-title {
    color: var(--primary-text);
}

/* Small text & muted.
   Bootstrap sets `.text-muted` with !important natively, so we match. */
.text-muted {
    color: var(--secondary-text) !important;
}

/* Bootstrap's .text-secondary is the app's "other" muted grey — ~100 call
   sites mix it freely with .text-muted (returns.html, financing.js,
   rentroll.js). Pin both to the same token so muted text is one grey
   everywhere and correctly flips in light theme. The !important must stay
   (Bootstrap's own .text-secondary is !important and loads first), so
   surfaces that do NOT flip with the theme re-map --secondary-text itself
   instead of fighting the pin: the always-white ledger body (.app-table
   tbody, app-tables.css) and the stay-dark panels (.app-card-very-dark
   below; .border[style*="#0f1319"], tab-theme.css) (2026-07-06). */
.text-secondary {
    color: var(--secondary-text) !important;
}

small, .small {
    color: var(--secondary-text);
}

/* Links */
a {
    color: var(--accent-color);
    text-decoration: none;
    cursor: pointer;
}
a:hover {
    color: #9ed8ff;
    text-decoration: underline;
}

/* Hurdle-mechanics modal triggers in the Returns Distribution table.
   In-table label stays the standard text color so the table reads cleanly;
   gold underline on hover/focus signals the row is clickable. */
.is-hurdle-link {
    color: var(--primary-text);
    text-decoration: none;
    cursor: pointer;
}
.is-hurdle-link:hover,
.is-hurdle-link:focus {
    color: var(--accent-color);
    text-decoration: underline;
    text-decoration-color: var(--accent-color);
    text-underline-offset: 3px;
}

/* Hurdle I/II mechanics modals — 3-tier z-index lift (matches the pattern
   used by #createNewDealModal, #rs_deck_preview_modal, etc.). The modals
   are rendered inside the deeply-nested Waterfall tab-pane; without this
   the modal-backdrop sits ABOVE the modal-content and the table is not
   interactable. The `~ .modal-backdrop` sibling selector targets the
   backdrop Bootstrap injects next to the modal at show-time. */
#hurdle-1-modal,
#hurdle-2-modal {
    z-index: var(--z-modal) !important;
}
#hurdle-1-modal .modal-dialog,
#hurdle-2-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#hurdle-1-modal .modal-content,
#hurdle-2-modal .modal-content {
    position: relative;
    z-index: calc(var(--z-modal) + 2) !important;
}
#hurdle-1-modal ~ .modal-backdrop,
#hurdle-2-modal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* T-12 partial-year warning modal — same 3-tier lift so the modal is
   clickable when fired from inside the deeply-nested T-12 tab pane. */
#t12-partial-year-modal { z-index: var(--z-modal) !important; }
#t12-partial-year-modal .modal-dialog { z-index: calc(var(--z-modal) + 1) !important; }
#t12-partial-year-modal .modal-content { position: relative; z-index: calc(var(--z-modal) + 2) !important; }
#t12-partial-year-modal ~ .modal-backdrop { z-index: calc(var(--z-modal) - 1) !important; }

/* Make sure clickable elements work */
button, a, [onclick], [role="button"], .clickable {
    cursor: pointer;
}

/* HR dividers */
hr {
    border-color: var(--border-color);
    opacity: 0.5;
}

/* Code blocks */
code {
    background: rgba(0,0,0,0.3);
    border: 1px solid var(--border-color);
    color: var(--accent-color);
    padding: 0.2em 0.4em;
    border-radius: 3px;
    font-family: var(--font-mono);
}
pre {
    background: rgba(0,0,0,0.3);
    border: 2px solid var(--border-color);
    color: var(--primary-text);
    padding: 1rem;
    border-radius: 3px;
}
pre code {
    background: none;
    border: none;
    padding: 0;
}

/* Spinners */
.spinner-border {
    border-color: var(--accent-color);
    border-right-color: transparent;
}
.spinner-grow {
    background-color: var(--accent-color);
}

/* Close buttons */
.btn-close:focus {
    box-shadow: 0 0 0 0.25rem rgba(126,200,255,0.25);
}

/* Bootstrap text/bg utility overrides.
   Bootstrap 5 uses !important natively on these utilities, so we must match. */
.text-dark {
    color: var(--primary-text) !important;
}
.bg-dark {
    background-color: rgba(0,0,0,0.3) !important;
}
.bg-light {
    background-color: rgba(255,255,255,0.1) !important;
}
.text-light {
    color: var(--primary-text) !important;
}

/* Form check inputs */
.form-check-input {
    background-color: rgba(255,255,255,0.1);
    border-color: var(--border-color);
}
.form-check-input:checked {
    background-color: var(--accent-color);
    border-color: var(--accent-color);
}
.form-check-label {
    color: var(--primary-text);
}

/* File inputs */
.form-control[type="file"]::file-selector-button {
    background: rgba(255,255,255,0.15);
    border: 1px solid var(--border-color);
    color: var(--primary-text);
    padding: 0.375rem 0.75rem;
    margin-right: 0.75rem;
    border-radius: 3px;
}
.form-control[type="file"]::file-selector-button:hover {
    background: rgba(255,255,255,0.25);
}

/* ==========================================================
   Deal Dashboard
   #deals-dashboard and .property-level-metrics-* styling.
   These are global enough that they belong here rather than
   in index.html. (The old shimmer keyframe + KPI ID list that
   glowed the headline numbers was removed 2026-07-11.)
   ========================================================== */

/* Hide the deals dashboard when viewing a single deal.
   #deals-dashboard has inline `style="display: flex"` (specificity 1,0,0,0),
   so this rule needs !important to win — otherwise the dashboard shows
   above the deal tabs in existing-deal-mode. */
body.existing-deal-mode #deals-dashboard {
    display: none !important;
}

/* Property Level Metrics card — gold theme */
/* The Returns metrics-row card is a bare .border div with no bg of its own —
   give it the themed card surface so it flips with the theme. Retargeted
   2026-07-06: the row was #property-image-row (image + metrics) until the
   property-photo panel was removed and returns.html renamed the row to
   #property-metrics-row; the stale id left the card transparent ("ghost
   card") in both themes. */
/* ========== PROPERTY LEVEL METRICS — KPI tile strip (2026-07-10) ==========
   Replaces the old glow-table treatment (gold text-shadows, hover-lift card).
   Quiet institutional tiles: hairline rules, uppercase muted labels, big
   tabular-nums values; gold reserved for the two hero return metrics. JS
   paints values by id and may toggle Bootstrap text-success/warning/danger
   on .plm-value — those keep priority over the base colors here. */
.plm-card {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 0.75rem;
    padding: 1rem 1.25rem 1.15rem;
}
.plm-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 0.85rem; }
.plm-title {
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-size: 0.8rem;
    color: var(--primary-text);
}
.plm-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 0;
}
.plm-grid.plm-returns { border-top: 2px solid var(--accent-color); }
.plm-grid.plm-acq { border-top: 1px solid var(--border-color); margin-top: 0.9rem; }
/* stat-tile treatment: hairline column separators so each metric reads as
   its own cell; first tile in each row flush-left */
.plm-tile {
    padding: 0.8rem 1rem 0.65rem 1.1rem;
    min-width: 0;
    border-left: 1px solid var(--border-color);
}
.plm-grid .plm-tile:first-child { border-left: none; padding-left: 0; }
.plm-label {
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--secondary-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.plm-value {
    font-size: 1.3rem;
    font-weight: 750;
    letter-spacing: -0.015em;
    font-variant-numeric: tabular-nums;
    color: var(--primary-text);
    line-height: 1.15;
    margin-top: 2px;
}
.plm-value { font-size: 1.4rem; }
.plm-hero .plm-value { color: var(--accent-color); font-size: 1.7rem; }
/* Loading state: values start as '--' until the IRA/summary responses land.
   A gentle opacity shimmer reads as "loading" instead of "broken/empty". */
.plm-value.text-secondary { color: var(--secondary-text); }
@media (prefers-reduced-motion: no-preference) {
    .plm-value.text-secondary { animation: plm-loading 1.6s ease-in-out infinite; }
}
@keyframes plm-loading { 0%, 100% { opacity: 0.85; } 50% { opacity: 0.35; } }
@media (max-width: 992px) {
    .plm-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ==========================================================
   Financing tab — Actor-color tinted inputs and labels
   The financing tab visually distinguishes each capital-stack actor
   (Senior, Mezz, Refi, etc.) by tinting its rate inputs and small
   labels with a distinct color. These patterns appeared verbatim ~30
   times in financing.html and the de_refi assumptions block.

   Naming: -blue/skyblue/purple/green/magenta/orange/gold/pink. Use
   the role mapping below as a reference (mapping is by convention,
   not enforced):
       Senior Loan       -> blue   (#8ecdf7 light blue)
       SOFR rate         -> skyblue (#7ec8ff sky)
       Mezz/Pref Equity  -> purple (#b8a9e8)
       Refinancing Loan  -> green  (#aee8a0)
       DSCR threshold    -> magenta (#e0a0ff)
       Costs             -> orange (#ff8c69)
       Year fields       -> gold   (#f0c674)
       UW Rate           -> pink   (#ff9999)
   ========================================================== */

/* Compact rate-input base (height/font/padding) — width stays inline since
   it varies between 55-90px depending on the field. Pair with .fin-tint-*. */
.fin-rate-input {
    height: 22px;
    font-size: 0.65rem;
    padding: 0 4px;
    text-align: center;
}

.fin-tint-blue     { background: rgba(142,205,247,0.12); border: 1px solid rgba(142,205,247,0.35); color: #8ecdf7; }
.fin-tint-skyblue  { background: rgba(126,200,255,0.12); border: 1px solid rgba(126,200,255,0.35); color: #7ec8ff; }
.fin-tint-purple   { background: rgba(184,169,232,0.12); border: 1px solid rgba(184,169,232,0.35); color: #b8a9e8; }
.fin-tint-green    { background: rgba(174,232,160,0.12); border: 1px solid rgba(174,232,160,0.35); color: #aee8a0; }
.fin-tint-magenta  { background: rgba(224,160,255,0.12); border: 1px solid rgba(224,160,255,0.35); color: #e0a0ff; }
.fin-tint-orange   { background: rgba(255,140,105,0.12); border: 1px solid rgba(255,140,105,0.35); color: #ff8c69; }
.fin-tint-gold     { background: rgba(240,198,116,0.12); border: 1px solid rgba(240,198,116,0.35); color: #f0c674; }
.fin-tint-pink     { background: rgba(255,153,153,0.08); border: 1px solid rgba(255,153,153,0.25); color: #ff9999; }

/* Color-only variants for inline labels (no bg/border, just .color). */
.text-fin-blue     { color: #8ecdf7; }
.text-fin-skyblue  { color: #7ec8ff; }
.text-fin-purple   { color: #b8a9e8; }
.text-fin-green    { color: #aee8a0; }
.text-fin-magenta  { color: #e0a0ff; }
.text-fin-orange   { color: #ff8c69; }
.text-fin-gold     { color: #f0c674; }
.text-fin-pink     { color: #ff9999; }

/* Compact label (.55rem, no-wrap) used alongside fin-tint-* inputs. */
.fin-label-tiny {
    font-size: 0.55rem;
    white-space: nowrap;
}

/* Dashed-border wrapper: subtle "drop here / placeholder" panel */
.app-card-dashed {
    background: rgba(255, 255, 255, 0.05);
    border: 1px dashed rgba(255, 255, 255, 0.15);
    border-radius: 0.5rem;
}

/* Very dark card (deeper than --card-bg) — used for nested dim panels */
.app-card-very-dark {
    background: #121820;
    border: 1px solid rgba(255, 255, 255, 0.12);
}
/* Light-mode guard (2026-07-06): this deep fill has no light-theme counterpart,
   and with .tab-pane now inheriting theme ink (see the .tab-pane rule) the
   un-classed loan titles inside ("Senior Loan" etc., financing.html) would go
   dark-on-dark. Pin inherited text to the dark-theme ink literal — the
   --primary-text token flips to ink here, so the token can't be used. Same
   for muted text (2026-07-06): the .text-secondary/.text-muted !important
   pins resolve var(--secondary-text) per-element, so the inherited-ink guard
   can't reach them ("Constant" labels, financing.html) — remap the token to
   its dark value on this stay-dark surface (light's slate was ~3.1:1 on
   #121820; the dark value is ~5.8:1). */
:root[data-theme="light"] .app-card-very-dark {
    color: #e8edf4;
    --secondary-text: #8494ac;
}

/* Compact financing value-display (deep navy bg, sky-blue mono-style text) */
.fin-value-display {
    background: #0a0e14;
    color: #7ec8ff;
    font-weight: 600;
}

/* Property level metrics — extras */
.text-amber-soft  { color: #ffe0a0; }   /* light amber accent */
.text-amber-rich  { color: #ffcc66; }   /* richer amber accent */

/* ==========================================================
   Demographics tab utilities
   ========================================================== */

/* Demographics income stat card — now EXTENDS .app-stat-tile (Phase 4 batch 4).
   The element carries `app-stat-tile demo-stat-card`; the shared surface
   (bg/border) comes from .app-stat-tile and this rule keeps only the
   demographics-specific deltas: flex sizing in the summary row, centered text,
   and its rounder corners / roomier padding. Compound selector (2026-07-06):
   at plain .demo-stat-card (0,1,0) the deltas tied .app-stat-tile further down
   this sheet and lost radius/padding on source order — (0,2,0) keeps them. */
.app-stat-tile.demo-stat-card {
    flex: 1;
    min-width: 160px;
    border-radius: 0.75rem;
    padding: 0.85rem 1rem;
    text-align: center;
}

/* ==========================================================
   Property tab utilities
   ========================================================== */

/* Bare icon-only button (no bg, no border, just a click target). Used for
   gear/edit icons in property cards. */
.btn-icon-bare {
    background: none;
    border: none;
    font-size: 1rem;
    cursor: pointer;
    padding: 0.2rem 0.5rem;
}

/* Gold badge chip — small, dense, gold-tinted */
.app-badge-gold {
    background: rgba(201, 168, 76, 0.2);
    color: var(--accent-color);
    font-size: 0.55rem;
    font-weight: 600;
    padding: 1px 4px;
    border-radius: 2px;
    border: 1px solid rgba(201, 168, 76, 0.35);
}

/* Muted badge chip — same dimensions as .app-badge-gold, neutral tone.
   Used to annotate non-actionable info (e.g. a reconciliation residual
   caused by source-file rounding, not a categorization gap). */
.app-badge-muted {
    background: rgba(120, 136, 160, 0.18);
    color: var(--secondary-text);
    font-size: 0.55rem;
    font-weight: 600;
    padding: 1px 4px;
    border-radius: 2px;
    border: 1px solid rgba(120, 136, 160, 0.32);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    cursor: help;
}

/* ==========================================================
   Phase 0 (Lane A) semantic utilities — ADDITIVE
   New canonical classes for tab polish. Nothing uses them until
   tabs adopt them in Phase 1 (so this block is visually inert).
   ========================================================== */

/* Required badge — sibling of .app-badge-gold/-muted; amber "must complete"
   signal (distinct from gold-accent + info-cyan). */
.app-badge-req {
    background: rgba(245, 158, 11, 0.16);
    color: var(--warning-color);
    font-size: 0.55rem;
    font-weight: 600;
    padding: 1px 4px;
    border-radius: 2px;
    border: 1px solid rgba(245, 158, 11, 0.35);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Info badge — cyan annotation chip (matches the app's info/cost cyan). */
.app-badge-info {
    background: rgba(56, 189, 248, 0.14);
    color: #7ec8ff;
    font-size: 0.55rem;
    font-weight: 600;
    padding: 1px 4px;
    border-radius: 2px;
    border: 1px solid rgba(56, 189, 248, 0.32);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* ---- Background-less badges / chips (Phase 4 batch 4) ----
   Companions to Bootstrap `.badge`. Token border/text only, no fill. */
/* Outline badge: border follows whatever .text-* utility colors the badge, so
   `badge text-accent badge-outline` reads as a gold-outlined pill, etc. */
.badge-outline {
    background-color: transparent;
    border: 1px solid currentColor;
}
/* Neutral standalone chip: a background-less pill with a token border + muted
   text, for annotations that carry no .text-* utility of their own. */
.ndt-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    background-color: transparent;
    border: 1px solid var(--border-color);
    color: var(--secondary-text);
    border-radius: 2rem;
    padding: 0.2rem 0.6rem;
    font-size: 0.72rem;
    font-weight: 500;
    line-height: 1.2;
}
/* Loan-type badges (financing amort subtabs) — tokenized replacements for the
   Bootstrap bg-primary / bg-info / bg-warning fills (off the navy/gold palette).
   Tinted surface + token text/border; all three flip with the theme. */
.badge-loan-senior {
    background: color-mix(in srgb, var(--info-color) 16%, transparent);
    color: var(--info-color);
    border: 1px solid color-mix(in srgb, var(--info-color) 40%, transparent);
}
.badge-loan-mezz {
    background: color-mix(in srgb, var(--accent-color) 16%, transparent);
    color: var(--accent-text);
    border: 1px solid color-mix(in srgb, var(--accent-color) 40%, transparent);
}
.badge-loan-refi {
    background: color-mix(in srgb, var(--warning-color) 16%, transparent);
    color: var(--warning-color);
    border: 1px solid color-mix(in srgb, var(--warning-color) 40%, transparent);
}
/* Light-mode guard (2026-07-06): financing's loan badges sit on
   .app-card-very-dark, which stays #121820 in light theme, but the tokens
   above DO flip — light's #0b5ed7/#8a6d2a inks and their 16% tints went
   dim/illegible on the dark card (2.7-2.9:1). Re-pin the tokens to their
   dark-theme values on that surface so the badges read identically in both
   themes (5.4-6.3:1). Literals because the tokens themselves are what flip —
   same pattern as the .app-card-very-dark ink guard above. Declared on the
   badges themselves so nothing else inside the card is touched. */
:root[data-theme="light"] .app-card-very-dark .badge-loan-senior,
:root[data-theme="light"] .app-card-very-dark .badge-loan-mezz,
:root[data-theme="light"] .app-card-very-dark .badge-loan-refi {
    --info-color: #60a5fa;
    --accent-color: #c9a84c;
    --accent-text: #c9a84c;
    --warning-color: #f59e0b;
}

/* Form field label (outside .app-table) — small uppercase muted caption.
   Replaces ad-hoc inline-styled <label>s during Phase 1. */
.app-field-label {
    display: block;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--secondary-text);
    margin-bottom: 0.25rem;
}

/* Card / panel heading — the standard title atop a .card or panel. */
.app-card-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--primary-text);
    letter-spacing: 0.01em;
    margin: 0 0 0.5rem;
}

/* Canonical KPI / metric stat tile (Phase 4 batch 4). ONE component for the
   bespoke per-tab metric tiles (waterfall GP/LP returns, tax mill-rate
   metrics, demographics income cards). A label slot + a value slot on a
   subtle elevated surface; the --sm modifier tightens it for dense metric
   rows. Token colors → flips with the theme. Paint computed values into
   .app-stat-tile__value and keep the element id unchanged. */
.app-stat-tile {
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 0.55rem 0.7rem;
}
.app-stat-tile__label {
    display: block;
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.25;
    color: var(--secondary-text);
    margin-bottom: 0.2rem;
}
.app-stat-tile__value {
    display: block;
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.1;
    color: var(--primary-text);
    font-variant-numeric: tabular-nums;
}
.app-stat-tile--sm { padding: 0.45rem 0.6rem; }
.app-stat-tile--sm .app-stat-tile__label { font-size: 0.6rem; }
.app-stat-tile--sm .app-stat-tile__value { font-size: 0.92rem; }

/* T-12 semantic-match review flag — small gold icon prefixing an account
   name whose category came from the embedding nearest-neighbor tier (not an
   exact / fuzzy guide hit). Signals "auto-matched, please verify". */
.t12-semantic-flag {
    color: var(--accent-color);
    margin-right: 4px;
    font-size: 0.8rem;
    cursor: help;
    vertical-align: -1px;
}

/* Shared empty-state upload card (Phase 4 batch 4). Generalized from the T-12
   empty state so the Rent Roll (and any future) empty upload state share one
   look. Use `.app-empty-upload-card` on new markup; `.t12-empty-upload-card`
   is kept as an alias so the existing t12.js markup keeps working. Shown in the
   same visual slot the loaded data occupies so the tab doesn't shift around
   between empty/loaded. */
.app-empty-upload-card,
.t12-empty-upload-card {
    max-width: 540px;
    margin: 0 auto;
    padding: 1.5rem;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 0.5rem;
    text-align: center;
    /* The card renders inside an .app-table td, which forces
       white-space:nowrap + ellipsis (table-layout:fixed). Reset here so the
       description wraps INSIDE the card instead of running past its edge. */
    white-space: normal;
    overflow-wrap: break-word;
}
.app-empty-upload-card .app-empty-upload-icon,
.t12-empty-upload-card .t12-empty-upload-icon {
    color: var(--accent-color);
    font-size: 2.25rem;
    line-height: 1;
    margin-bottom: 0.75rem;
}
.app-empty-upload-card .app-empty-upload-title,
.t12-empty-upload-card .t12-empty-upload-title {
    color: var(--primary-text);
    font-weight: 600;
    letter-spacing: 0.01em;
    margin-bottom: 0.25rem;
}
.app-empty-upload-card .app-empty-upload-desc,
.t12-empty-upload-card .t12-empty-upload-desc {
    color: var(--secondary-text);
    font-size: 0.85rem;
    margin-bottom: 1.25rem;
}
.app-empty-upload-card input[type="file"],
.t12-empty-upload-card input[type="file"] {
    max-width: 300px;
    background: var(--bg-primary);
    color: var(--primary-text);
    border: 1px solid var(--border-color);
    border-radius: 0.375rem;
}
.app-empty-upload-card input[type="file"]::file-selector-button,
.t12-empty-upload-card input[type="file"]::file-selector-button {
    background: rgba(201, 168, 76, 0.14);
    border: none;
    border-right: 1px solid var(--border-color);
    color: var(--primary-text);
    font-weight: 500;
    padding: 0.35rem 0.75rem;
    margin-right: 0.75rem;
}
.app-empty-upload-card input[type="file"]::file-selector-button:hover,
.t12-empty-upload-card input[type="file"]::file-selector-button:hover {
    background: rgba(201, 168, 76, 0.26);
}
/* .t12-empty-upload-submit (Process T-12 button) → canonical .btn-accent. */

/* ==========================================================
   Shared save-status indicator (.ndt-save-status)
   ONE component for the per-tab "Saving…/Saved/Save failed"
   cue next to the control the user touched. Driven by
   window.setSaveStatus (save_helpers.js) — replaces the five
   divergent per-tab badge implementations (Phase 4 batch 1).
   Idle = empty text + no state class → renders nothing.
   Global error toasts / retry stay in index_init.js — this is
   only the local inline indicator.
   ========================================================== */
.ndt-save-status {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--secondary-text);
    transition: color 0.15s ease;
}
/* Idle (no content) collapses entirely — avoids phantom flex-gap slots. */
.ndt-save-status:empty {
    display: none;
}
/* Reserved-footprint variant: keeps a fixed box while idle so the badge
   appearing/disappearing NEVER reflows the surrounding layout. Used where
   the badge is its row's only content (Property tab header) and collapsing
   would shift everything below. Overrides the :empty collapse above — same
   specificity, later in the sheet. No color/background, so it is invisible
   when idle and theme-neutral. */
.ndt-save-status--reserved,
.ndt-save-status--reserved:empty {
    display: inline-flex;
    justify-content: flex-end;
    min-width: 5.5rem;
    min-height: 1.2rem;
}
.ndt-save-status.is-saving {
    color: var(--secondary-text);
}
.ndt-save-status.is-saving i {
    display: inline-block;
    animation: ndt-save-spin 1s linear infinite;
}
.ndt-save-status.is-saved {
    color: var(--success-color);
}
.ndt-save-status.is-error {
    color: var(--danger-color);
}
@keyframes ndt-save-spin {
    to { transform: rotate(360deg); }
}

/* Pill toggle — gold (active) and ghost (inactive) variants */
.app-toggle-pill {
    border-radius: 0.4rem;
    padding: 0.15rem 0.5rem;
    font-size: 0.72rem;
    cursor: pointer;
}
.app-toggle-pill.is-on {
    background: rgba(201, 168, 76, 0.15);
    border: 1px solid rgba(201, 168, 76, 0.3);
    color: var(--accent-color);
}
.app-toggle-pill.is-off {
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: var(--secondary-text);
}

/* Header-style chip — uppercase, gold-bg, primary-text */
.app-chip-header {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    color: var(--primary-text);
    border-radius: 0.5rem;
    padding: 0.3rem 0.5rem;
    font-size: 0.8rem;
    text-transform: uppercase;
}

/* Translucent panel — generic semi-transparent backdrop with subtle border.
   Used for inline cards/wrappers across multiple tabs (~11 occurrences). */
.app-panel-translucent {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
}

/* Institutional input with thick (2px) blue border — used for renovation
   funding-source select on the deal page and tax DB state/muni selects. */
.app-input-thick {
    background-color: #ffffff;
    color: #0d6efd;
    border: 2px solid rgba(91, 165, 220, 0.85);
}

/* Subtle elevated panel (whiter than .app-card-subtle) */
.app-panel-elevated {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
}

/* Page-bg utility — avoids the inline `style="background:var(--bg-primary)"`
   pattern that proliferated across deal-page chrome. Bootstrap's .bg-primary
   is a different blue, hence the -app prefix. */
.bg-app-primary { background: var(--bg-primary); }

/* Additional financing actor color shorthands (700-weight value labels and
   .55rem text labels) used across the de_refi assumptions block. These
   complete the .text-fin-* family with the warmer/teal/lime variants. */
.text-fin-salmon  { color: #ffb399; }
.text-fin-lavender{ color: #d9b3ff; }
.text-fin-teal    { color: #66ffdd; }
.text-fin-lime    { color: #5cff8a; }
.text-fin-amber   { color: #ffc864; }
.text-fin-tangerine { color: #ffa500; }
.text-fin-violet  { color: #c080ff; }
.text-fin-success { color: #28a745; }
.text-fin-aqua    { color: #00e6b4; }

/* Financing chip — small rounded value-chip used in the Refi assumptions row
   to pair a label with a derived numeric value. Single uniform style (matches
   the canonical .app-table .is-section input look so chips feel consistent
   with the inputs they sit alongside). */
.fin-chip {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 4px;
    background: var(--tbl-input-section-bg, rgba(142, 205, 247, 0.15));
    border: 1px solid var(--tbl-input-section-bd, rgba(142, 205, 247, 0.35));
    color: var(--tbl-input-section-fg, #8ecdf7);
}

/* ==========================================================
   Final extracted utilities (small, low-frequency but still global)
   ========================================================== */

/* Soft gold shadow (used on property cards) */
.app-shadow-gold-soft { box-shadow: 0 2px 10px rgba(201, 168, 76, 0.08); }

/* Ghost outline (transparent bg, faint white border) */
.app-outline-faint {
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.15);
}

/* Success tint (green panel — used in tax projection cards and S&U calc inputs) */
.app-tint-success {
    background: rgba(40, 167, 69, 0.15);
    border: 1px solid rgba(40, 167, 69, 0.3);
}

/* Gold top divider (used between sections in S&U) */
.app-divider-top-gold {
    border-top: 2px solid rgba(201, 168, 76, 0.3);
}

/* Translucent panel — slightly more opaque variants for stronger separation */
.app-panel-translucent-08 {
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.2);
}

/* Navy-tinted panel with token border (form-section wrappers) */
.app-panel-tinted {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
}

/* ==========================================================
   Demographics tab — editorial "people" panel (ported from the
   Household Income app), re-themed to the dark navy/gold palette.
   Layout: 4-column stat block + (income chart | ethnicity bars).
   ========================================================== */
/* Demographics radius selector — clear toggle chips + an obvious Analyze action,
   so the "pick a radius, THEN Analyze" flow reads at a glance (was tiny faint
   checkboxes + a link-style button). Native checkbox is visually hidden; the
   chip reflects checked state. Multi-select preserved (compare radii). */
.demo-radii-group { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.demo-radii-label {
    font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.04em; color: var(--secondary-text); white-space: nowrap;
}
.demo-radii-chip {
    display: inline-flex; align-items: center; cursor: pointer; margin: 0;
    font-size: 0.78rem; font-weight: 600; line-height: 1; white-space: nowrap;
    padding: 0.34rem 0.62rem; border-radius: 999px;
    border: 1px solid var(--border-color); color: var(--secondary-text);
    background: var(--bg-tertiary); user-select: none;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.demo-radii-chip input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.demo-radii-chip:hover { border-color: var(--accent-color); color: var(--primary-text); }
.demo-radii-chip:has(input:checked) {
    background: var(--accent-color); border-color: var(--accent-color);
    color: #1a1206; font-weight: 700;
    box-shadow: 0 1px 4px rgba(201, 168, 76, 0.35);
}
.demo-radii-chip:has(input:focus-visible) { outline: 2px solid var(--accent-color); outline-offset: 2px; }
.demo-radii-arrow { color: var(--secondary-text); font-size: 0.8rem; margin: 0 0.1rem; opacity: 0.7; }
/* .demo-analyze-btn (Analyze / Refresh) → canonical .btn-accent. */
/* Location banner gets a defined card surface so the address + controls are
   readable in BOTH themes (was transparent → in light the dark-shimmed address
   read as dark-on-dark). */
#demographics-location-banner { background: var(--card-bg); border: 1px solid var(--border-color); }
/* "pick a radius, then Refresh" helper note. */
.demo-radii-hint { margin-top: 0.55rem; font-size: 0.74rem; color: var(--secondary-text); }
.demo-radii-hint .demo-radii-hint-star { color: var(--accent-color); font-weight: 700; }
#demographics-mount-point .demo-grid { display: block; margin-bottom: 1.5rem; }

#demographics-mount-point .eyebrow {
    display: block;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--secondary-text);
    margin-bottom: 0.75rem;
}

/* ---- 4-column stat block ---- */
#demographics-mount-point .stat-block {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 0.75rem;
    overflow: hidden;
}
#demographics-mount-point .stat-col {
    padding: 1.25rem;
    border-right: 1px solid var(--border-color);
}
#demographics-mount-point .stat-col:last-child { border-right: 0; }
#demographics-mount-point .stat-col-hero {
    font-size: 2.1rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--accent-color);
    margin-bottom: 0.9rem;
}
#demographics-mount-point .stat-col-hero em {
    font-style: normal;
    font-weight: 500;
    font-size: 1.05rem;
    color: var(--secondary-text);
    margin-left: 4px;
}
#demographics-mount-point .stat-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.35rem 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    font-size: 0.82rem;
}
#demographics-mount-point .stat-row:last-child { border-bottom: 0; }
#demographics-mount-point .stat-row .label { color: var(--secondary-text); }
#demographics-mount-point .stat-row .value {
    font-weight: 600;
    color: var(--primary-text);
    font-variant-numeric: tabular-nums;
}

/* ---- Distribution section: income chart + ethnicity bars ---- */
#demographics-mount-point .dist-section { margin-top: 1.5rem; }
#demographics-mount-point .dist-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
}
#demographics-mount-point .dist-block {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 0.75rem;
    padding: 1.1rem 1.25rem;
}
#demographics-mount-point .chart-wrap { position: relative; height: 240px; margin-top: 0.5rem; }

#demographics-mount-point .bar-list { display: flex; flex-direction: column; gap: 0.6rem; }
#demographics-mount-point .bar-row {
    display: grid;
    grid-template-columns: 120px 1fr 48px;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.82rem;
}
#demographics-mount-point .bar-row .bar-label { color: var(--secondary-text); }
#demographics-mount-point .bar-row .bar-track {
    background: rgba(255, 255, 255, 0.06);
    height: 8px;
    border-radius: 4px;
    overflow: hidden;
}
#demographics-mount-point .bar-row .bar-fill {
    height: 100%;
    background: var(--accent-color);
    border-radius: 4px;
    transition: width 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
#demographics-mount-point .bar-row .bar-pct {
    font-weight: 600;
    text-align: right;
    color: var(--primary-text);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 900px) {
    #demographics-mount-point .dist-grid { grid-template-columns: 1fr; gap: 1rem; }
    #demographics-mount-point .stat-block { grid-template-columns: 1fr 1fr; }
    #demographics-mount-point .stat-col { border-right: 0; }
    #demographics-mount-point .stat-col:nth-child(odd) { border-right: 1px solid var(--border-color); }
    #demographics-mount-point .stat-col:nth-child(-n+2) { border-bottom: 1px solid var(--border-color); }
}
/* .demo-radius-tabs / .demo-radius-tab* retired (Phase 4 batch 4) — the
   demographics radius switcher migrated to the canonical
   `ul.nav.nav-pills.ndt-subtabs` pattern (built in demographics_script.html;
   styled by the `.ndt-subtabs` rules below). The radius buttons now carry
   `.nav-link` + `data-demo-radius`; the JS switch is unchanged. */

/* ==========================================================
   Property tab — relocated from templates/tabs/property.html <style>
   ========================================================== */

/* White input fields with blue text + outline for Property tab */
/* Property tab (#tabpane-core) — modern DARK integrated inputs (scoped to this
   tab only; not yet app-wide). Replaces the stark white boxes with subtle dark
   fields that sit in the navy theme, gold-tinted borders, gold focus ring. */
#tabpane-core .form-control,
#tabpane-core .form-select {
    background: rgba(255, 255, 255, 0.045);
    color: var(--primary-text);
    border: 1px solid rgba(201, 168, 76, 0.20);
    border-radius: 8px;
    font-weight: 500;
    padding: 0.34rem 0.65rem;
    font-size: 0.84rem;
    line-height: 1.35;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
#tabpane-core .form-control:hover,
#tabpane-core .form-select:hover {
    border-color: rgba(201, 168, 76, 0.38);
}
#tabpane-core .form-control:focus,
#tabpane-core .form-select:focus {
    background: rgba(255, 255, 255, 0.07);
    border-color: var(--accent-color);
    box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.18);
    color: var(--primary-text);
    outline: none;
}
#tabpane-core .form-control::placeholder {
    color: var(--secondary-text);
}
#tabpane-core .input-group-text {
    background: rgba(255, 255, 255, 0.04);
    color: var(--accent-color);
    border: 1px solid rgba(201, 168, 76, 0.20);
}

/* Required Property inputs — refined gold accent (always visible): a gold inset
   left-bar + gold-tinted border signals "this field gates workflow", without the
   old loud 3px blue. */
#purchase_price,
#city,
#state,
#property_address {
    border-color: rgba(201, 168, 76, 0.55);
    box-shadow: inset 3px 0 0 var(--accent-color);
}
#purchase_price:focus,
#city:focus,
#state:focus,
#property_address:focus {
    border-color: var(--accent-color);
    box-shadow: inset 3px 0 0 var(--accent-color), 0 0 0 3px rgba(201, 168, 76, 0.22);
}

/* EMPTY required fields glow amber so they're obviously "fill me"; once filled
   (or focused) they fall back to the calmer gold treatment above. */
#purchase_price:placeholder-shown:not(:focus),
#city:placeholder-shown:not(:focus),
#state:placeholder-shown:not(:focus),
#property_address:placeholder-shown:not(:focus) {
    border-color: var(--warning-color);
    box-shadow: inset 3px 0 0 var(--warning-color);   /* glow ring + pulse removed (Carson 2026-07-11: too much glow) */
}

/* ----------------------------------------------------------
   Property tab (#tabpane-core) vertical density (Lane A) — fit one viewport
   at 100% on a 1080p laptop. Tightens the card/label/row rhythm without
   changing the redesign's look. Tune the values here if still too tall / now
   too cramped. (card override needs !important to beat Bootstrap's .p-3.)
   ---------------------------------------------------------- */
#tabpane-core .card { padding: 0.45rem 0.7rem !important; position: relative; }   /* tighter + anchor for overlay coachmarks */
#tabpane-core .form-label { margin-bottom: 0.2rem; }
#tabpane-core .row.mb-2 { margin-bottom: 0.4rem; }
#tabpane-core .d-flex.flex-column.gap-2 { gap: 0.5rem !important; }

/* Required-field marker + legend (replaces the floating coachmarks) */
.app-req-star { color: var(--warning-color); font-size: 1.05rem; font-weight: 800; vertical-align: middle; line-height: 0; margin-left: 0.25rem; cursor: help; }
.app-req-legend { display: block; font-size: 0.72rem; font-weight: 600; color: var(--warning-color); margin: 0.1rem 0 0.5rem; }
.app-req-legend .app-req-star { margin-left: 0; font-size: 0.85rem; }

/* Visible "Choose photo" button inside the Property Photo dropzone. It sits in
   the for-linked <label>, so a click triggers the file input natively (no JS). */
.app-upload-btn {
    display: inline-flex;
    align-items: center;
    margin-top: 0.5rem;
    padding: 0.3rem 0.85rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--accent-color);
    background: rgba(201, 168, 76, 0.12);
    border: 1px solid rgba(201, 168, 76, 0.4);
    border-radius: var(--radius-sm);
    transition: background 0.15s ease, border-color 0.15s ease;
}
.property-image-dropzone:hover .app-upload-btn { background: rgba(201, 168, 76, 0.2); }

/* ==========================================================
   Rent Study tab — Deck preview modal: per-property image side panel
   Compact horizontal mini-cards stacked vertically in a narrow right
   sidebar next to the embedded PDF iframe. Each card = small thumbnail
   on the left, name + Upload/Delete buttons stacked on the right. The
   preview itself is the actual PDF (iframe), so these cards only need
   to expose Upload + Delete controls per property.
   ========================================================== */
.rs-deck-img-card {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 5px;
    padding: 0.35rem;
    display: flex;
    flex-direction: row;
    gap: 0.5rem;
    align-items: center;
    flex: 0 0 auto;
}
.rs-deck-img-thumb {
    flex: 0 0 60px;
    width: 60px;
    height: 45px;
    background: var(--bg-primary);
    border-radius: 3px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.rs-deck-img-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.rs-deck-img-placeholder {
    color: #4a5568;
    font-size: 1.1rem;
}
.rs-deck-img-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}
.rs-deck-img-name {
    color: var(--primary-text);
    font-size: 0.7rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.rs-deck-img-actions {
    display: flex;
    gap: 0.25rem;
}
.rs-deck-img-actions .btn {
    padding: 0.1rem 0.4rem;
    font-size: 0.68rem;
    line-height: 1.1;
}

/* ==========================================================
   Tax tab — Tax Analysis Grid
   Relocated from templates/tabs/tax.html <style>
   ========================================================== */
#tax-analysis-grid-wrapper .app-table { font-size: 0.75rem; }
#tax-analysis-grid-wrapper .app-table td { padding: 0.2rem 0.35rem; }
#tax-analysis-grid-wrapper td[id$="_display"] { text-align: right; }
/* Column-header font-size + pad override removed 2026-07-13 — the uniform
   --tbl-header-size (0.65rem) + --tbl-header-pad tokens (app-tables.css) now
   own header typography. Body-cell padding above stays tight. */
#tax-analysis-grid-wrapper .form-control,
#tax-analysis-grid-wrapper .form-control-sm {
    padding: 0.15rem 0.3rem;
    height: auto;
    min-height: 0;
    font-size: 0.7rem;
    line-height: 1.4;
    text-align: right;
}
/* Selects need room on the right for Bootstrap's caret (drawn as a background
   image); the form-control rule above would tuck the option text under it.
   Keep them left-aligned with caret clearance so "Yes/No" no longer overlaps. */
#tax-analysis-grid-wrapper .form-select-sm {
    padding: 0.15rem 1.5rem 0.15rem 0.4rem;
    height: auto;
    min-height: 0;
    font-size: 0.7rem;
    line-height: 1.4;
    text-align: left;
    background-position: right 0.45rem center;
}
#tax-analysis-grid-wrapper .input-group-text {
    padding: 0.15rem 0.25rem;
    font-size: 0.65rem;
}
/* Gold border on editable mill-rate / pct-of-price inputs */
#tax-analysis-grid-wrapper #tax_acq_pct_of_price,
#tax-analysis-grid-wrapper #tax_sale_pct_of_price,
#tax-analysis-grid-wrapper #tax_county_mill_rate,
#tax-analysis-grid-wrapper #tax_assessment_level_pct,
#tax-analysis-grid-wrapper #tax_acq_assessment_level_pct,
#tax-analysis-grid-wrapper #tax_sale_assessment_level_pct { border-color: rgba(201, 168, 76, 0.8); }
#tax-analysis-grid-wrapper #tax_acq_pct_of_price:focus,
#tax-analysis-grid-wrapper #tax_sale_pct_of_price:focus,
#tax-analysis-grid-wrapper #tax_county_mill_rate:focus,
#tax-analysis-grid-wrapper #tax_assessment_level_pct:focus,
#tax-analysis-grid-wrapper #tax_acq_assessment_level_pct:focus,
#tax-analysis-grid-wrapper #tax_sale_assessment_level_pct:focus {
    border-color: rgba(201, 168, 76, 1);
    box-shadow: 0 0 0 2px rgba(201, 168, 76, 0.2);
}
/* Tax Impact columns (shown when reassess-on-sale = Yes) */
#tax-analysis-grid-wrapper td.tax-impact-label {
    font-weight: 600;
    border-left: 2px solid rgba(201, 168, 76, 0.5);
}
#tax-analysis-grid-wrapper td.tax-impact-value { text-align: right; }
#tax-analysis-grid-wrapper td.tax-impact-notes {
    border-left: 2px solid rgba(201, 168, 76, 0.5);
    vertical-align: top;
    padding: 0.5rem;
}
#tax-analysis-grid-wrapper td.tax-impact-notes textarea {
    width: 100%;
    resize: none;
    font-size: 0.7rem;
    text-align: left;
}
#tax-analysis-grid-wrapper td.tax-impact-notes .tax-notes-header {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid rgba(201, 168, 76, 0.5);
    margin-bottom: 0.4rem;
}

/* Headline KPI numbers: the old gold text-shadow shimmer animation was
   removed 2026-07-11 (Carson: "numbers are glowing still lets not do that").
   The .plm-value tiles above own the KPI treatment — flat colors, no glow. */

/* Deals dashboard table + cards */
#deals-dashboard {
    background: transparent;
    position: relative;
    z-index: 1;
}
#deals-dashboard .card {
    background: var(--card-bg);
    border: 1px solid rgba(201,168,76,0.12);
    box-shadow: 0 4px 16px rgba(0,0,0,0.25);
    position: relative;
    z-index: 2;
}
/* (The old #deals-dashboard .table thead/td/hover rules were superseded by the
   DEALS DASHBOARD — PREMIUM PASS block at the end of this file, 2026-07-28.) */
#deals-dashboard .brand {
    color: var(--primary-text);
    text-shadow: 0 0 10px rgba(201,168,76,0.3);
    font-weight: 600;
}
#deals-dashboard .subtext {
    color: var(--accent-color);
    font-weight: 400;
}

/* ==========================================================================
   Deals dashboard chrome — promoted off per-element inline styles
   (partials/deals_dashboard.html). z-index uses --z-app-header (was a literal
   9999). Behavior-preserving; the mobile !important rules further down still
   override padding/logo-size on small screens.
   ========================================================================== */
.reuw-dash-nav {
    position: sticky;
    top: 0;
    z-index: var(--z-app-header);
    width: 100%;
    /* Wordmark (1.7rem) is shorter than the old 50px logo image, so the dashboard
       bar lost height when it switched over; pad up to stay level with the deal
       + home nav bars. */
    padding: 1.15rem 0;
    /* Match the deal-shell #reuw-top-nav chrome: opaque navy bar + bottom border
       so the dashboard and deal top bars read as the same component. */
    background: var(--bg-primary);
    border-bottom: 1px solid var(--border-color);
    box-shadow: 0 1px 3px rgba(201, 168, 76, 0.08), 0 4px 12px rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(10px);
}
.reuw-dash-accent {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--accent-color);   /* the gold accent line (was colorless) */
    pointer-events: none;
}
.reuw-dash-navrow {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-left: 2.75rem;   /* wordmark lands ~3.25rem, level with home + deal */
    padding-right: 3rem;
    position: relative;
}
.reuw-dash-navrow .nav-dash-link {
    text-decoration: none;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    transition: all 0.15s ease;
    padding: 0.15rem 0.5rem;
    border-radius: 0.5rem;
}
.reuw-dash-navrow .nav-dash-link img {
    height: 50px;   /* match the deal-shell logo (was 72px) so the bars line up */
    width: auto;
}

/* ===== REUW wordmark (replaces the building-logo image; 2026-06-28) =====
   Clean modern gold-gradient wordmark with subtle 3D depth + a slow shine
   sweep so it pops. Self-contained — drop <span class="reuw-wordmark">REUW</span>
   into any nav link in place of the <img>. Shorter than the 50px image, so it
   also frees a little nav height (property-fit friendly). */
.reuw-wordmark {
    display: inline-block;
    font-family: var(--font-ui);
    font-weight: 700; /* heaviest weight actually loaded (was 800 = faux-bold) */
    font-size: 1.7rem;
    letter-spacing: 0.1em;
    line-height: 1;
    /* Gold gradient with a bright band for the shine sweep. */
    background: linear-gradient(110deg, #b8923e 0%, #c9a84c 30%, #f6e6b0 50%, #c9a84c 70%, #a8893e 100%);
    background-size: 250% 100%;
    background-position: 90% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--accent-color);   /* fallback if background-clip:text unsupported */
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));   /* subtle 3D depth */
    transition: filter 0.2s ease, transform 0.2s ease;
    animation: reuw-shine 7s ease-in-out infinite;
    user-select: none;
}
.nav-dash-link:hover .reuw-wordmark {
    filter: drop-shadow(0 2px 5px rgba(201, 168, 76, 0.4));   /* gold glow on hover */
    transform: translateY(-1px);
}
@keyframes reuw-shine {
    0%, 100% { background-position: 90% 0; }
    50%      { background-position: 10% 0; }
}
@media (prefers-reduced-motion: reduce) {
    .reuw-wordmark { animation: none; }
}
.reuw-dash-main {
    flex: 1;
    padding: 2rem 3rem;
    width: 100%;
}

/* Deal-row utility classes (status / type badges, full-deal link, action btn) */
.deal-full-link {
    color: var(--primary-text);
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
    transition: color 0.15s;
}
.deal-full-link:hover {
    color: var(--accent-color);
    text-decoration: none;
}
/* (.deal-status-badge / .deal-type-badge / .status-* / .type-* chip styling was
   superseded by the DEALS DASHBOARD — PREMIUM PASS block at the end of this
   file, 2026-07-28 — homepage-style pills, gold discipline.) */
.action-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.8rem;
    background: rgba(16,185,129,0.15);
    color: var(--success-color);
    border: 1px solid rgba(16,185,129,0.2);
    border-radius: 6px;
    text-decoration: none;
    font-weight: 500;
    font-size: 0.82rem;
    transition: all 0.15s ease;
}
.action-btn:hover {
    background: rgba(16,185,129,0.25);
    color: var(--success-color);
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(0,0,0,0.2);
}

/* ==========================================================
   Canonical Input-State Classes
   Replaces the inline `style="background: rgba(40,167,69,0.1); ..."`
   patterns that proliferated in tab partials (especially S&U,
   Financing, Tax, Property). Apply ONE of these classes to an
   <input> or <select>; do not stack them with inline color/bg/border.

   Naming convention:
     .app-input-*   — semantic states for tab-partial inputs that
                       sit OUTSIDE .app-table (which has its own
                       data-row-input rules in app-tables.css).
   ========================================================== */

/* Editable: white background, blue text, blue border. The institutional
   default look for any user-fillable field. */
.app-input-editable {
    background: #ffffff;
    border: 1px solid rgba(91, 165, 220, 0.85);
    color: #0d6efd;
    border-radius: 6px;
}
.app-input-editable:focus {
    background: #ffffff;
    border-color: #0d6efd;
    box-shadow: 0 0 0 3px rgba(91, 165, 220, 0.4);
    color: #0d6efd;
    outline: none;
}
.app-input-editable::placeholder {
    color: rgba(13, 110, 253, 0.55);
}

/* Calculated: green tint, read-only. For values computed from other
   fields (S&U Senior Debt = Purchase Price × LTV, etc.). */
.app-input-calculated {
    background: rgba(40, 167, 69, 0.10);
    border: 1px solid rgba(40, 167, 69, 0.45);
    color: var(--primary-text);
    cursor: not-allowed;
}

/* Percentage: gold tint. For % fields like Acquisition Fee, Lender Fee. */
.app-input-percentage {
    background: rgba(255, 193, 7, 0.10);
    border: 1px solid rgba(255, 193, 7, 0.30);
    color: var(--primary-text);
}

/* Cost: cyan tint. For debt service / contingency / cost-of-capital fields. */
.app-input-cost {
    background: rgba(23, 162, 184, 0.10);
    border: 1px solid rgba(23, 162, 184, 0.30);
    color: var(--primary-text);
}

/* Readonly display: white-low-alpha. For display-only fields that aren't
   computed (e.g. mirrored values from another tab). */
.app-input-readonly {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: var(--secondary-text);
    cursor: not-allowed;
}

/* Required: gold border + glow. For fields that gate further workflow
   (Property tab's required gates). */
.app-input-required {
    border: 3px solid #0d6efd;
    box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.25);
}

/* ==========================================================
   Searchable Category Dropdown (.searchable-select-*)
   Custom dropdown component used in T-12 category mapping and
   Expense Bridge category cells. Self-contained — no Bootstrap.
   Relocated from templates/index.html.
   ========================================================== */

.searchable-select-wrapper {
    position: relative;
    display: inline-block;
    width: 100%;
    min-width: 180px;
    z-index: 1;
}
.searchable-select-wrapper.open {
    z-index: var(--z-dropdown);
}
/* Ensure table rows are positioned so z-index works for dropdown layering */
tr:has(.searchable-select-wrapper) {
    position: relative;
}
.searchable-select-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: #212529;
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 4px;
    color: var(--primary-text);
    cursor: pointer;
    padding: 0.15rem 0.3rem;
    font-size: 0.65rem;
    min-height: 24px;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    user-select: none;
}
.searchable-select-trigger:hover {
    border-color: rgba(201,168,76,0.5);
}
.searchable-select-wrapper.open .searchable-select-trigger {
    border-color: var(--accent-color);
    box-shadow: 0 0 0 1px rgba(201,168,76,0.25);
}
.searchable-select-trigger span {
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1;
}
.searchable-select-trigger .ss-chevron {
    margin-left: 4px;
    font-size: 0.55rem;
    opacity: 0.6;
    transition: transform 0.15s;
    flex-shrink: 0;
}
.searchable-select-wrapper.open .ss-chevron {
    transform: rotate(180deg);
}
.searchable-select-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    right: 0;
    z-index: var(--z-dropdown);
    background: #1a2234;
    border: 1px solid rgba(201,168,76,0.4);
    border-radius: 6px;
    margin-top: 2px;
    box-shadow: 0 8px 28px rgba(0,0,0,0.7);
    min-width: 300px;
    width: max-content;
    max-width: 380px;
}
.searchable-select-wrapper.open .searchable-select-dropdown {
    display: block;
}
.searchable-select-search {
    width: 100%;
    border: none;
    border-bottom: 1px solid rgba(255,255,255,0.15);
    background: #0f1a2e;
    color: var(--primary-text);
    padding: 8px 10px;
    font-size: 0.8rem;
    outline: none;
    box-sizing: border-box;
}
.searchable-select-search::placeholder {
    color: var(--secondary-text);
}
.searchable-select-options {
    max-height: 400px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: #c9a84c33 transparent;
}
.searchable-select-options::-webkit-scrollbar {
    width: 5px;
}
.searchable-select-options::-webkit-scrollbar-thumb {
    background: rgba(201,168,76,0.3);
    border-radius: 3px;
}
.searchable-select-optgroup {
    padding: 5px 10px 3px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--accent-color);
    pointer-events: none;
    opacity: 0.85;
    border-top: 1px solid rgba(255,255,255,0.08);
}
.searchable-select-optgroup:first-child {
    border-top: none;
}
.searchable-select-option {
    padding: 6px 12px;
    font-size: 0.8rem;
    color: var(--primary-text);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.searchable-select-option:hover,
.searchable-select-option.highlighted {
    background: rgba(201,168,76,0.15);
    color: var(--primary-text);
}
.searchable-select-option.selected {
    background: rgba(201,168,76,0.25);
    color: var(--accent-color);
}
.searchable-select-option.ss-hidden {
    display: none;
}
.searchable-select-no-results {
    padding: 8px 10px;
    font-size: 0.6rem;
    color: var(--secondary-text);
    text-align: center;
    font-style: italic;
}

/* ==========================================================
   Site-wide Form Controls
   The institutional blue-on-white input look applied to every
   .form-control / .form-select that is NOT inside an .app-table
   (which has its own data-row-input rules in app-tables.css with
   higher specificity via :not() chains). Relocated from
   templates/index.html. Use these classes instead of inline
   style="background:..." for any user-fillable input.
   ========================================================== */

.form-control, .form-select {
    background: #ffffff;
    border: 1px solid rgba(91, 165, 220, 0.85);
    border-radius: 6px;
    color: #0d6efd;
    font-weight: 400;
    padding: 0.625rem 0.875rem;
    transition: all 0.15s ease;
    font-size: 0.875rem;
}

.form-control:focus, .form-select:focus {
    background: #ffffff;
    border-color: #0d6efd;
    box-shadow: 0 0 0 3px rgba(91, 165, 220, 0.4);
    color: #0d6efd;
    outline: none;
}

.form-control::placeholder {
    color: rgba(13, 110, 253, 0.55);
}

.form-control:disabled, .form-control[readonly] {
    background: rgba(255,255,255,0.03);
    border-color: #1f2937;
    color: #6b7280;
    cursor: not-allowed;
}

/* Auto-calculated fields — yellow highlight (deprecated; prefer
   .app-input-calculated above which uses the same semantic but
   without the .form-control coupling). Kept for legacy markup. */
input.auto-calculated[readonly] {
    background: rgba(255,217,102,0.15);
    border-color: var(--accent-color);
    color: var(--accent-color);
    font-weight: 600;
}

input.auto-calculated[readonly]:hover {
    box-shadow: 0 0 15px rgba(255,217,102,0.3);
}

/* Select dropdowns — chevron tinted to match blue input text */
.form-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%230d6efd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 16px 12px;
}

/* ==========================================================
   Tab Navigation — main deal tab bars (#newDealTabs and
   #existing-top-tabs), fallback Bootstrap .nav-tabs, .nav-pills,
   the .ndt-subtabs scoped class for inner subtab bars, and the
   .tab-content / .tab-pane wrappers. Relocated from
   templates/index.html so all navigation styling lives in one file.
   ========================================================== */

/* Wrapper border for non-main nav-tabs */
.nav-tabs:not(#newDealTabs):not(#existing-top-tabs) {
    border-bottom: 1px solid var(--border-color);
    background: transparent;
    padding: 0;
    position: relative;
    z-index: 2;
    overflow: visible;
    justify-content: center;
}

/* -- Deal page top nav (logo + tab row) --
   We own color/border/z-index here so scrolled tab content is fully painted
   over (was bleeding through when only backdrop-filter was applied). */
#reuw-top-nav {
    background: var(--bg-primary);
    border-bottom: 1px solid var(--border-color);
    z-index: var(--z-app-header);
}
/* Sticky chrome — moved off the index.html inline style (2026-07-13; only the
   display:none toggle stays inline there). Scoped to body.deal-shell because
   the auth/settings pages reuse the #reuw-top-nav id with their own auth.css
   styling. */
body.deal-shell #reuw-top-nav {
    position: sticky;
    top: 0;
    padding: 0;
    overflow: visible;
    box-shadow: 0 1px 3px rgba(201, 168, 76, 0.08), 0 4px 12px rgba(0, 0, 0, 0.4);
}
/* Gold accent hairline across the very top of the bar. */
#reuw-top-nav .nav-accent-line {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--accent-color);
    pointer-events: none;
}

/* Decorative merged "haze x nyc" skyline: 2 soft far haze layers + a crisp
   block band + detailed mid/front layers of small-scale towers (setback
   crowns, water towers, spires, mechanicals, window-grid pattern fills),
   with a thin gold ridge-contour tracing the jagged front roofline. Every
   mid/front building is separated by real gaps, alternating two-tone fills
   (mrg-g3/g3b, mrg-g4/g4b) and vertical edge hairlines (.sky-egm/.sky-egf)
   so towers read individually (Carson, 2026-07-07). One SVG in the DOM;
   light theme restyles gradient stops + detail classes via the overrides. */
.nav-skyline {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 100%;   /* rises behind the whole nav — the full-width tab row would
                       otherwise hide a bottom-anchored strip almost entirely */
    opacity: 0.9;   /* subtlety comes from color-closeness to the nav bg, not
                       raw opacity (faint gold over navy goes muddy olive) */
    pointer-events: none;
    z-index: 0;
    /* Fade the silhouette out toward the top so the header text (deal name /
       logo / account, which sit on the upper band) stays legible over it. */
    -webkit-mask-image: linear-gradient(to top, #000 50%, rgba(0, 0, 0, 0.45) 72%, transparent 97%);
            mask-image: linear-gradient(to top, #000 50%, rgba(0, 0, 0, 0.45) 72%, transparent 97%);
}
/* Dark-mode gold dimmer (Carson 2026-07-07: "too much gold on the buildings").
   Unscoped so they hit the dark defaults; the light block below re-raises
   every one of these, so light mode's bronze detail is untouched. */
.nav-skyline .sky-ridge { opacity: 0.5; }
.nav-skyline .sky-wga   { opacity: 0.16; }
.nav-skyline .sky-ndl   { opacity: 0.4; }
.nav-skyline .sky-bcn   { opacity: 0.45; }
.nav-skyline .sky-dca   { opacity: 0.5; }
:root[data-theme="light"] .nav-skyline .sky-bcn { opacity: 1; }
:root[data-theme="light"] .nav-skyline .sky-dca { opacity: 1; }
:root[data-theme="light"] .nav-skyline .sky-s0a{stop-color:#dbe2ec}:root[data-theme="light"] .nav-skyline .sky-s0b{stop-color:#d2dae7}
:root[data-theme="light"] .nav-skyline .sky-s1a{stop-color:#ccd5e3}:root[data-theme="light"] .nav-skyline .sky-s1b{stop-color:#c0cbda}
:root[data-theme="light"] .nav-skyline .sky-s2a{stop-color:#b9c5d5}:root[data-theme="light"] .nav-skyline .sky-s2b{stop-color:#adbacc}
:root[data-theme="light"] .nav-skyline .sky-s3a{stop-color:#adbacc}:root[data-theme="light"] .nav-skyline .sky-s3b{stop-color:#9fafc4}
:root[data-theme="light"] .nav-skyline .sky-s3c{stop-color:#a4b2c7}:root[data-theme="light"] .nav-skyline .sky-s3d{stop-color:#97a7bd}
:root[data-theme="light"] .nav-skyline .sky-s4a{stop-color:#8a9bb2}:root[data-theme="light"] .nav-skyline .sky-s4b{stop-color:#6a7d99}
:root[data-theme="light"] .nav-skyline .sky-s4c{stop-color:#7e90a9}:root[data-theme="light"] .nav-skyline .sky-s4d{stop-color:#5f7390}
:root[data-theme="light"] .nav-skyline .sky-egm{stroke:#7d90aa;opacity:0.55}
:root[data-theme="light"] .nav-skyline .sky-egf{stroke:#2f4463;opacity:0.6}
:root[data-theme="light"] .nav-skyline .sky-swb{stop-color:#8ea2bf;stop-opacity:0.11}
:root[data-theme="light"] .nav-skyline .sky-sra{stop-color:#a8842c}:root[data-theme="light"] .nav-skyline .sky-srb{stop-color:#c9a84c}
:root[data-theme="light"] .nav-skyline .sky-ridge{stroke-width:1.8;opacity:1}
:root[data-theme="light"] .nav-skyline .sky-wga{fill:#33455f;opacity:0.4}
:root[data-theme="light"] .nav-skyline .sky-wba{fill:#33455f;opacity:0.3}
:root[data-theme="light"] .nav-skyline .sky-wma{fill:#6c7f9a;opacity:0.45}
:root[data-theme="light"] .nav-skyline .sky-tk{fill:#647999}:root[data-theme="light"] .nav-skyline .sky-tkc{fill:#6f84a2}
:root[data-theme="light"] .nav-skyline .sky-mek{fill:#6b8099}
:root[data-theme="light"] .nav-skyline .sky-ant{stroke:#5c6f88}
:root[data-theme="light"] .nav-skyline .sky-ndl{stroke:#a8842c;opacity:0.9}
:root[data-theme="light"] .nav-skyline .sky-bcn{fill:#a8842c}
:root[data-theme="light"] .nav-skyline .sky-l2d{stroke:#9fafc4}
:root[data-theme="light"] .nav-skyline .sky-dcb{fill:#6f84a2}
:root[data-theme="light"] .nav-skyline .sky-dca{stroke:#a8842c}

/* -- Main Deal Tab Bar -- */
/* Deal-shell control row (all layout moved off index.html inline styles,
   2026-07-13). flex-wrap lets the tab strip (flex:1 1 100%, order:2 below)
   take its own line beneath the breadcrumb / deal name / presence avatars /
   Excel / account. gap: row-gap 0 so the tab line sits snug under the
   controls (its own padding-top provides the separation); 0.75rem uniform
   column gap between the controls, which all center in the 52px line. */
#reuw-nav-row {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    min-height: 52px;
    padding: 0.35rem 1rem;
    gap: 0 0.75rem;
    position: relative;
    z-index: 1;
}

#newDealTabs,
#existing-top-tabs {
    --tab-gap: 0.25rem;
    display: flex;
    flex-wrap: wrap;
    gap: var(--tab-gap);
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0.4rem 0 0;
    overflow: visible;
    scrollbar-width: none;
    margin-bottom: 0;
    /* Own full-width row: flex-basis 100% wraps the tab strip onto its own
       line inside #reuw-nav-row, and order:2 places it AFTER the logo /
       presence avatars / Excel / account (which stay on line 1). All 15 tabs
       then sit on ONE clean centered line with room to spare, instead of
       wrapping lopsidedly (WATERFALL/SALES COMPS/LOI orphaned on a 2nd row). */
    flex: 1 1 100%;
    order: 2;
    min-width: 0;
    justify-content: center;   /* B: centered group — balanced wide + clean when wrapped */
}
#newDealTabs.hidden-by-existing {
    display: none;
}
#newDealTabs::-webkit-scrollbar,
#existing-top-tabs::-webkit-scrollbar { display: none; }

#newDealTabs .nav-item,
#existing-top-tabs .nav-item {
    flex: 0 0 auto;          /* content-width: clean, even tabs (no stretch); wrap on medium */
    min-width: max-content;  /* never clip the label */
    text-align: center;
    position: relative;
}
/* Full-bleed: now that the tab strip owns its own row, let each tab grow to an
   equal share so the bar spans the whole width edge-to-edge (min-width above
   still keeps long labels like "SOURCES & USES" from clipping). */
#existing-top-tabs .nav-item { flex: 1 1 0; }

#newDealTabs .nav-link,
#existing-top-tabs .nav-link {
    /* Outlined folder tabs (Carson, variant B): EVERY tab is a visible boxed
       folder (subtle fill + border, rounded top, open bottom) so the tab
       boundaries are always obvious — not just the active one. Active lifts to
       the card surface + gold frame. Token-based so both themes work; the gold
       accents are the consistent "selected" signal in light AND dark.
       Same padding/font -> bar height unchanged (property-tab fit safe). */
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-bottom: none;
    border-radius: 0.5rem 0.5rem 0 0;
    /* lighter than --secondary-text so inactive tabs are easier to read on the
       dark bar, while gold (active) + white (hover) stay distinct */
    color: color-mix(in srgb, var(--primary-text) 62%, var(--secondary-text));
    font-family: var(--font-ui);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-size: 0.72rem;
    line-height: 1.2;
    padding: 0.45rem 0.55rem;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
    white-space: nowrap;
    width: auto;
    display: block;
    text-align: center;
    position: relative;
    box-shadow: none;
}
/* The tab is a <button>, which stays content-width even as display:block, so
   inside the equal-width flex items it sat narrow with gaps around it. Fill the
   slot so the folders butt up edge-to-edge (only the 0.25rem --tab-gap between)
   — an even, gapless full-width bar. */
#existing-top-tabs .nav-link { width: 100%; }

#newDealTabs .nav-link:hover,
#existing-top-tabs .nav-link:hover {
    background: var(--card-bg);
    color: var(--primary-text);
    border-color: color-mix(in srgb, var(--accent-color) 45%, var(--border-color));
}

#newDealTabs .nav-link.active,
#existing-top-tabs .nav-link.active {
    /* The lit folder: lighter fill, framed sides, gold top edge + gold bold
       label, subtle lift. Unmistakably "the tab you're on." */
    background: var(--card-bg);
    border-color: var(--border-color);
    border-bottom: none;
    color: var(--accent-color);
    font-weight: 700;
    letter-spacing: 0.03em;
    box-shadow: inset 0 2px 0 var(--accent-color), 0 -2px 6px rgba(0, 0, 0, 0.22);
}

/* Underline accent disabled for folder tabs (the lit folder is the indicator) */
#newDealTabs .nav-link::after,
#existing-top-tabs .nav-link::after {
    content: none;
    position: absolute;
    bottom: 0;
    left: 20%;
    width: 60%;
    height: 2px;
    background: linear-gradient(90deg, transparent, #c9a84c, transparent);
    border-radius: 1px;
    transform: scaleX(0);
    transition: transform 0.2s ease, opacity 0.2s ease;
    opacity: 0;
}
#newDealTabs .nav-link.active::after,
#existing-top-tabs .nav-link.active::after {
    transform: scaleX(1);
    opacity: 1;
}
#newDealTabs .nav-link:hover::after,
#existing-top-tabs .nav-link:hover::after {
    transform: scaleX(0.35);
    opacity: 0.2;
}

#newDealTabs .nav-link.active:hover,
#existing-top-tabs .nav-link.active:hover {
    background: var(--card-bg);
    color: #d4b85c;
}

/* Light mode: tint the deal nav bar a light-grey "track" so the white folder
   boxes (inactive + active) read as a distinct tab strip lifting off it. The
   gold frame/edge on .active is the selected signal (same as dark). */
:root[data-theme="light"] #reuw-top-nav { background: var(--bg-tertiary); }

/* Seamless folder → content: a baseline rail along the bottom of the deal nav
   that reads as the content's top edge. Inactive boxes sit ON the rail; the
   active folder "breaks" it (paints over with its own fill via a matching
   bottom border) so it connects down into the content with no floating gap. */
#reuw-top-nav { border-bottom: 1px solid var(--border-color); }
/* The deal-nav tab strip drops to the bottom of the (symmetrically-padded) nav so
   it meets the rail, while the logo / Excel / account stay vertically centered in
   the nav (matching the home/dashboard logo position). The negative margin spans
   the nav-row's bottom padding so the folders reach the rail. */
#existing-top-tabs { align-self: flex-end; margin-bottom: -0.5rem; }
/* Only the active folder overlaps + breaks the rail (inactive boxes sit on it). */
#newDealTabs .nav-link.active,
#existing-top-tabs .nav-link.active {
    margin-bottom: -1px;
    border-bottom: 1px solid var(--card-bg);
}

/* ---- Responsive ----
   No <=992px rules here on purpose: both tab bars are display:none below
   1100px (the .ndt-tab-select dropdown replaces them — see that section),
   so narrower breakpoints for these bars are unreachable. */

/* Fallback for generic .nav-tabs (non-main-tabs) */
.nav-tabs:not(#newDealTabs):not(#existing-top-tabs) .nav-item {
    flex: 1 1 0;
    text-align: center;
}

.nav-tabs:not(#newDealTabs):not(#existing-top-tabs) .nav-link {
    background: transparent;
    border: 1px solid rgba(255,255,255,0.2);
    border-bottom: 2px solid rgba(255,255,255,0.2);
    color: #94a3b8;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-size: clamp(0.58rem, 0.9vw, 0.75rem);
    margin-right: 0;
    border-radius: 2px 2px 0 0;
    padding: 0.5rem 0.4rem;
    transition: all 0.2s ease;
    white-space: nowrap;
    width: 100%;
}

.nav-tabs:not(#newDealTabs):not(#existing-top-tabs) .nav-link:hover {
    background: rgba(91, 143, 201, 0.1);
    border-color: rgba(91, 143, 201, 0.45);
    border-bottom-color: rgba(91, 143, 201, 0.5);
    color: #cbd5e1;
}

.nav-tabs:not(#newDealTabs):not(#existing-top-tabs) .nav-link.active {
    background: rgba(91, 143, 201, 0.08);
    border-color: rgba(91, 143, 201, 0.4);
    border-bottom-color: #c9a84c;
    color: #c9a84c;
    font-weight: 600;
    box-shadow: none;
}

/* -- Bootstrap .nav-pills -- */
.nav-pills .nav-link {
    background: rgba(30,77,123,0.6);
    border: 2px solid transparent;
    color: var(--secondary-text);
    font-weight: 500;
    border-radius: 3px;
    padding: 0.6rem 1.2rem;
}

.nav-pills .nav-link:hover {
    background: rgba(255,255,255,0.15);
    border-color: rgba(255,255,255,0.3);
    color: var(--primary-text);
}

.nav-pills .nav-link.active {
    background: linear-gradient(135deg, #c9a84c 0%, #a07e2e 100%);
    border-color: var(--accent-color);
    color: #0a2942;
    font-weight: 600;
    box-shadow: 0 4px 15px rgba(201, 168, 76, 0.3);
}

/* ---- Standardized subtab bars (.ndt-subtabs) ----
   Scoped class for inner-content subtab bars. Does NOT affect #newDealTabs. */
.ndt-subtabs { gap: 0.4rem; flex-wrap: wrap; }
.ndt-subtabs .nav-link {
    background: rgba(30, 77, 123, 0.5);
    border: 1px solid transparent;
    color: var(--secondary-text);
    font-weight: 500;
    font-size: 0.78rem;
    border-radius: 0.4rem;
    padding: 0.35rem 0.85rem;
    transition: all 0.15s ease;
    white-space: nowrap;
}
.ndt-subtabs .nav-link:hover {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.25);
    color: var(--primary-text);
}
.ndt-subtabs .nav-link.active {
    background: linear-gradient(135deg, #c9a84c 0%, #a07e2e 100%);
    border-color: var(--accent-color);
    color: #0a2942;
    font-weight: 600;
    box-shadow: 0 2px 8px rgba(201, 168, 76, 0.3);
}
.ndt-subtabs .nav-link i { font-size: 0.72rem; }

/* -- Tab Content Wrappers -- */
.tab-content {
    background: transparent;
    border: none;
    border-top: none;
    padding: 1.5rem 0;
    position: relative;
    z-index: 2;
}

.tab-pane {
    background: transparent;
    /* Theme ink (2026-07-06) — was the dark-theme literal #e2e8f0, which never
       flipped and was the root cause of every "ghost grey header in light mode"
       bug patched per-element above. Dark mode now inherits #e8edf4 instead of
       #e2e8f0 — imperceptible. Stay-dark surfaces inside panes are guarded
       (.app-card-very-dark above; the legacy rent-roll panels in tab-theme.css). */
    color: var(--primary-text);
}


/* ==========================================================
   Canonical Card Section Variants
   Replaces the inline gradient backgrounds on .card elements
   in tab partials (S&U Sources/Uses cards, Returns cards,
   Demographics cards, etc.). Apply alongside .card.

   Each variant tints the card to signal semantic role; the
   .card base styling (rounded corners, padding, shadow) comes
   from the .card rule above.
   ========================================================== */

.card-section-success {
    background: linear-gradient(135deg, rgba(40,167,69,0.06) 0%, rgba(201,168,76,0.05) 100%);
    border: 1px solid rgba(40,167,69,0.25);
    box-shadow: 0 2px 10px rgba(40,167,69,0.10);
}

.card-section-warning {
    background: linear-gradient(135deg, rgba(255,193,7,0.06) 0%, rgba(255,159,64,0.05) 100%);
    border: 1px solid rgba(255,193,7,0.25);
    box-shadow: 0 2px 10px rgba(255,193,7,0.10);
}

.card-section-info {
    background: linear-gradient(135deg, rgba(23,162,184,0.06) 0%, rgba(13,202,240,0.05) 100%);
    border: 1px solid rgba(23,162,184,0.25);
    box-shadow: 0 2px 10px rgba(23,162,184,0.10);
}

.card-section-neutral {
    background: linear-gradient(135deg, rgba(108,117,125,0.06) 0%, rgba(52,58,64,0.05) 100%);
    border: 1px solid rgba(108,117,125,0.25);
    box-shadow: 0 2px 10px rgba(0,0,0,0.10);
}

/* ==========================================================
   Sources & Uses tab utilities
   These rgba alpha values are tuned for the S&U CapEx subtotal
   cells that sit on top of .card-section-warning gradient. The
   .app-table .is-subtotal* row-states use lower alphas tuned for
   white-background tables — different visual context, different
   values. Relocated from the per-tab <style> block so they're
   discoverable from one place.
   ========================================================== */

/* CapEx subtotal cell backdrops — apply to <td>. Pair with
   `.su-input-summary` for the readonly input inside. */
.su-cell-grey   { background: rgba(160, 160, 160, 0.5); }
.su-cell-gold   { background: rgba(201, 168, 76, 0.45); }
.su-cell-danger { background: rgba(220, 53, 69, 0.15); }

/* CapEx readonly summary inputs — transparent bg, hard black 2px border */
.su-input-summary {
    background: transparent;
    border: 2px solid #000;
    color: #000;
    font-weight: 600;
}
/* Variant: red-tinted (Total Unit Upgrades) */
.su-input-summary-danger {
    background: rgba(220, 53, 69, 0.15);
    border: 2px solid rgba(220, 53, 69, 0.4);
    color: var(--primary-text);
    font-weight: 600;
}
/* Variant: amber-tinted (Wtd Avg Cost/Unit derived) */
.su-input-summary-warning {
    background: rgba(255, 193, 7, 0.1);
    border: 1px solid rgba(255, 193, 7, 0.3);
    color: var(--primary-text);
    cursor: not-allowed;
}

/* Standard subtotal label (used in cells alongside .su-cell-*) */
.su-label-subtotal {
    color: #000;
    font-size: 0.95rem;
    font-weight: 600;
}

/* S&U cards: override the shared .card-section-success / -warning gradient
   tints with a flat navy fill so the Sources and Uses panels match the rest
   of the dark theme. Colored borders (green for Sources, amber for Uses) are
   preserved as semantic outlines — only the panel fill changes. Scoped to
   the S&U tab so other consumers of .card-section-* (Returns, Demographics,
   etc.) are unaffected. */
#tabpane-sources-uses .card.card-section-success,
#tabpane-sources-uses .card.card-section-warning {
    background: var(--card-bg);
}

/* Property tab (Core Inputs): flatten the Property Details and Seller & Broker
   Details panels' .card-section-warning amber-gradient fill to navy so they match
   the plain-navy Purchase Price / Whisper Price card above them. The amber border
   is preserved as a semantic "fill these in" outline — only the fill changes.
   Scoped to #tabpane-core (same pattern as the S&U override above). */
#tabpane-core .card.card-section-warning {
    background: var(--card-bg);
}

/* S&U-specific font sizing override (cells slightly larger than canonical .app-table) */
#tabpane-sources-uses .app-table { font-size: 0.85rem; }
/* Compact density: tighter vertical padding + drop the canonical 30px row
   min-height so more Sources/Uses rows fit on screen at once. */
#tabpane-sources-uses .app-table tbody td { padding: 0.28rem 0.6rem; height: auto; }
/* Row-label cells are the tallest element per row (0.9rem at default
   line-height); tighten their line-height so they don't bottleneck the
   compacted rows. */
#tabpane-sources-uses .app-table tbody td label { line-height: 1.3; margin-bottom: 0; }
/* Total Sources / Total Uses rows: the canonical .is-total rule shrinks
   font-size to 0.75rem (designed for compact NOI-style summary rows), which
   reads as smaller than the body. Match the body size so the totals don't
   look subordinate to their own rows' inputs. */
#tabpane-sources-uses .app-table tbody tr.is-total td,
#tabpane-sources-uses .app-table tbody tr.is-total input {
    font-size: 0.85rem;
}
/* Column headers bumped to 0.8rem (vs canonical 0.55rem) for legibility.
   Letter-spacing tightened to fit the inline "(X units)" / "(Y sqft)"
   reference text in the Per Unit / Per Sqft headers. */
#tabpane-sources-uses .app-table thead th {
    /* font-size / letter-spacing removed 2026-07-13 — uniform --tbl-header-*
       tokens (app-tables.css) now own header typography. */
    padding: 0.42rem 0.7rem;
}
/* Inline reference text inside the headers (the "(X units)" / "(Y sqft)"
   spans). Slightly smaller than the header label so the column name stays
   visually dominant. */
#tabpane-sources-uses .app-table thead th small {
    font-size: 0.7rem;
    letter-spacing: 0;
    text-transform: none;
}

/* Per-unit / per-sqft readonly cells render in black so the calculated
   value is legible against the white default background. Editable
   per-sqft inputs (e.g. Roof Replacement when Type=Per Sqft) lack the
   [readonly] attribute and keep the default editable blue text.
   Subtotal/total amount cells (.su-input-summary) get the same treatment —
   without this, .form-control[readonly] in global.css paints them grey
   (#6b7280) and they look faded next to per-unit/per-sqft.
   The Sources rows (Senior Debt, Mezz/Pref Equity, Sponsor & Investor
   Equity) are all readonly auto-calculated displays — Type %, Amount $,
   per-unit, per-sqft — so [id^="sources_"] covers all four columns. */
#tabpane-sources-uses .app-table input[readonly][id$="_per_unit"],
#tabpane-sources-uses .app-table input[readonly][id$="_per_sqft"],
#tabpane-sources-uses .app-table input[readonly].su-input-summary,
#tabpane-sources-uses .app-table input[readonly].su-input-summary-danger,
#tabpane-sources-uses .app-table input[readonly][id^="sources_"],
#tabpane-sources-uses .app-table input[readonly]#su_property_acquisition {
    color: #000;
}

/* Right-align $ values in the Amount / Per Unit / Per Sqft columns of
   both the Sources and Uses tables. First two columns (Item, Type) keep
   default left alignment so labels and dropdown text stay readable. */
#tabpane-sources-uses .app-table tbody td:nth-child(n+3) input {
    text-align: right;
}

/* Exception: the three Sources rows (Senior Debt, Mezz/Pref Equity,
   Sponsor & Investor Equity) show a calculated % in their Type cell — not a
   dropdown — so right-align those to match the $ columns. The Uses Type
   column keeps its left-aligned Per Unit/Per Sqft/Lump Sum dropdowns. */
#tabpane-sources-uses .app-table input[id^="sources_"][id$="_type"] {
    text-align: right;
}

/* Fee % inputs (Construction Mgmt, Contingency, Working Capital, Acquisition,
   Assumption, Lender Broker, Mortgage Recording Tax, Equity Fee) carry a
   baked-in "X.XX% of <basis>" label in their value (replacing the old Bootstrap
   input-group addon), so they're wider than a bare number field and read
   left-to-right. */
#tabpane-sources-uses .su-pct-input {
    width: 150px;
    text-align: left;
}

/* Bump font-weight on all body inputs/selects in the S&U tables (Type,
   Amount, Per Unit, Per Sqft columns) so values render with similar visual
   weight to the rest of the app's tables — the canonical .app-table data
   inputs render at 0.65rem where the default 400 weight reads fine, but
   S&U overrides font-size to 0.85rem and the same 400 weight looks thin
   in the wider boxes. 600 matches the existing .su-input-summary weight
   so the totals row no longer reads heavier than the data rows. */
#tabpane-sources-uses .app-table tbody td input,
#tabpane-sources-uses .app-table tbody td select {
    font-weight: 600;
    /* Compact density: shrink the form-control-sm box so rows pack tighter. */
    padding-top: 0.12rem;
    padding-bottom: 0.12rem;
    min-height: 0;
    line-height: 1.4;
}

/* ==========================================================
   Subtle Card Wrappers
   Translucent panels used as section wrappers in waterfall, tax,
   and property tabs. The two variants differ only in border-radius.
   Apply alongside any layout class:
       <div class="app-card-subtle"> ... </div>
   For larger pill-style corners (waterfall hurdle cards):
       <div class="app-card-subtle-lg"> ... </div>
   ========================================================== */

.app-card-subtle {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 0.6rem;
}

.app-card-subtle-lg {
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 0.85rem;
}

/* Dark navy input/select used in property-tab dropdowns + filter chips */
.app-input-dark {
    background: var(--bg-primary);
    color: var(--primary-text);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 0.4rem;
    padding: 0.15rem 0.3rem;
    font-size: 0.8rem;
    cursor: pointer;
}

/* Property-tab card chip (white-low-alpha bg, primary text, rounded) */
.app-chip {
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.2);
    color: var(--primary-text);
    border-radius: 0.5rem;
    padding: 0.3rem 0.5rem;
    font-size: 0.8rem;
}

/* Faint horizontal divider — `border-bottom: 1px solid rgba(255,255,255,0.1)`
   pattern that proliferated across deal-detail panels for separating list rows. */
.app-divider-bottom {
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

/* Accent text (brand gold). Was previously defined inline in index.html's
   <style> block at line 873; relocated here so any template can use it. */
.text-accent {
    color: var(--accent-text);
}

/* Faded text — same as .text-muted but without Bootstrap's !important
   (relocated from index.html). Use when you need to override on a child
   without escalating. */
.text-faded {
    color: var(--secondary-text);
}

/* Background helpers — single-purpose, used alongside .app-card-very-dark
   when the inline pattern only carries the bg (not the border). */
.bg-app-very-dark { background: #161c23; }
.border-faint    { border: 1px solid rgba(255, 255, 255, 0.12); }

/* Disabled / dimmed state — fills the gap between Bootstrap's .opacity-25 and .opacity-50.
   Used for "fully renovated" cells and similar greyed-out content. */
.opacity-40 { opacity: 0.4; }

/* ============ IRA Year-of-Sale slider (in-table) ============
   The slider lives in its own <thead> row above the Year 1..Year 11 header
   cells of the IRA table. Geometry: each year column is 90px wide and the
   slider's <th colspan="11"> spans Y1..Y11. Padding 45px on each side (= half
   a column) makes the slider track end exactly at the CENTER of the Y1 and
   Y11 header cells below — so the thumb at value=N visually lines up on the
   "Year N" label.

   The track fill is driven by --ira-yos-fill (a percentage) set in JS on
   the `input` event, so the gold portion of the track follows the thumb
   live while dragging. Tick marks under the track are JS-generated <span>s
   inside .ira-yos-slider-ticks, positioned at each year's % offset. */
.ira-yos-slider-label-cell {
    background: transparent !important;
    border: none !important;
    padding: 4px 12px !important;
    vertical-align: middle;
}
.ira-yos-slider-cell {
    background: transparent !important;
    border: none !important;
    padding: 8px 45px 14px 45px !important;
    vertical-align: middle;
    position: relative;
}
.ira-yos-slider {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    height: 4px;
    background: linear-gradient(
        to right,
        var(--accent-color) 0%,
        var(--accent-color) var(--ira-yos-fill, 40%),
        rgba(255, 255, 255, 0.07) var(--ira-yos-fill, 40%),
        rgba(255, 255, 255, 0.07) 100%
    );
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.45);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
    padding: 0;
    margin: 0;
    display: block;
    position: relative;
    z-index: 2;
}
.ira-yos-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    background: linear-gradient(180deg, #e3c473 0%, var(--accent-color) 50%, #a07e2e 100%);
    border: 1px solid rgba(0, 0, 0, 0.55);
    border-radius: 50%;
    cursor: grab;
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.25) inset,
        0 1px 3px rgba(0, 0, 0, 0.55);
    transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.ira-yos-slider::-webkit-slider-thumb:hover {
    transform: scale(1.07);
}
.ira-yos-slider::-webkit-slider-thumb:active {
    cursor: grabbing;
    transform: scale(1.12);
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.3) inset,
        0 2px 6px rgba(0, 0, 0, 0.7);
}
.ira-yos-slider::-moz-range-thumb {
    width: 14px;
    height: 14px;
    background: linear-gradient(180deg, #e3c473 0%, var(--accent-color) 50%, #a07e2e 100%);
    border: 1px solid rgba(0, 0, 0, 0.55);
    border-radius: 50%;
    cursor: grab;
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.25) inset,
        0 1px 3px rgba(0, 0, 0, 0.55);
    transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.ira-yos-slider::-moz-range-thumb:hover {
    transform: scale(1.07);
}
.ira-yos-slider::-moz-range-thumb:active {
    cursor: grabbing;
    transform: scale(1.12);
}
.ira-yos-slider::-moz-range-track {
    height: 4px;
    background: transparent;
    border-radius: 2px;
}
.ira-yos-slider:focus { outline: none; }
.ira-yos-slider:focus::-webkit-slider-thumb {
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.3) inset,
        0 2px 6px rgba(0, 0, 0, 0.7),
        0 0 0 3px rgba(201, 168, 76, 0.18);
}
/* Firefox pair for the ring above — without it the slider has NO visible
   keyboard focus there (outline is suppressed on :focus). */
.ira-yos-slider:focus::-moz-range-thumb {
    box-shadow:
        0 1px 0 rgba(255, 255, 255, 0.3) inset,
        0 2px 6px rgba(0, 0, 0, 0.7),
        0 0 0 3px rgba(201, 168, 76, 0.18);
}

/* Tick marks — JS appends 11 <span class="ira-yos-tick">s into this container.
   Each tick is positioned via inline `left: N%` (0%, 10%, ..., 100%). The
   container sits just below the track, lined up with year-column centers. */
.ira-yos-slider-ticks {
    position: absolute;
    left: 45px;
    right: 45px;
    bottom: 5px;
    height: 5px;
    pointer-events: none;
    z-index: 1;
}
.ira-yos-tick {
    position: absolute;
    top: 0;
    width: 1px;
    height: 4px;
    background: rgba(255, 255, 255, 0.2);
    transform: translateX(-50%);
    transition: background 0.15s ease, height 0.15s ease;
}
.ira-yos-tick.is-passed {
    background: rgba(201, 168, 76, 0.55);
}
.ira-yos-tick.is-current {
    background: var(--accent-color);
    height: 6px;
    top: -1px;
    width: 2px;
}

/* Year-header cells — highlight the column that matches the current Year of
   Sale. Restrained: bolder weight + accent color, no glow. JS toggles
   .ira-year-selected on the matching <th data-year="N">. */
.ira-year-header.ira-year-selected {
    color: var(--accent-color);
    font-weight: 700;
}
.ira-year-header.ira-year-selected .ira-year-date {
    color: var(--accent-color);
    opacity: 0.95;
}

/* ============ IRA table typography (templates/tabs/returns.html) ============
   Dedup 2026-07-06: these replace inline style="" attrs that were copy-pasted
   across the static scaffold (the table font-size, 11 year-header <th>s, their
   11 .ira-year-date <div>s, and the 10 Y0 assumption inputs). Structural inline
   styles stay in the template (table-layout/width/min-width on the <table>,
   per-input width, colgroup widths). */
#inv-return-table { font-size: .64rem; }

/* Year-header cells — compact two-line header ("Year N" over its projected
   date). The width is informational only: under table-layout:fixed the
   <colgroup> governs column widths. */
#inv-return-table .ira-year-header {
    width: 90px;
    padding: 0.25rem 0.5rem;
    line-height: 1.15;
    font-size: 0.75rem;
}
/* Projected-date sub-label inside each year header (painted by returns.js /
   proforma.js). Only typography here — color/opacity for the selected column
   come from .ira-year-header.ira-year-selected .ira-year-date above (the ID
   prefix keeps this opacity winning, matching the old inline behavior). */
#inv-return-table .ira-year-date {
    font-size: .5rem;
    font-weight: 400;
    opacity: .85;
    text-transform: none;
    letter-spacing: .3px;
}

/* Y0 assumption inputs (Assumptions column of the IRA table).
   Base = the dominant 0.75rem size (Partnership Expenses, Escrow Reserves,
   AM Fee %, Exit Cap Rate %, Transaction Expense %).
   --xs = the compact variant (the three Loan Points exit-fee inputs + the
   Year of Sale input inside the Residual Sale band). */
#inv-return-table .ira-assum-input {
    font-size: 0.75rem;
    padding: 0.1rem 0.3rem;
}
#inv-return-table .ira-assum-input--xs {
    font-size: 0.65rem;
    padding: 0.05rem 0.25rem;
}
/* AM-fee calculation-mode <select> next to the fee % input. */
#inv-return-table .ira-assum-select {
    font-size: 0.7rem;
    padding: 0.1rem 0.4rem;
}

/* ==========================================================
   BLUEPRINT THEME — relocated from templates/index.html inline <style>
   block. These were the institutional dark/gold base theme rules that
   couldn't live in tab partials because they cross-cut the entire app
   (modal stacking, base layout, utility overrides, page-modal z-index).
   ========================================================== */

html, body {
    margin: 0;
    padding: 0;
    min-height: 100vh;
    color: var(--primary-text) !important;
    font-weight: 400;
    line-height: 1.6;
    position: relative;
}

/* Heading sizes — typography family/weight/letter-spacing live in
   the Headings rule earlier in this file. */
h1 { font-size: 1.75rem; letter-spacing: -0.02em; }
h2 { font-size: 1.375rem; }
h3 { font-size: 1.125rem; }
h4 { font-size: 1rem; }
h5 { font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.05em; }
h6 { font-size: 0.8125rem; font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; }

/* Create New Deal Modal — 3-tier nesting (modal / dialog / content)
   preserves input pointer-events through the stacking context. */
#createNewDealModal {
    z-index: var(--z-modal) !important;
}
#createNewDealModal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#createNewDealModal .modal-content {
    position: relative;
    z-index: calc(var(--z-modal) + 2) !important;
}
#createNewDealModal .modal-body {
    position: relative;
    z-index: 1;
}

/* Deal Details quick-view modal (dashboard, opened by openDealModal()) — same
   3-tier lift as #createNewDealModal. Without it the global
   `.modal-backdrop.show { z-index: 10059 }` rule renders the backdrop ON TOP of
   the modal (Bootstrap default modal z-index is only 1055), greying it out and
   swallowing every click on its buttons. */
#dealDetailsModal {
    z-index: var(--z-modal) !important;
}
#dealDetailsModal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#dealDetailsModal .modal-content {
    position: relative;
    z-index: calc(var(--z-modal) + 2) !important;
}
#dealDetailsModal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* Rent Study Deck Preview modal — same 3-tier z-index lift as
   #createNewDealModal so the fullscreen modal sits above the page
   header (which uses a high z-index that covers Bootstrap's default
   modal at 1055). Pair the backdrop bump so it covers the navbar too. */
.modal-backdrop.show {
    z-index: var(--z-modal-backdrop);
}
#rs_deck_preview_modal {
    z-index: var(--z-modal) !important;
}
#rs_deck_preview_modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#rs_deck_preview_modal .modal-content {
    position: relative;
    z-index: calc(var(--z-modal) + 2) !important;
}
/* Custom input styling for Create New Deal modal — no form-control class
   to avoid Bootstrap interference with the dark-theme palette. */
#createNewDealModal .create-deal-input {
    display: block;
    width: 100%;
    position: relative;
    z-index: 100;
    pointer-events: auto !important;
    -webkit-user-select: text !important;
    user-select: text !important;
    background: #0d2840 !important;
    border: 2px solid rgba(255, 255, 255, 0.4) !important;
    color: #ffffff !important;
    font-family: var(--font-sans);
    font-size: 1rem;
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    outline: none;
}
#createNewDealModal input.create-deal-input {
    cursor: text !important;
}
#createNewDealModal select.create-deal-input {
    cursor: pointer !important;
    appearance: auto;
    -webkit-appearance: menulist;
}
#createNewDealModal .create-deal-input:focus {
    background: #0a1f33 !important;
    border-color: #c9a84c !important;
    box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.25) !important;
    outline: none !important;
}
#createNewDealModal .create-deal-input::placeholder {
    color: rgba(255, 255, 255, 0.5) !important;
}

/* Bootstrap btn-close is dark by default — invert for the dark theme. */
.btn-close {
    filter: invert(1) brightness(2);
}

/* ---- Form labels ---- */
.form-label, label {
    font-weight: 500;
    letter-spacing: normal;
    margin-bottom: 0.5rem;
    font-size: 0.875rem;
}

/* Standardized save-button class (used on every per-tab save button). */
.ndt-save-btn {
    white-space: nowrap;
    font-weight: 600;
}

/* Purchase Price required pulse animation. JS in templates/tabs/
   property.html toggles this on #purchase-price-card when the user tries
   to navigate to a gated tab without entering a price. */
@keyframes ppRequiredPulse {
    0%, 100% { box-shadow: 0 0 12px rgba(201, 168, 76, 0.25), 0 2px 10px rgba(201, 168, 76, 0.12); }
    50% { box-shadow: 0 0 24px rgba(201, 168, 76, 0.55), 0 2px 16px rgba(201, 168, 76, 0.3); border-color: #e0c060; }
}

/* ---- Utility overrides ---- */
/* Bootstrap defines .text-success/-warning/-danger with !important natively, so we match. */
.text-success { color: var(--success-color) !important; }
.text-warning { color: var(--warning-color) !important; }
.text-danger { color: var(--danger-color) !important; }

/* Negative number formatting */
.negative-number {
    color: var(--danger-color);
}

/* Bootstrap .bg-white override for the dark theme — translucent white
   over a bordered surface, never opaque white. */
.bg-white {
    background: rgba(255, 255, 255, 0.08) !important;
    border: 2px solid var(--border-color);
}

/* ---- Page-modal z-index hierarchies ----
   Each modal needs its own pointer-events / dialog-z-index hierarchy to
   stack above the navbar (z-index var(--z-modal) = 10060) and the
   .modal-backdrop. Bootstrap's defaults aren't enough when the modal is
   nested or appended late by JS. */

/* Floorplan grouping modal (built dynamically by static/js/tabs/rentroll.js). */
#fp-grouping-modal {
    z-index: var(--z-modal) !important;
}
#fp-grouping-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#fp-grouping-modal .modal-content {
    pointer-events: all !important;
}
#fp-grouping-modal ~ .modal-backdrop {
    z-index: var(--z-modal-backdrop) !important;
}
/* Floorplan preview modal (built dynamically by static/js/tabs/rentroll.js).
   Sits a sub-layer above the grouping modal it can be launched from. */
#fp-preview-modal {
    z-index: calc(var(--z-modal) + 10) !important;
}
#fp-preview-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 11) !important;
}
#fp-preview-modal .modal-content {
    pointer-events: all !important;
}
#fp-preview-modal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) + 9) !important;
}

/* Post-upload "Review Uploaded Units" preview + "Delete Rent Roll" confirm
   (both injected by static/js/tabs/rentroll.js). Without these lifts the
   global `.modal-backdrop.show { z-index: 10059 }` rule renders the backdrop
   ON TOP of the modal (Bootstrap default modal z-index is only 1055), which
   swallows every click on the modal's buttons. */
#rr-unit-review-modal,
#rr-delete-modal {
    z-index: var(--z-modal) !important;
}
#rr-unit-review-modal .modal-dialog,
#rr-delete-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#rr-unit-review-modal .modal-content,
#rr-delete-modal .modal-content {
    pointer-events: all !important;
}
#rr-unit-review-modal ~ .modal-backdrop,
#rr-delete-modal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* Rent Comps upload modal (injected by static/js/tabs/rent_study.js). */
#prUploadSavedModal {
    z-index: var(--z-modal) !important;
}
#prUploadSavedModal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#prUploadSavedModal .modal-content {
    pointer-events: all !important;
}
#prUploadSavedModal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* Auto Combine criteria modal (injected by static/js/tabs/rent_study.js). */
#rs-combine-modal {
    z-index: var(--z-modal) !important;
}
#rs-combine-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#rs-combine-modal .modal-content {
    pointer-events: all !important;
}
#rs-combine-modal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* Manual Add Comp modal (injected by static/js/tabs/rent_study.js). */
#rs-manual-add-modal {
    z-index: var(--z-modal) !important;
}
#rs-manual-add-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#rs-manual-add-modal .modal-content {
    pointer-events: all !important;
}
#rs-manual-add-modal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* Expense Bridge monthly drilldown modal (built by static/js/tabs/proforma.js).
   Must sit above .modal-backdrop.show (z-index var(--z-modal-backdrop) = 10059)
   or the backdrop renders ON TOP of the modal content and blocks interaction. */
#expense-bridge-monthly-modal {
    z-index: var(--z-modal) !important;
}
#expense-bridge-monthly-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#expense-bridge-monthly-modal .modal-content {
    pointer-events: all !important;
}
#expense-bridge-monthly-modal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* Debt/Equity monthly drilldown modal (built by static/js/tabs/financing.js).
   Same stacking constraint as the expense-bridge modal above. */
#de-monthly-modal {
    z-index: var(--z-modal) !important;
}
#de-monthly-modal .modal-dialog {
    z-index: calc(var(--z-modal) + 1) !important;
}
#de-monthly-modal .modal-content {
    pointer-events: all !important;
}
#de-monthly-modal ~ .modal-backdrop {
    z-index: calc(var(--z-modal) - 1) !important;
}

/* ---- Rent Data / Lease Stats column toggle ----
   Rent Roll table has two view modes; classes on the table root hide
   the alternate column set. */
.view-rent-data .col-stats { display: none !important; }
.view-lease-stats .col-rent { display: none !important; }

/* ---- Year-header column hover (Expense Bridge) ----
   th gets the translucent tint LAYERED over the opaque header bg
   (gradient on top of var) — without the opaque base, sticky thead
   cells go see-through on hover and reveal scrolling rows below.
   The year label (row 1) and its closing date (row 2, .eb-year-date)
   are now sibling <th> cells; both highlight together on column hover. */
.expense-bridge-year-header,
.eb-year-date {
    transition: background-color 0.2s ease, color 0.2s ease;
}
.expense-bridge-year-header.eb-year-col-hover {
    background: linear-gradient(rgba(158, 203, 255, 0.15), rgba(158, 203, 255, 0.15)), var(--tbl-header-bg);
    color: #fff;
    border-bottom-color: transparent;   /* unify with the date cell below — no "split into 2" look */
}
.eb-year-date.eb-year-col-hover {
    background: linear-gradient(rgba(158, 203, 255, 0.15), rgba(158, 203, 255, 0.15)), var(--tbl-header-bg);   /* match the year cell exactly */
    color: #fff;
    border-top-color: transparent;
}
.expense-bridge-year-header.eb-year-col-hover i {
    opacity: 1;
}

/* Refreshed year-column headers (Proforma) — uniform, modern treatment.
   Replaces the repeated inline th styles; keeps data-year/title/class hooks. */
#proforma-review-table thead th.expense-bridge-year-header {
    padding: 0.45rem 0.5rem;
    /* font-size / font-weight / letter-spacing removed 2026-07-13 — the uniform
       --tbl-header-* tokens (app-tables.css) now own header typography. */
    line-height: 1.2;
    cursor: pointer;
}

/* ===== Proforma projection table — modernized header hierarchy =====
   Two-tier head: a bold uppercase primary row (period + year columns) over a
   lighter caption row (closing dates / $/Unit / assumptions). Centralizes the
   typography the per-<th> inline styles used to carry, so the whole head reads
   as one cohesive unit. Only typography is set here — sticky positioning,
   z-index, backgrounds and the column-hover machinery stay in app-tables.css /
   the .eb-year-* rules above. */
#proforma-review-table thead th.is-sticky-col,
#proforma-review-table thead th.is-sticky-col-2,
#proforma-review-table thead th.is-sticky-col-3 {
    padding: 0.45rem 0.5rem;
    /* font-size / font-weight / letter-spacing removed 2026-07-13 — uniform
       --tbl-header-* tokens (app-tables.css) now own header typography. */
    line-height: 1.2;
    text-transform: uppercase;
}
#proforma-review-table thead tr.is-subheader th {
    padding: 0.55rem 0.5rem;
    /* font-size !important removed 2026-07-13 — row routes through the shared
       .is-subheader treatment (app-tables.css) so header typography is uniform. */
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.25;
    text-transform: none;
    color: rgba(255, 255, 255, 0.85);
    /* distinct caption band so the date reads as its own cell under the year */
    background: linear-gradient(rgba(0, 0, 0, 0.14), rgba(0, 0, 0, 0.14)), var(--tbl-header-bg);
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}
/* Light mode: the white-alpha caption text was invisible on the light header —
   use a readable grey and a light band instead. */
html[data-theme="light"] #proforma-review-table thead tr.is-subheader th {
    color: var(--tbl-header-fg);
    background: linear-gradient(rgba(0, 0, 0, 0.045), rgba(0, 0, 0, 0.045)), var(--tbl-header-bg);
    border-top: 1px solid rgba(0, 0, 0, 0.08);
}
#proforma-review-table thead th.eb-year-date {
    cursor: pointer;
}

/* ===== Proforma projection table — "institutional ledger" body =====
   The table is an intentionally light spreadsheet embedded in the dark shell
   (white body — see the --tbl-* defaults in app-tables.css). This block
   declutters its dense black grid into a clean ledger: no interior vertical
   rules, soft horizontal hairlines, structural separators only on group /
   subtotal / total rows, a floating frozen label column, and a quiet data-row
   hover. Everything is scoped to #proforma-review-table so no other .app-table
   (rent study, sources & uses, etc.) is touched. ID specificity (1,x,y) lets
   these survive the (0,2,3) row-state rules in app-tables.css. */

/* Body-ledger rules are shared by the main projection table AND the per-year
   monthly-breakdown modal table (#expense-bridge-monthly-table) so both read
   identically. Grouped by id to keep (1,x,y) specificity over the .app-table
   base. */

/* Strip every cell border, then re-add a soft horizontal rule + a very light
   vertical column guide (much lighter than the original black grid). */
#proforma-review-table tbody td,
#expense-bridge-monthly-table tbody td {
    border: 0;
    border-bottom: 1px solid var(--tbl-hairline);
    border-right: 1px solid var(--tbl-hairline);
}
/* Light-on-dark column guides in the header, aligned to the body lines. */
#proforma-review-table thead th,
#expense-bridge-monthly-table thead th {
    border-right: 1px solid rgba(255, 255, 255, 0.14);
}
/* Light frame around the whole header band so it reads as a defined bar against
   the dark page (top of row 1, bottom of the subheader row, + outer edges). */
#proforma-review-table thead tr:first-child th,
#expense-bridge-monthly-table thead tr:first-child th {
    border-top: 1px solid rgba(255, 255, 255, 0.22);
}
#proforma-review-table thead tr:last-child th,
#expense-bridge-monthly-table thead tr:last-child th {
    border-bottom: 1px solid rgba(255, 255, 255, 0.22);
}
#proforma-review-table thead th:first-child,
#expense-bridge-monthly-table thead th:first-child {
    border-left: 1px solid rgba(255, 255, 255, 0.22);
}
#proforma-review-table thead th:last-child,
#expense-bridge-monthly-table thead th:last-child {
    border-right: 1px solid rgba(255, 255, 255, 0.22);
}

/* Structural separators, re-added on top of the reset above. */
#proforma-review-table tbody tr.is-group-header td,
#expense-bridge-monthly-table tbody tr.is-group-header td {
    border-top: 1px solid #c9d0db;
}
#proforma-review-table tbody tr.is-subtotal td,
#proforma-review-table tbody tr.is-subtotal-success td,
#proforma-review-table tbody tr.is-subtotal-warning td,
#expense-bridge-monthly-table tbody tr.is-subtotal td {
    border-top: 1px solid #c2c7cf;
}
#proforma-review-table tbody tr.is-total td,
#expense-bridge-monthly-table tbody tr.is-total td {
    border-top: 2px solid var(--tbl-total-border, #a8893e);
    border-bottom: 2px solid var(--tbl-total-border, #a8893e);
}
#proforma-review-table tbody tr.is-section td,
#expense-bridge-monthly-table tbody tr.is-section td {
    border-top: 0;
    border-bottom: 0;
}

/* Gold rail on the section / group header bands — an institutional accent. */
#proforma-review-table tbody tr.is-section td:first-child,
#proforma-review-table tbody tr.is-group-header td:first-child,
#expense-bridge-monthly-table tbody tr.is-section td:first-child,
#expense-bridge-monthly-table tbody tr.is-group-header td:first-child {
    border-left: 3px solid var(--accent-color, #c9a84c);
}

/* No vertical column guides on the dark section / group-header bands — they'd
   show as light ticks around the inline inputs (e.g. the % Growth Rate cell). */
#proforma-review-table tbody tr.is-section td,
#proforma-review-table tbody tr.is-group-header td,
#expense-bridge-monthly-table tbody tr.is-section td,
#expense-bridge-monthly-table tbody tr.is-group-header td {
    border-right-color: transparent;
}

/* Boundary between the frozen assumptions block and the year projections — a
   clean divider line (no scroll shadow; the table fits at 100%). Main table
   only — the monthly modal has a single sticky column. */
#proforma-review-table thead th.is-sticky-col-3,
#proforma-review-table tbody td.is-sticky-col-3 {
    border-right: 1px solid var(--tbl-hairline);
}

/* Quiet hover on data rows only (skips every colored state row). */
#proforma-review-table tbody tr:not(.is-section):not(.is-group-header):not(.is-total):not(.is-subtotal):not(.is-subtotal-success):not(.is-subtotal-warning):not(.is-metric):not(.is-highlight):not(.is-synthetic):hover td,
#expense-bridge-monthly-table tbody tr:not(.is-section):not(.is-group-header):not(.is-total):not(.is-subtotal):not(.is-subtotal-success):not(.is-subtotal-warning):not(.is-metric):not(.is-highlight):not(.is-synthetic):hover td {
    background: #eff4fb;
}

/* ===== Proforma editable cells — tinted input cells =====
   Override inputs (.prf-per-unit-input) get the classic financial-model
   "input cell" cue: a soft blue wash + light box at rest so they unmistakably
   read as editable against the plain white readonly cells. Hover firms the box
   up; focus turns it white with a gold ring. Excluded so they keep their own
   distinct treatment: the always-gold growth-rate assumption inputs
   (.prf-growth-input), the cream unsaved-edit state (.is-dirty — except it
   still gets the gold focus ring), and the readonly computed state (.is-calc).
   Scoped to #proforma-review-table so the .prf-per-unit-input reused in
   Financing is untouched. box-sizing:border-box (set on the input elsewhere)
   keeps the border swap layout-stable across states. */
#proforma-review-table input.prf-per-unit-input:not(.prf-growth-input):not(.is-dirty):not(.is-calc) {
    background: #e6f0fb;             /* soft blue input-cell wash — "editable" */
    border: 1px solid #a6c0e0;       /* visible soft box */
    box-shadow: none;
    border-radius: 4px;
    transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
#proforma-review-table input.prf-per-unit-input:not(.prf-growth-input):not(.is-dirty):not(.is-calc):hover:not(:focus) {
    background: #ffffff;
    border-color: #6f9fd4;          /* firmer box on hover */
}
#proforma-review-table input.prf-per-unit-input:not(.prf-growth-input):not(.is-calc):focus {
    outline: none;
    background: #ffffff;
    border-color: var(--accent-color, #c9a84c);
    box-shadow: 0 0 0 2px rgba(201, 168, 76, 0.35);   /* gold focus ring */
}

/* "You changed this" marker — a gold left-tick on any cell whose value is an
   applied override (.prf-overridden is stamped by the renderer when
   row.proforma_source === 'override'). Presentation only. */
#proforma-review-table tbody td.prf-overridden {
    box-shadow: inset 3px 0 0 0 var(--accent-color, #c9a84c);
}

/* ---- Year-header column hover (Debt/Equity) ----
   Same opaque-base pattern as Expense Bridge but with the gold tint. */
.de-year-header,
.de-year-date {
    transition: background-color 0.2s ease, color 0.2s ease;
}
.de-year-header.de-year-col-hover {
    background: linear-gradient(rgba(255, 193, 7, 0.15), rgba(255, 193, 7, 0.15)), var(--tbl-header-bg);
    color: #fff;
}
.de-year-date.de-year-col-hover {
    background-color: transparent;
}
.de-year-header.de-year-col-hover i {
    opacity: 1;
}

/* ---- Render-perf hints (relocated from Critical CSS inline block) ---- */
.tab-pane:not(.active) {
    content-visibility: auto;
    contain-intrinsic-size: 0 500px;
}
.table-responsive {
    content-visibility: auto;
    contain-intrinsic-size: 0 300px;
}

/* ---- Dark-theme page base ----
   The REUW navy (#0a1628 deep navy / #0f2038 raised) as a subtle radial so the
   dark theme is blue edge-to-edge (Carson, 2026-06-29). Preserved from the
   inline <style id="dark-theme-failsafe"> block in index.html, but the old
   charcoal gradient (#20242b → #121418) was swapped to the brand navy so the
   page base matches the cards/nav instead of reading black.
   LIGHT MODE: scoped to :not([data-theme="light"]) so this !important base never
   touches light mode (light lets the theme tokens paint the base). */
html:not([data-theme="light"]),
html:not([data-theme="light"]) body {
    background: radial-gradient(circle at 20% 20%, #0f2038, #0a1628 60%) !important;
}
/* Light-mode page base: re-assert with !important so nothing stale can pin it
   dark. Token-driven, so it follows the palette. */
html[data-theme="light"],
html[data-theme="light"] body {
    background: var(--bg-primary) !important;
}

/* ==========================================================
   OM (Offering Memorandum) PDF drop zone — relocated from
   templates/index.html. Used in templates/tabs/property.html
   for the OM PDF upload widget. Styling cycles through
   default → om-uploading → om-uploaded states.
   ========================================================== */
.om-drop-area {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.6rem 0.8rem;
    border: 2px dashed rgba(13, 202, 240, 0.3);
    border-radius: 0.5rem;
    background: rgba(13, 202, 240, 0.04);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
    min-height: 48px;
}
.om-drop-area:hover,
.om-drop-area:focus-within {
    border-color: rgba(13, 202, 240, 0.6);
    background: rgba(13, 202, 240, 0.08);
    box-shadow: 0 0 12px rgba(13, 202, 240, 0.15);
}
.om-drop-area.om-uploading {
    border-color: #c9a84c;
    background: rgba(201, 168, 76, 0.06);
}
.om-drop-area.om-uploaded {
    border-color: rgba(40, 167, 69, 0.5);
    background: rgba(40, 167, 69, 0.06);
}
.om-drop-icon {
    font-size: 1.4rem;
    color: rgba(13, 202, 240, 0.5);
    transition: color 0.2s;
}
.om-drop-area:hover .om-drop-icon {
    color: rgba(13, 202, 240, 0.8);
}
.om-drop-msg {
    font-size: 0.75rem;
    color: var(--secondary-text);
    text-align: center;
}

/* ==========================================================
   Toasts + Bootstrap utility-button overrides — relocated from
   templates/index.html. The toast container is global (used by
   showToast() in index.html and rent_study.js / dashboard.js).
   ========================================================== */
.toast-container {
    position: fixed;
    top: 20px;
    right: 20px;
    /* Toasts must outrank modals/backdrops (save-failure toasts can fire
       while a modal is open) — 1050 left them hidden behind the backdrop. */
    z-index: var(--z-toast);
}
.toast {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 0.75rem;
    box-shadow: var(--card-shadow);
    color: var(--primary-text);
}
.toast-header {
    background: transparent;
    border-bottom: 1px solid var(--border-color);
    color: var(--primary-text);
}
.toast-body {
    color: var(--primary-text);
}

.btn-outline-light {
    color: var(--primary-text);
    border-color: rgba(255, 255, 255, 0.2);
}
.btn-outline-light:hover {
    background-color: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.3);
    color: var(--primary-text);
}

.btn-link {
    color: var(--accent-color);
    text-decoration: none;
}
.btn-link:hover {
    color: var(--accent-color-hover);
}

/* ==========================================================
   Deals dashboard styling — relocated from templates/index.html.
   Markup lives in templates/partials/deals_dashboard.html;
   behavior in static/js/dashboard.js. Renders only on the
   /deals route (no preload_deal_id).
   ========================================================== */
/* (.deals-history-section panel + #deals-table base styling were superseded by
   the DEALS DASHBOARD — PREMIUM PASS block at the end of this file, 2026-07-28.) */

/* Scrollbar for deals table */
#deals-table-container .table-responsive::-webkit-scrollbar { width: 5px; }
#deals-table-container .table-responsive::-webkit-scrollbar-track { background: transparent; }
#deals-table-container .table-responsive::-webkit-scrollbar-thumb { background: rgba(201, 168, 76, 0.2); border-radius: 3px; }
#deals-table-container .table-responsive::-webkit-scrollbar-thumb:hover { background: rgba(201, 168, 76, 0.35); }

/* (#open-full-new-deal-btn CTA + the dashboard search/filter field styling were
   superseded by the DEALS DASHBOARD — PREMIUM PASS block at the end of this
   file, 2026-07-28 — same !important mechanics kept there so the fields still
   beat Bootstrap's white form-control/form-select rules.) */

#back-to-dashboard-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
}

@media (max-width: 768px) {
    .action-btn {
        padding: 0.4rem 0.8rem;
        font-size: 0.8rem;
    }
}
/* (Mobile density for .deals-history-section/#deals-table and ALL dashboard
   light-mode theming were superseded by the DEALS DASHBOARD — PREMIUM PASS
   block at the end of this file, 2026-07-28.) */

/* ==========================================================
   Layout + Form-select contrast fix — relocated from
   templates/index.html. The form-select rules force a white
   background + blue text against the dark theme; required
   because the dark <option> backgrounds make a white-bg select
   the most legible (verified by users via blueprint review).
   The base SVG chevron + sizing rules live higher in this file.
   ========================================================== */
.container-fluid {
    z-index: 10;
    position: relative;
}

select.form-select,
.form-select {
    background-color: #ffffff !important;
    color: #0d6efd !important;
    border: 1px solid rgba(91, 165, 220, 0.85) !important;
}
select.form-select:focus,
.form-select:focus {
    background-color: #ffffff !important;
    color: #0d6efd !important;
    border-color: #0d6efd !important;
    box-shadow: 0 0 0 2px rgba(91, 165, 220, 0.4) !important;
}
/* Option text (most browsers) — keep dark dropdown for legibility while open */
select.form-select option {
    background: rgba(22, 61, 100, 0.95);
    color: #ffffff;
}
select.form-select option:disabled {
    color: #6c7a86;
}
.form-select.form-select-sm {
    background-color: #ffffff !important;
}
/* Override placeholder light-on-light issues */
select.form-select option[value=""],
select.form-select:invalid {
    color: rgba(13, 110, 253, 0.55) !important;
}
.input-group > .form-select {
    flex: 0 0 auto;
}
/* Tax database state/muni selects — keep white */
#taxdb_state.form-select,
#taxdb_muni.form-select,
#taxdb_state.form-select:focus,
#taxdb_muni.form-select:focus {
    background: #ffffff;
}


/* ========== GLOBAL NAV EXCEL BUTTON ========== */
/* Sits in the right cluster of the deal-shell control row. Quiet gold-tinted
   brand button — the Bootstrap green .btn-success look fought the navy/gold
   chrome (class dropped from the markup 2026-07-13). The adjacent status span
   shows transient "Generating…/Downloaded/error" feedback. */
.nav-excel-btn {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    height: 40px;
    padding: 0 0.9rem;
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 0.82rem;
    white-space: nowrap;
    color: var(--accent-text);
    background: color-mix(in srgb, var(--accent-color) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent-color) 40%, var(--border-color));
    border-radius: 8px;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.nav-excel-btn:hover,
.nav-excel-btn:focus-visible {
    color: var(--accent-text);
    background: color-mix(in srgb, var(--accent-color) 18%, transparent);
    border-color: var(--accent-color);
}
.nav-excel-btn:active {
    color: var(--accent-text);
    background: color-mix(in srgb, var(--accent-color) 24%, transparent);
    border-color: var(--accent-color);
}

/* Deal name — the dominant element of the control row. Sits left, right after
   the breadcrumb; larger + semibold so it outranks the controls; truncates
   with an ellipsis instead of wrapping. The wrap doubles as the flex:1 spacer
   that pushes the presence/share/Excel/account cluster to the right edge.
   (The old centered "glass plate" treatment went with the skyline — the deal
   bar is flat now.) */
.nav-deal-name-wrap {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: flex-start;
}
.nav-deal-name {
    max-width: 100%;
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 1.05rem;
    letter-spacing: 0.01em;
    color: var(--primary-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.nav-deal-name:empty { display: none; }
.nav-excel-status {
    flex-shrink: 0;
    white-space: nowrap;
    color: var(--secondary-text);
}
.nav-excel-status.is-error { color: #dc3545; }
.nav-excel-status.is-success { color: #28a745; }

/* L13 (CSP nonce migration): hover states moved off inline on* handlers so
   script-src can drop 'unsafe-inline'. Values match the prior inline literals. */
.nav-dash-link:hover { background: rgba(201, 168, 76, 0.08); }
.refresh-deals-hover { border-color: rgba(255, 255, 255, 0.08); }
.refresh-deals-hover:hover { border-color: rgba(201, 168, 76, 0.3); color: var(--accent-color) !important; }

/* ==========================================================================
   Mobile: dashboard + deal-app top bar (≤768px)
   The dashboard header and deal-page #reuw-top-nav use a 72px logo and 3rem
   side padding tuned for desktop; on a phone that overflows (clips the account
   email / Excel button). Shrink the shared logo, trim padding, and collapse the
   account button to its icon. !important is intentional here — these elements
   carry inline styles (padding/height) that a plain rule can't override.
   ========================================================================== */
@media (max-width: 768px) {
    .nav-dash-link img { height: 30px !important; }      /* brand frieze — keep the 30px system size (rule predates it: 72px logo -> 44px) */
    #account-menu-email { display: none; }                /* icon-only account button */
    .reuw-dash-navrow { padding-left: 1rem !important; padding-right: 1rem !important; }
    .reuw-dash-main { padding-left: 1rem !important; padding-right: 1rem !important; }
}

/* ==========================================================================
   Legal disclaimer — shared footer note (partials/legal_disclaimer.html).
   "Estimates / not investment advice / verify independently" — rendered across
   the deal app, dashboard, and marketing/legal pages. Small, muted, centered.
   ========================================================================== */
.legal-disclaimer {
    max-width: 760px;
    margin: 1.5rem auto 0;
    padding: 0 1rem 1.25rem;
    text-align: center;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--secondary-text);
}
.legal-disclaimer a { color: var(--accent-color); text-decoration: none; }
.legal-disclaimer a:hover { text-decoration: underline; }

/* ==========================================================================
   Responsive deal-tab dropdown (static/js/tab_dropdown.js)
   Wide/medium: the horizontal #existing-top-tabs bar shows (content-width,
   wraps to extra rows as needed). Below 1100px the bar is hidden and a single
   dropdown drives it — no more vertical stacking on narrow windows.
   ========================================================================== */
.ndt-tab-select {
    display: none;            /* hidden until the threshold below */
    flex: 1 1 auto;
    min-width: 0;
    max-width: 360px;
    margin: 0;                /* the control row centers items now — the old
                                 0.4rem top margin sat it below the midline */
    padding: 0.5rem 0.8rem;
    background: linear-gradient(180deg, rgba(20,34,56,0.9) 0%, rgba(14,26,44,0.75) 100%);
    color: var(--accent-text);
    border: 1px solid rgba(201,168,76,0.28);
    border-radius: 0.5rem;
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    /* gold chevron */
    background-image:
        linear-gradient(180deg, rgba(20,34,56,0.9) 0%, rgba(14,26,44,0.75) 100%),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%23c9a84c' d='M0 0l5 6 5-6z'/%3E%3C/svg%3E");
    background-repeat: no-repeat, no-repeat;
    background-position: center, right 0.7rem center;
    padding-right: 1.8rem;
}
.ndt-tab-select option { background: var(--card-bg); color: var(--primary-text); }

@media (max-width: 1100px) {
    #newDealTabs,
    #existing-top-tabs { display: none; }
    .ndt-tab-select { display: block; }
}

/* ==========================================================================
   Property tab (#tabpane-core) — modern compact refresh (2026-06-22)
   The global .form-control forces 0.625rem 0.875rem padding even on -sm inputs,
   making Property's fields oversized. Scope a compact, modern treatment here
   (higher specificity than the global rule, so no !important), tighten the
   cards/spacing, and make the Purchase-Price requirement obvious.
   ========================================================================== */
#tabpane-core .card { border-radius: 10px; }
/* tighten the inter-field vertical rhythm */
#tabpane-core .row.g-2 { --bs-gutter-y: 0.55rem; }

/* "REQUIRED" pill on the Purchase Price label — prominent + always visible,
   so it's obvious the field gates the other tabs (the gate message itself is
   toggled by property.js when empty). */
.app-required-badge {
    background: var(--accent-color);
    color: #0a1628;
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    padding: 0.14rem 0.5rem;
    border-radius: 4px;
}
#purchase-price-required-msg { font-size: 0.74rem; font-weight: 600; }

/* ============================================================
   Onboarding coachmarks — floating popups that guide the user to
   the next action. Put .app-coach-anchor (position:relative) on the
   wrapper of the field being pointed at, then drop a .app-coach inside
   it; data-caret picks the pointer side. .app-coach.is-inline turns it
   into a normal-flow guidance strip (no float / caret). Dismissal
   persists via localStorage (wired by the inline script in property.html).
   Plain absolute positioning + flow — works in every browser. */
.app-coach-anchor { position: relative; }

.app-coach {
    position: absolute;
    top: calc(100% + 9px);
    left: 0;
    z-index: var(--z-popover);
    width: max-content;
    max-width: min(300px, 90vw);
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    padding: 0.6rem 0.7rem;
    background: rgba(18, 30, 50, 0.82);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(201, 168, 76, 0.5);
    border-radius: 10px;
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(201, 168, 76, 0.06);
    color: var(--primary-text);
    font-size: 0.76rem;
    line-height: 1.4;
    pointer-events: none;   /* click-through: never blocks the field beneath; buttons re-enable below */
    animation: app-coach-pop 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.3) both;
}
@keyframes app-coach-pop {
    from { opacity: 0; transform: translateY(-5px) scale(0.96); }
    to   { opacity: 1; transform: none; }
}
.app-coach__icon { color: var(--accent-color); font-size: 0.95rem; line-height: 1.25; flex-shrink: 0; }
.app-coach strong { color: var(--accent-color); font-weight: 700; }
.app-coach__body { flex: 1 1 auto; }
.app-coach__actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.app-coach__btn {
    border: 1px solid rgba(201, 168, 76, 0.45);
    background: rgba(201, 168, 76, 0.14);
    color: var(--accent-color);
    border-radius: 6px;
    padding: 0.22rem 0.6rem;
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    pointer-events: auto;   /* re-enable clicks on the buttons (coach body is click-through) */
    transition: background 0.15s ease, border-color 0.15s ease;
}
.app-coach__btn:hover { background: rgba(201, 168, 76, 0.26); border-color: rgba(201, 168, 76, 0.7); }
.app-coach__btn--ghost { background: transparent; color: var(--secondary-text); border-color: rgba(255, 255, 255, 0.14); }
.app-coach__btn--ghost:hover { color: var(--primary-text); background: rgba(255, 255, 255, 0.06); }

/* caret pointing back at the anchored field */
.app-coach::before {
    content: "";
    position: absolute;
    width: 11px;
    height: 11px;
    background: #16273f;
    border-left: 1px solid rgba(201, 168, 76, 0.5);
    border-top: 1px solid rgba(201, 168, 76, 0.5);
}
.app-coach[data-caret="top"]::before       { top: -6px; left: 20px; transform: rotate(45deg); }
.app-coach[data-caret="top-right"]::before { top: -6px; right: 20px; left: auto; transform: rotate(45deg); }

/* In-flow popup variant: docks inside the card (so it never overlaps the next
   field/card) while keeping the floating-popup look — caret, shadow, dark fill.
   position:relative keeps the caret anchored to the popup, not the card. */
.app-coach.is-pop {
    position: absolute;          /* overlay, OUT of flow — dismissing never reflows the form */
    top: auto;
    bottom: 0.6rem;
    left: 0.7rem;
    right: 0.7rem;
    margin: 0;
    max-width: none;
}
.app-coach.is-pop::before { display: none; }   /* overlay: caret not meaningful */

.app-coach.is-dismissed { display: none !important; }

/* Gate coachmarks (the kind that auto-hide once their field is filled —
   anything with data-coach-satisfied) stay hidden until JS confirms, AFTER the
   deal's saved state has loaded, that the field is genuinely empty. Without
   this a saved deal flashes the popup during the async state hydration: it
   renders visible, then hides ~400ms later once the data lands. The JS adds
   .is-revealed only against loaded, still-empty fields. */
.app-coach[data-coach-satisfied]:not(.is-revealed) { display: none; }

/* Inline variant: a normal-flow guidance strip (a standing call-to-action,
   e.g. the "upload your data" banner). Gold-tinted so it stays prominent —
   the dark fill above is for the transient floating field popups. */
.app-coach.is-inline {
    position: static;
    width: auto;
    max-width: none;
    margin: 0 0 0.45rem 0;
    padding: 0.4rem 0.7rem;
    align-items: center;
    background: linear-gradient(180deg, rgba(201, 168, 76, 0.17), rgba(201, 168, 76, 0.09));
    border-color: rgba(201, 168, 76, 0.6);
    box-shadow: 0 2px 10px rgba(201, 168, 76, 0.10);
    animation: app-coach-fade 0.3s ease both;
}
.app-coach.is-inline::before { display: none; }
.app-coach.is-inline .app-coach__btn { background: rgba(201, 168, 76, 0.22); }
.app-coach.is-inline .app-coach__btn:hover { background: rgba(201, 168, 76, 0.34); }
@keyframes app-coach-fade { from { opacity: 0; } to { opacity: 1; } }

/* ===== Property tab — photo + location media panels =====
   Fill the lower canvas of the property tab so the form doesn't strand a short
   block at the top. Photo reuses the existing /property_image upload+serve
   flow; the map is a keyless Google Maps embed keyed off city/state/address. */
.property-media-card { display: flex; flex-direction: column; min-height: 200px; }
.property-media-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 150px; }
.property-media__status { color: var(--secondary-text); margin-top: 0.4rem; min-height: 1em; }

.property-image-dropzone {
    flex: 1 1 auto; margin: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 0.45rem; text-align: center; cursor: pointer;
    padding: 1.75rem 1rem;
    border: 1.5px dashed rgba(201, 168, 76, 0.45);
    border-radius: 10px;
    background: rgba(201, 168, 76, 0.04);
    color: var(--secondary-text);
    transition: border-color 0.18s ease, background 0.18s ease, color 0.18s ease;
}
.property-image-dropzone:hover { border-color: var(--accent-color); background: rgba(201, 168, 76, 0.09); color: var(--primary-text); }
.property-image-dropzone.om-uploading { opacity: 0.55; pointer-events: none; }
/* Dropzone is a keyboard-focusable label (tabindex="0" + role="button" in
   property.html); no generic focus-ring rule covers labels, so give it the
   app's standard accent focus ring for keyboard users. */
.property-image-dropzone:focus-visible {
    outline: 2px solid var(--accent-color-light);
    outline-offset: 2px;
}
.property-dropzone__icon { font-size: 1.8rem; color: var(--accent-color); }
.property-dropzone__text { font-size: 0.83rem; }
.property-dropzone__text strong { color: var(--accent-color); }
.property-dropzone__hint { font-size: 0.66rem; letter-spacing: 0.05em; text-transform: uppercase; opacity: 0.65; }
.property-image-preview {
    flex: 1 1 auto; width: 100%; min-height: 180px;
    object-fit: cover; border-radius: 10px; border: 1px solid var(--border-color);
}

/* --- one consistent field + panel system across the whole property tab --- */
#tabpane-core .form-control,
#tabpane-core .form-select {
    background: rgba(255, 255, 255, 0.045);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 0.42rem 0.6rem;
    font-size: 0.8rem;
    color: var(--primary-text);
}
#tabpane-core .form-control::placeholder { color: var(--secondary-text); opacity: 0.6; }
#tabpane-core .form-control:focus,
#tabpane-core .form-select:focus {
    border-color: var(--accent-color);
    box-shadow: 0 0 0 2px rgba(201, 168, 76, 0.16);
    background: rgba(255, 255, 255, 0.06);
}
/* field labels (carry for=) share one tier; card titles (no for=) get the header tier + hairline */
#tabpane-core .form-label[for] { font-size: 0.76rem; font-weight: 600; margin-bottom: 0.25rem; }
#tabpane-core .form-label:not([for]) {
    display: flex; align-items: center; gap: 0.4rem; width: 100%;
    font-size: 0.92rem; font-weight: 700; color: var(--primary-text);
    padding-bottom: 0.5rem; margin-bottom: 0.7rem;
    border-bottom: 1px solid var(--border-color);
}

/* ========== LOAD-FAILURE BANNER ========== */
/* Blocking banner shown when the initial GET /state fails (dispatched as
   state:load-failed by deal_state.js, rendered by index_init.js). While it
   is up, DealState stays un-loaded so autosave cannot overwrite the server
   copy with blanks — the banner is the user's only path back (Retry). */
.app-load-error-banner {
    position: fixed;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: var(--z-toast);
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: min(560px, calc(100vw - 24px));
    padding: 10px 16px;
    background: var(--card-bg);
    border: 1px solid var(--danger-color);
    border-left: 4px solid var(--danger-color);
    border-radius: 8px;
    color: var(--primary-text);
    font-size: 0.85rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}

/* ========== DEAL COLLABORATION (presence / edit-lock / share) ========== */
/* All elements are created by static/js/collab.js on the first successful
   collab heartbeat (except #collabShareModal, in templates/index.html), so
   none of this renders on a backend without the collab API. Token colors
   only — flips with the theme. */

/* Presence avatar strip — lives in #reuw-nav-row before #nav-excel-status.
   Avatars overlap slightly (Figma-style); the lock holder wears a gold ring. */
.collab-presence {
    display: flex;
    align-items: center;
    flex-shrink: 0;
}
.collab-presence[hidden] { display: none; }
.collab-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    /* Ring gap against the nav bar so overlapped circles read as separate. */
    border: 2px solid var(--bg-primary);
    font-family: var(--font-ui);
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1;
    color: var(--primary-text);
    background: var(--bg-tertiary);
    user-select: none;
    cursor: default;
}
.collab-avatar + .collab-avatar { margin-left: -6px; }
/* Gold ring = current edit-lock holder. Box-shadow, not border, so the
   bg-primary separation ring is preserved underneath. */
.collab-avatar.is-holder {
    box-shadow: 0 0 0 2px var(--accent-color);
}
/* Deterministic small palette — collab.js hashes user_id onto c0…c5.
   Same color-mix-over-token approach as .badge-loan-*: tints track both
   themes (light pastels on light, deep tints on dark) with readable
   primary-text on top. */
.collab-avatar.collab-c0 { background: color-mix(in srgb, var(--info-color) 32%, var(--bg-tertiary)); }
.collab-avatar.collab-c1 { background: color-mix(in srgb, var(--success-color) 32%, var(--bg-tertiary)); }
.collab-avatar.collab-c2 { background: color-mix(in srgb, var(--warning-color) 32%, var(--bg-tertiary)); }
.collab-avatar.collab-c3 { background: color-mix(in srgb, var(--danger-color) 28%, var(--bg-tertiary)); }
.collab-avatar.collab-c4 { background: color-mix(in srgb, var(--accent-color) 32%, var(--bg-tertiary)); }
.collab-avatar.collab-c5 { background: color-mix(in srgb, var(--secondary-text) 32%, var(--bg-tertiary)); }
/* "+N" chip past 5 avatars — neutral, like .ndt-chip. */
.collab-avatar.collab-avatar-overflow {
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    color: var(--secondary-text);
    font-weight: 600;
}

/* Share button — 26px icon circle matching the avatar strip. */
.collab-share-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    flex-shrink: 0;
    border: 1px dashed var(--border-color);
    border-radius: 50%;
    background: transparent;
    color: var(--secondary-text);
    font-size: 0.75rem;
    line-height: 1;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.collab-share-btn:hover,
.collab-share-btn:focus-visible {
    color: var(--accent-text);
    border-color: color-mix(in srgb, var(--accent-color) 60%, var(--border-color));
}

/* NOTE (2026-07-07): a horizontal-scroll tab strip was tried here to keep the
   tabs on one row once the presence avatars were added, but it clipped the
   leftmost tabs behind the scrollbar with no way to reach them. Reverted — the
   original #existing-top-tabs rule (flex-wrap:wrap, centered) governs, so the
   tabs simply wrap to a second row (the app's pre-collab behavior); every tab
   stays reachable and the avatars just move the wrap point slightly. */

/* View-only banner — appended INSIDE #reuw-top-nav (last child) so the
   sticky nav carries it and index_init's --app-header-h measurement
   (nav offsetHeight) automatically accounts for its height; sticky table
   headers then clear it with no extra wiring. Info-tinted per the app's
   status language. */
/* Banner sits INLINE in the header row, between the deal name (flex:1 wrap)
   and the account block. display:contents lets the pill be the actual flex
   item; [hidden] still wins (display:none overrides contents), and because
   the pill lives on the existing line the nav height never jumps when it
   appears — no sticky-offset churn. */
.collab-banner { display: contents; }
.collab-banner[hidden] { display: none; }
/* Glass pill — translucent + blurred so the skyline reads through; can
   shrink (text ellipsises) but never pushes the account block off. */
.collab-banner-pill {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex: 0 1 auto;
    min-width: 0;
    max-width: min(44vw, 560px);
    padding: 0.22rem 0.28rem 0.22rem 1rem;
    background: color-mix(in srgb, var(--bg-secondary) 72%, transparent);
    -webkit-backdrop-filter: blur(8px);
            backdrop-filter: blur(8px);
    border: 1px solid color-mix(in srgb, var(--info-color) 45%, transparent);
    border-radius: 999px;
    color: var(--primary-text);
    font-size: 0.8rem;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
    position: relative;   /* above the z-index:0 skyline */
    z-index: 1;
}
.collab-banner-text {
    font-weight: 500;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Compact capsule button shaped to the pill's curvature — the default
   btn-sm rectangle poked past the rounded ends. */
.collab-banner-takeover {
    flex-shrink: 0;
    border-radius: 999px;
    padding: 0.16rem 0.8rem;
    font-size: 0.74rem;
    font-weight: 600;
    line-height: 1.25;
}
.collab-banner-takeover[hidden] { display: none; }

/* View-only mode: grey + inert the form controls inside the deal tabs.
   VISUAL affordance only — buttons/uploads stay clickable and the server's
   423 on write routes is the real enforcement. */
body.collab-readonly .tab-pane :is(input, select, textarea):not([type="file"]) {
    pointer-events: none;
    opacity: 0.6;
}

/* v1.1 live view — the field the lock HOLDER is focused in, as seen by
   viewers (advisory, beat-driven; applied/cleared by collab.js). Gold
   outline pulses ~2 cycles then holds steady; outline never affects layout,
   and collab.js never scrolls or focuses to it. Tokens → flips with theme. */
.collab-remote-field {
    outline: 2px solid color-mix(in srgb, var(--accent-color) 85%, transparent);
    outline-offset: 1px;
    animation: collab-remote-pulse 1.1s ease-in-out 2;
}
@keyframes collab-remote-pulse {
    0%, 100% { outline-color: color-mix(in srgb, var(--accent-color) 85%, transparent); }
    50%      { outline-color: color-mix(in srgb, var(--accent-color) 25%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    /* Steady outline only — no pulse. */
    .collab-remote-field { animation: none; }
}
/* The readonly dimming above (specificity 0-3-2) would fade the highlight
   with the rest of the pane; matching its specificity later in the file
   lifts just the remote-edited control — no !important needed. */
body.collab-readonly .tab-pane :is(input, select, textarea).collab-remote-field {
    opacity: 0.85;
}

/* v1.1 live view — transient "· synced just now" suffix on the view-only
   banner (~4s after a viewer-side refresh lands). Visual-only (collab.js
   marks it aria-hidden: the banner is aria-live, and re-announcing every
   sync would be screen-reader noise). */
.collab-banner-synced {
    color: var(--secondary-text);
    font-size: 0.78rem;
    font-weight: 400;
}
.collab-banner-synced[hidden] { display: none; }

/* Share modal internals (#collabShareModal — shell styling comes from the
   global .modal-content/.modal-header rules). */
.collab-share-list { min-height: 2rem; }
.collab-share-entry {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.15rem;
    border-bottom: 1px solid var(--border-secondary);
    font-size: 0.85rem;
}
.collab-share-entry:last-child { border-bottom: 0; }
.collab-share-email {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--primary-text);
}
.collab-share-owner {
    flex-shrink: 0;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-tertiary);
}
.collab-share-empty {
    padding: 0.45rem 0.15rem;
    color: var(--secondary-text);
    font-size: 0.82rem;
}
/* Access-level badge — same color-mix tint pattern as .badge-loan-*. */
.collab-level-badge {
    flex-shrink: 0;
    border-radius: 2rem;
    padding: 0.15rem 0.55rem;
    font-size: 0.66rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    line-height: 1.3;
}
.collab-level-read {
    background: color-mix(in srgb, var(--secondary-text) 14%, transparent);
    color: var(--secondary-text);
    border: 1px solid color-mix(in srgb, var(--secondary-text) 35%, transparent);
}
.collab-level-write {
    background: color-mix(in srgb, var(--info-color) 16%, transparent);
    color: var(--info-color);
    border: 1px solid color-mix(in srgb, var(--info-color) 40%, transparent);
}
.collab-level-admin {
    background: color-mix(in srgb, var(--accent-color) 16%, transparent);
    color: var(--accent-text);
    border: 1px solid color-mix(in srgb, var(--accent-color) 40%, transparent);
}
.collab-share-remove {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--secondary-text);
    font-size: 0.7rem;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.collab-share-remove:hover,
.collab-share-remove:focus-visible {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 45%, transparent);
}
/* Modal inputs — the createNewDealModal input styling is scoped to that
   modal (with literals), so the share modal gets its own token-based rules. */
.collab-share-input {
    display: block;
    background: var(--bg-primary);
    color: var(--primary-text);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 0.5rem 0.75rem;
    font-size: 0.88rem;
    outline: none;
    min-width: 0;
}
.collab-share-input:focus {
    border-color: var(--accent-color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-color) 25%, transparent);
}
select.collab-share-input {
    cursor: pointer;
    flex: 0 0 auto;
    width: auto;
}
.collab-share-input::placeholder { color: var(--text-tertiary); }
/* Same 3-tier z-lift as #createNewDealModal (the global .modal-backdrop.show
   sits at --z-modal-backdrop, above Bootstrap's default modal z of 1055).
   ID specificity beats Bootstrap's .modal rule, so no !important needed. */
#collabShareModal { z-index: var(--z-modal); }
#collabShareModal .modal-dialog { z-index: calc(var(--z-modal) + 1); }
#collabShareModal .modal-content { position: relative; z-index: calc(var(--z-modal) + 2); }

/* ========== CSP-SAFE HOVERS (2026-07-10) ==========
   The self-only CSP (script-src 'self' + nonce) blocks inline event handlers,
   so the old onmouseover/onmouseout style-swaps in dashboard.js (deal delete
   action) and property.js (datepicker day cells) are now CSS :hover rules. */
.deal-action-delete { background: transparent; }
.deal-action-delete:hover { background: rgba(231, 76, 60, 0.12); }

.ndt-dp-day { background: none; }
.ndt-dp-day.is-selected { background: rgba(201, 168, 76, 0.35); }
/* hover last: overrides is-selected while hovering (matches old JS behavior) */
.ndt-dp-day:hover { background: rgba(201, 168, 76, 0.2); }

/* ==========================================================================
   REUW BRAND SYSTEM (2026-07-13) — finalized brand assets wired into the
   chrome (static/images/brand/): frieze in the dashboard/home navs, tower on
   login + the deal-load splash.
   ========================================================================== */
/* Theme-variant swap: each placement ships a dark + light <img> pair
   (.brand-theme-dark / .brand-theme-light) and html[data-theme] — set
   pre-paint by partials/theme_head.html, default dark — picks one.
   !important so the swap beats the imgs' inline display:block. */
.brand-theme-light { display: none !important; }
:root[data-theme="light"] .brand-theme-light { display: block !important; }
:root[data-theme="light"] .brand-theme-dark { display: none !important; }

/* Deal editor shows NO brand: hide the deal shell's logo link while a deal is
   being edited (body.existing-deal-mode, set by index.html JS). display:none
   only — the element stays in the markup because the same shell serves
   dashboard mode. */
body.existing-deal-mode #reuw-top-nav .nav-dash-link,
body.existing-deal-mode #reuw-top-nav .reuw-wordmark { display: none; }

/* Deal editor keeps an exit: the brand link is hidden in existing-deal-mode
   (no logo in the editor), so a plain breadcrumb takes its place. */
.nav-back-deals { display: none; }
body.existing-deal-mode #reuw-top-nav .nav-back-deals {
    display: inline-flex;
    align-items: center;
    min-height: 40px;   /* consistent 40px control height across the row */
    color: var(--secondary-text);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 600;
    padding: 0 0.6rem;
    border-radius: 0.5rem;
    flex-shrink: 0;
    transition: color 0.15s ease, background 0.15s ease;
}
body.existing-deal-mode #reuw-top-nav .nav-back-deals:hover {
    color: var(--primary-text);
    background: color-mix(in srgb, var(--accent-color) 8%, transparent);
}

/* ===== Deal-shell nav cleanup (Carson 2026-07-13): the skyline artwork fought
   the tabs and controls — hard to read, especially light mode. The deal editor
   gets a CALM flat bar; the skyline stays on surfaces where it can breathe
   (dashboard hero). One visual idea per surface. */
body.existing-deal-mode #reuw-top-nav .nav-skyline { display: none; }
body.existing-deal-mode #reuw-top-nav {
    background: var(--bg-primary);
    border-bottom: 1px solid var(--border-color);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}
html[data-theme="light"] body.existing-deal-mode #reuw-top-nav {
    background: #ffffff;
    box-shadow: 0 1px 4px rgba(16, 31, 56, 0.08);
}
/* One tidy 52px control line — the row's base layout (flex, wrap, 0.75rem
   column gap, 0.35rem 1rem padding, min-height 52px) lives on the
   #reuw-nav-row base rule near the tab-bar section; the rules below give the
   individual controls a consistent 40px height, all vertically centered. */

/* Left: brand link (dashboard mode only — existing-deal-mode hides it above). */
#reuw-nav-row .nav-dash-link {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    text-decoration: none;
    padding: 0.15rem 0.5rem;
    border-radius: 0.5rem;
    transition: background 0.15s ease;
}

/* Right: account email + settings gear behind a hairline divider. */
#reuw-nav-row .nav-account {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-left: auto;   /* belt & suspenders — the deal-name wrap is the spacer */
    flex-shrink: 0;
    height: 40px;
    padding-left: 0.85rem;
    border-left: 1px solid var(--border-color);
}
#reuw-nav-row .account-email {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--secondary-text);
    white-space: nowrap;
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
}
#reuw-nav-row .nav-settings-gear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--secondary-text);
    text-decoration: none;
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
#reuw-nav-row .nav-settings-gear:hover,
#reuw-nav-row .nav-settings-gear:focus-visible {
    color: var(--accent-text);
    border-color: color-mix(in srgb, var(--accent-color) 60%, var(--border-color));
    background: color-mix(in srgb, var(--accent-color) 8%, transparent);
}

/* Tab strip flush on the bar's bottom rail: the base rule's -0.5rem matched
   the row's old 0.5rem inline bottom padding; the flat bar pads 0.35rem, so
   re-match here or the folders overhang the border. Row-gap is 0 (base rule),
   so the strip's own padding-top is its only separation from the controls. */
body.existing-deal-mode #existing-top-tabs {
    padding-top: 0.35rem;
    margin-bottom: -0.35rem;
}

/* (Removed 2026-07-13) .prf-warn-close — the proforma opex-understated advisory
   was retired; the T-12 red "uncategorized" highlight is now the sole in-app cue. */

/* ========== PROPERTY TAB DENSITY (Carson 2026-07-14) ==========
   Fit every input at 100% zoom with no scroll. CSS-ONLY — no markup or
   data-state binding changes. !important here fights Bootstrap's p-3 / mb-2 /
   gap-2 utility !important (the sanctioned exception), scoped to #tabpane-core
   so no other tab is affected. */
#tabpane-core .card { padding: 0.6rem 0.8rem !important; }
#tabpane-core .form-label {
    margin-bottom: 0.1rem;
    font-size: 0.72rem;
    line-height: 1.15;
    font-weight: 600;
}
#tabpane-core .row.mb-2 { margin-bottom: 0.35rem !important; }
#tabpane-core .row.g-2 { --bs-gutter-y: 0.35rem; }
#tabpane-core .d-flex.flex-column.gap-2 { gap: 0.5rem !important; }
#tabpane-core .form-control-sm,
#tabpane-core .form-select-sm {
    padding-top: 0.22rem;
    padding-bottom: 0.22rem;
    min-height: 0;
    font-size: 0.82rem;
}
#tabpane-core > .d-flex.justify-content-end.mb-2 { margin-bottom: 0.2rem !important; }
#tabpane-core .app-req-legend { font-size: 0.62rem; }
/* the media/photo card can shrink to match the tightened right column */
#tabpane-core .property-media-card { padding: 0.6rem 0.8rem !important; }
#tabpane-core .property-image-dropzone { min-height: 120px; }
/* the OM-upload button sits tight under the last field */
#tabpane-core .card .mt-2 { margin-top: 0.4rem !important; }

/* ==========================================================================
   DEALS DASHBOARD — PREMIUM PASS (2026-07-28)
   The authenticated daily-driver deals list, brought up to the landing page's
   design language (static/css/homepage.css): the 3-layer shadow +
   top-edge-lit hairline depth recipe, gold accent discipline (edges / lines /
   numbers / status only), Fraunces display for the page voice with Inter for
   all UI, and the one-shot 0.6s cubic-bezier(0.22,1,0.36,1) entrance idiom.

   SUPERSEDES (removed above, 2026-07-28): the old #deals-dashboard .table
   rules, .deal-status-badge/.deal-type-badge/.status-*/.type-* chips, the
   relocated .deals-history-section / #deals-table / #open-full-new-deal-btn /
   search+filter blocks, their light-mode overrides, and the dashboard rows of
   the 768px media block.

   Rules are scoped to #deals-dashboard / dashboard-specific ids so no other
   page is touched. Token-driven only (color-mix over literals) so dark AND
   light themes both read correctly. All motion lives at the bottom behind
   html.reuw-anim (set by dashboard.js only when motion is allowed) +
   prefers-reduced-motion; the base state is always fully visible.
   ========================================================================== */

#deals-dashboard {
    /* Display serif for the page voice — Fraunces ships app-wide via the
       vendored fonts.css in theme_head.html. */
    --font-display: 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
    /* Ink used ON gold fills. Deliberately theme-invariant: the gold accent is
       the same hue in both themes, so the contrast ink must stay dark navy —
       a theme-flipped token would go light-on-gold in light mode. */
    --dash-on-accent-ink: #0a1628;
    font-family: var(--font-ui);
}

/* ---- Content column: centered, homepage-scale width, generous gutters ---- */
.reuw-dash-main {
    max-width: min(96vw, 1560px);
    margin: 0 auto;
    padding: 2.25rem 3rem 3rem;
}

/* ---- Nav account cluster (dashboard bar) — mirrors the deal-shell
   #reuw-nav-row treatment so the two bars read as one component. The inline
   styles moved here from the partial so :hover can actually restyle them. ---- */
.reuw-dash-navrow .nav-account {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding-right: 0.9rem;
    margin-right: 0.35rem;
    border-right: 1px solid var(--border-color);
}
.reuw-dash-navrow .account-email {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--secondary-text);
    white-space: nowrap;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.reuw-dash-navrow .nav-settings-gear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--secondary-text);
    text-decoration: none;
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.reuw-dash-navrow .nav-settings-gear:hover,
.reuw-dash-navrow .nav-settings-gear:focus-visible {
    color: var(--accent-text);
    border-color: color-mix(in srgb, var(--accent-color) 60%, var(--border-color));
    background: color-mix(in srgb, var(--accent-color) 8%, transparent);
}

/* ---- Primary gold CTA — nav "New Deal" + the empty-state twin. Same recipe
   as the homepage .home-btn--primary: gold fill, navy ink, lift + lighter
   gold + glow on hover. ---- */
#open-full-new-deal-btn,
.dash-gold-cta {
    background: var(--accent-color);
    color: var(--dash-on-accent-ink);
    border: 1px solid var(--accent-color);
    border-radius: 6px;
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 0.82rem;
    letter-spacing: 0.01em;
    box-shadow: 0 2px 8px rgba(201, 168, 76, 0.25);
    transition: all 0.15s ease;
}
#open-full-new-deal-btn:hover,
#open-full-new-deal-btn:focus-visible,
.dash-gold-cta:hover,
.dash-gold-cta:focus-visible {
    transform: translateY(-1px);
    background: var(--accent-color-light);
    border-color: var(--accent-color-light);
    color: var(--dash-on-accent-ink);
    box-shadow: 0 4px 16px rgba(201, 168, 76, 0.35);
}

/* ---- Section header: Fraunces title + gold count chip + quiet refresh ---- */
.dash-title {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.45rem;
    font-weight: 500;
    letter-spacing: -0.015em;
    line-height: 1.15;
}
#deals-count {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.72rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--accent-text);
    background: var(--accent-subtle);
    border: 1px solid color-mix(in srgb, var(--accent-color) 40%, transparent);
    border-radius: 999px;
    padding: 0.28rem 0.7rem;
    white-space: nowrap;
}
#refresh-deals-btn {
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 0.78rem;
    font-weight: 500;
    padding: 0.35rem 0.75rem;
    background: transparent;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
#refresh-deals-btn:hover,
#refresh-deals-btn:focus-visible {
    border-color: color-mix(in srgb, var(--accent-color) 50%, var(--border-color));
    background: color-mix(in srgb, var(--accent-color) 6%, transparent);
}

/* ---- Search + filter toolbar — app-input idiom. The !important mechanics of
   the superseded rules are preserved: Bootstrap's .form-control/.form-select
   (and this file's global white form-select override) would otherwise force
   white fields onto the dark panel. color-mix over --primary-text keeps the
   tint correct in BOTH themes (soft white-alpha on dark, soft ink on light). ---- */
#deals-dashboard .input-group.app-panel-tinted {
    background: color-mix(in srgb, var(--primary-text) 4%, transparent);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
#deals-dashboard .input-group.app-panel-tinted:focus-within {
    border-color: color-mix(in srgb, var(--accent-color) 55%, var(--border-color));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-color) 15%, transparent);
}
#deals-dashboard .input-group .input-group-text {
    background: transparent;
    border: none;
    padding-left: 0.85rem;
}
#deals-search {
    background: transparent !important;
    border: none;
    font-size: 0.875rem;
    padding: 0.6rem 0.75rem;
    color: var(--primary-text) !important;
}
#deals-search::placeholder { color: var(--secondary-text); }
/* Quiet on mouse focus, but never invisible for keyboard users. The id
   selector already outranks Bootstrap's non-!important focus reset. */
#deals-search:focus { box-shadow: none !important; }
#deals-search:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: -2px;
}
#deals-filter.app-panel-tinted {
    /* Opaque (native select) — mixed over card-bg so it matches the search
       field's tint on the same panel surface. background-COLOR (not the
       shorthand) so Bootstrap's .form-select chevron background-image
       survives — the reserved 2.25rem right padding is for that arrow. */
    background-color: color-mix(in srgb, var(--primary-text) 4%, var(--card-bg)) !important;
    color: var(--primary-text) !important;
    border: 1px solid var(--border-color) !important;
    border-radius: 8px;
    font-size: 0.875rem;
    padding: 0.6rem 2.25rem 0.6rem 0.75rem;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
#deals-filter.app-panel-tinted:focus {
    border-color: color-mix(in srgb, var(--accent-color) 55%, var(--border-color)) !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-color) 15%, transparent) !important;
}
#deals-filter option { background: var(--card-bg); color: var(--primary-text); }

/* ---- The deals panel — homepage depth recipe (3-layer shadow + top-edge-lit
   hairline + inset top light), adapted for a working surface: no hover lift
   on the panel itself; the ROWS carry the hover response instead. ---- */
.deals-history-section {
    position: relative;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-top-color: rgba(255, 255, 255, 0.10);
    border-radius: 12px;
    padding: 1.6rem 1.6rem 1.35rem;
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.40),
        0 6px 16px rgba(0, 0, 0, 0.30),
        0 18px 44px rgba(0, 0, 0, 0.24),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

/* ---- Deals table — dense, institutional. Gold appears only as the header
   hairline, the row-hover rim, and status/number accents. ---- */
#deals-table {
    border-collapse: separate;
    border-spacing: 0;
}
#deals-table thead th {
    position: sticky;          /* stays put inside the 72vh scroll container */
    top: 0;
    z-index: 3;
    background: color-mix(in srgb, var(--card-bg) 82%, var(--bg-primary));
    color: var(--secondary-text);
    font-family: var(--font-ui);
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    border: none;
    border-bottom: 1px solid color-mix(in srgb, var(--accent-color) 35%, var(--border-color));  /* the one gold line */
    padding: 0.7rem 1rem;
    white-space: nowrap;
}
/* Neutralize Bootstrap's .table paint machinery on this table: BS paints every
   cell with `box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg)` ON TOP
   of background-color, so a background-only hover wash gets swallowed on any
   cell where that layer is non-transparent — hover read as patchy/broken. Zero
   the variables AND the shadow layer, then paint hover as an OPAQUE mix over
   card-bg (no compositing surprises, clearly visible in both themes). */
#deals-table,
#deals-table tbody tr {
    --bs-table-bg: transparent;
    --bs-table-accent-bg: transparent;
    --bs-table-striped-bg: transparent;
    --bs-table-hover-bg: transparent;
    --bs-table-active-bg: transparent;
}
#deals-table tbody td {
    background: transparent;
    box-shadow: none;          /* kills the 9999px BS accent layer */
    color: var(--primary-text);
    border: none;
    border-bottom: 1px solid var(--border-secondary);
    padding: 0.78rem 1rem;
    vertical-align: middle;
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
    transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
#deals-table tbody tr:last-child td { border-bottom: none; }
#deals-table tbody tr:hover td {
    background-color: color-mix(in srgb, var(--accent-color) 8%, var(--card-bg));
}
/* Gold rim on the hovered row's leading edge (inset shadow on the first cell —
   box-shadow does not paint on <tr> in Chromium). */
#deals-table tbody tr:hover td:first-child {
    box-shadow: inset 2px 0 0 var(--accent-color);
}

/* Deal name — the row's anchor. Inter semibold (Fraunces reads fussy at table
   density); color + gold hover come from the existing .deal-full-link rules. */
#deals-table .deal-full-link {
    font-weight: 600;
    font-size: 0.92rem;
    letter-spacing: -0.005em;
}
/* Quick-view eye — quiet until hovered. */
#deals-table .js-open-deal {
    color: var(--secondary-text);
    border: none;
    transition: color 0.15s ease;
}
#deals-table .js-open-deal:hover,
#deals-table .js-open-deal:focus-visible { color: var(--accent-text); }
/* 3-dot actions — matches (text-muted's !important needs matching). */
#deals-table .deal-actions-btn:hover,
#deals-table .deal-actions-btn:focus-visible { color: var(--accent-text) !important; }
/* Actions dropdown had no background at all (inline styles only set layout). */
.deal-actions-dropdown {
    background: var(--card-bg);
    border: 1px solid var(--border-color);
}
.deal-action-delete { color: var(--danger-color); font-weight: 500; }

/* ---- Status / type chips — homepage .dash-card__status idiom: small caps,
   999px pill, 1px tinted border. Gold = in-progress underwriting; green =
   complete package; deal-type is a quiet neutral outline (gold discipline). ---- */
.deal-status-badge,
.deal-type-badge {
    display: inline-block;
    padding: 0.22rem 0.6rem;
    border-radius: 999px;
    font-family: var(--font-ui);
    font-size: 0.64rem;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    line-height: 1.2;
    white-space: nowrap;
    border: 1px solid var(--border-color);
    color: var(--secondary-text);
    background: transparent;
}
.deal-status-badge.status-complete {
    color: var(--success-color);
    background: color-mix(in srgb, var(--success-color) 12%, transparent);
    border-color: color-mix(in srgb, var(--success-color) 35%, transparent);
}
.deal-status-badge.status-partial {
    color: var(--accent-text);
    background: var(--accent-subtle);
    border-color: color-mix(in srgb, var(--accent-color) 40%, transparent);
}
/* .type-custom / .type-standard intentionally share the quiet neutral base. */

/* ---- Bid countdown — live numbers, so: mono + tabular, urgency via token
   color only. (These spans' classNames are rewritten every second by
   dashboard.js — style strictly through these classes.) ---- */
.bid-countdown-badge {
    display: inline-block;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.2;
    padding: 0.2rem 0.5rem;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    color: var(--secondary-text);
    background: transparent;
    white-space: nowrap;
}
.bid-countdown-badge.bid-warning {
    color: var(--accent-text);
    border-color: color-mix(in srgb, var(--accent-color) 40%, transparent);
    background: color-mix(in srgb, var(--accent-color) 10%, transparent);
}
.bid-countdown-badge.bid-urgent {
    color: var(--warning-color);
    border-color: color-mix(in srgb, var(--warning-color) 40%, transparent);
    background: color-mix(in srgb, var(--warning-color) 10%, transparent);
}
.bid-countdown-badge.bid-critical {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 40%, transparent);
    background: color-mix(in srgb, var(--danger-color) 10%, transparent);
}
.bid-countdown-badge.bid-expired {
    color: var(--text-tertiary);
    border-color: var(--border-secondary);
}

/* ---- Loading / empty / error states — quiet, well-typeset, shared shell ---- */
.dash-state { padding: 3.25rem 1rem 3rem; text-align: center; }
.dash-state__icon {
    width: 56px;
    height: 56px;
    margin: 0 auto 1.1rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid color-mix(in srgb, var(--accent-color) 35%, var(--border-color));
    background: color-mix(in srgb, var(--accent-color) 6%, transparent);
    color: var(--accent-text);
    font-size: 1.35rem;
}
.dash-state__title {
    font-family: var(--font-display);
    font-size: 1.15rem;
    font-weight: 500;
    color: var(--primary-text);
    margin: 0 0 0.4rem;
    letter-spacing: -0.01em;
}
.dash-state__text {
    color: var(--secondary-text);
    font-size: 0.875rem;
    line-height: 1.6;
    margin: 0 auto;
    max-width: 44ch;
}
.dash-state__actions { margin-top: 1.35rem; }

/* Loading skeleton — ghost table rows, fully visible at rest; the shimmer
   sweep only runs under the motion gate at the bottom of this block. */
.dash-skel {
    display: grid;
    gap: 0.6rem;
    max-width: 760px;
    margin: 0 auto 1.25rem;
    text-align: initial;
}
.dash-skel__row {
    display: grid;
    grid-template-columns: 2.2fr 1fr 0.6fr 1fr 0.8fr;
    gap: 1rem;
    align-items: center;
    padding: 0.85rem 1rem;
    background: color-mix(in srgb, var(--primary-text) 3%, transparent);
    border: 1px solid var(--border-secondary);
    border-radius: 8px;
}
.dash-skel__bar {
    position: relative;
    height: 10px;
    border-radius: 5px;
    overflow: hidden;
    background: color-mix(in srgb, var(--primary-text) 9%, transparent);
}

/* ---- Mobile density (replaces the superseded 768px dashboard rules; the
   older !important padding overrides further up still agree with these) ---- */
@media (max-width: 768px) {
    .reuw-dash-main { padding-top: 1.25rem; padding-bottom: 2rem; }
    .deals-history-section { padding: 1rem; }
    #deals-table thead th,
    #deals-table tbody td { padding: 0.6rem 0.5rem; }
    .reuw-dash-navrow .account-email { display: none; }   /* icon-only account on phones */
}

/* ==========================================================================
   Dashboard MOTION — one-shot entrance, homepage idiom (0.6s
   cubic-bezier(0.22,1,0.36,1)). Everything sits behind html.reuw-anim —
   added by dashboard.js ONLY when the dashboard exists and
   prefers-reduced-motion is not set — plus the media query, so the base
   state above is never hidden for no-JS / reduced-motion users. The shell
   elements animate via `animation ... both` (hidden state exists only while
   the gate class is present); table rows get .dash-row-enter + a JS-set
   --dash-row-delay on the FIRST render only, so search/filter/delete
   re-renders never replay the cascade. Rows animate opacity ONLY (transforms
   on <tr> are unreliable across engines); the rise lives on the panel.
   ========================================================================== */
@keyframes dash-rise-in {
    from { opacity: 0; translate: 0 14px; }
    to   { opacity: 1; translate: 0 0; }
}
@keyframes dash-row-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes dash-shimmer {
    from { transform: translateX(-100%); }
    to   { transform: translateX(100%); }
}
@media (prefers-reduced-motion: no-preference) {
    html.reuw-anim #deals-dashboard .dash-fade {
        animation: dash-rise-in 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
        animation-delay: var(--dash-delay, 0s);
    }
    html.reuw-anim #deals-table tbody tr.dash-row-enter {
        animation: dash-row-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
        animation-delay: var(--dash-row-delay, 0s);
    }
    /* Loading-progress shimmer (transient feedback, not decoration; it exists
       only while the skeleton panel is shown and never under reduced motion). */
    html.reuw-anim .dash-skel__bar::after {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(90deg,
            transparent,
            color-mix(in srgb, var(--accent-color) 18%, transparent),
            transparent);
        transform: translateX(-100%);
        animation: dash-shimmer 1.6s ease-in-out infinite;
    }
}

/* ==========================================================================
   Dashboard LIGHT THEME — mirrors the homepage's light overrides: ink-tinted
   shadows, no white inset edge, hairline top border instead of the lit edge.
   Everything else above is color-mix/token-driven and re-themes itself.
   ========================================================================== */
:root[data-theme="light"] .deals-history-section {
    border-top-color: var(--border-color);
    box-shadow:
        0 1px 2px rgba(16, 31, 56, 0.06),
        0 4px 12px rgba(16, 31, 56, 0.07),
        0 14px 32px rgba(16, 31, 56, 0.06);
}
:root[data-theme="light"] #open-full-new-deal-btn,
:root[data-theme="light"] .dash-gold-cta {
    box-shadow: 0 2px 8px rgba(184, 146, 62, 0.30);
}
:root[data-theme="light"] .deal-status-badge.status-partial {
    /* --accent-subtle is a strong cream in light mode; thin it for a chip. */
    background: color-mix(in srgb, var(--accent-color) 12%, transparent);
}
