/* ===== Design tokens =====
   Two hairline weights, from docs/design/DESIGN.md. `--hairline` is passive
   structure (card borders, row separators) — it organizes without asserting.
   `--hairline-strong` is for edges competing with something active (inputs,
   buttons, totals rows). If a new border needs a third value, that's a signal
   to revisit the system in DESIGN.md, not to reach for another gray — the
   running CSS already drifted to 8+ near-identical grays once before this
   existed. New borders should reference these variables, not hardcode a hex. */
:root {
    --hairline: #E6E9EF;
    --hairline-strong: #CFD5E0;

    /* Surface + text, from DESIGN.md — card-sunken is for wells inside a
       card (grid headers, read-only cells); card-hover is row hover, not a
       button state. mute/action-soft are read here for grid affordances. */
    /* Surfaces. The page is the gray field and cards are white on top of it —
       this was inverted (white page, #F9FAFB cards), which made every card
       read as inset and left the segmented-control tracks invisible against
       the card they sat on. Sunken elements *inside* a card stay gray and
       became correct for free once the two outer layers swapped. */
    --canvas: #F7F8FA;
    --card: #FFFFFF;
    --card-sunken: #F1F3F7;
    --card-hover: #FBFCFE;

    /* Stronger than DESIGN.md's `raised` (0 1px 2px rgba(12,35,64,.04)),
       which was invisible against the canvas. DESIGN.md needs revising to
       match rather than this being special-cased. */
    --raised: 0 1px 3px rgba(12, 35, 64, 0.06);
    --ink: #0C2340;
    --mute: #8A94A6;

    /* Action is indigo — see DESIGN.md. Chosen over a navy-adjacent blue that
       didn't separate from brand-navy, and over teal, which collides with
       success green. Teal survives only as the timeline's range fill, where
       it is never adjacent to a semantic chip. */
    --action: #4F46E5;
    --action-hover: #4338CA;
    --action-soft: #EEF2FF;

    /* Semantic — flat vs. -soft/-deep is a judgment call (see DESIGN.md
       Semantic section), not a fixed rule: flat text for a dense column of
       values read as a set (Biggest Movers), -soft/-deep chip for a single
       standalone status word. warning-soft runs hot — reserve for rare,
       genuinely serious cases; routine callouts stay neutral gray with
       warning-colored text. */
    --success: #16A34A;
    --success-soft: #F0FDF4;
    --success-deep: #15803D;
    --danger: #DC2626;
    --danger-soft: #FEF2F2;
    --danger-deep: #B91C1C;
    --warning: #D97706;
    --warning-soft: #FFF7ED;
    --warning-deep: #B45309;
}

/* ===== Brand fonts =====
   Self-hosted, SIL OFL — free for commercial use, no attribution required in
   the running app. D-DIN is a signage/instrument face: reserved for headline
   figures and page titles only (see .expenses-page rules below), never for
   anything that stacks in a column — it has no tabular-numeral variant, so a
   money column set in it saws left-right. Geist covers everything else and
   carries real tabular numerals via `font-variant-numeric: tabular-nums`. */
@font-face {
    font-family: "D-DIN";
    src: url("fonts/D-DIN.woff2") format("woff2");
    font-weight: 400;
    font-display: swap;
}
@font-face {
    font-family: "D-DIN";
    src: url("fonts/D-DIN-Bold.woff2") format("woff2");
    font-weight: 700;
    font-display: swap;
}
@font-face {
    font-family: "Geist";
    src: url("fonts/Geist[wght].ttf") format("truetype-variations");
    font-weight: 100 900;
    font-display: swap;
}

/* ===== Global Reset ===== */
* {
    box-sizing: border-box;
}

body {
    margin: 0;
    padding: 0;
    font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        sans-serif;
    background-color: var(--canvas);
}

/* ===== Expenses page — typography pilot =====
   Scoped to .expenses-page only, per the design-system rollout plan: approve
   a component here before it spreads to the rest of the app. */
.expenses-page {
    font-family: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        sans-serif;
}

.expenses-page h2,
.expenses-page .thermo-metric,
.expenses-page .kpi-card-value {
    font-family: "D-DIN", "Geist", sans-serif;
}

/* Stat-card type scale — matched to the thermometer card.
   These need the .expenses-page prefix to win: `.page-container h4` (0,1,1) and
   `.page-container p` (0,1,1) out-specify the bare `.kpi-card-value` (0,1,0) and
   `.kpi-card-subtitle` (0,1,0) further down this file, so the card's own sizes
   were never actually applying — the value rendered at 1.1rem instead of 1.25rem
   and the subtitle at 0.95rem instead of 0.68rem, which is why a subtitle could
   out-shout the label above it. */
.expenses-page .kpi-card-value {
    font-size: 1.9rem;
    font-weight: 700;
    line-height: 2.05rem;
    letter-spacing: -0.4px;
    color: #101828;
    margin-bottom: 0;
}

/* _kpi_label_row() hard-codes minHeight: 3.4rem inline while .thermo-head is
   1.9rem — a 24px difference that pushed every stat-card figure below its
   neighbouring thermometer figure. Overridden here rather than fixed in
   components/kpi_card.py because that component is shared with the other pages,
   which are not part of this pilot. !important is required to beat the inline
   style. Fold this into the component when the rollout goes site-wide. */
.expenses-page .kpi-card-label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.6px;
    color: #8a94a6;
    min-height: 1.9rem !important;
}

.expenses-page .kpi-card-subtitle {
    font-size: 0.78rem;
    font-weight: 500;
    color: #8a94a6;
    margin-top: 3px;
}

/* AG Grid v33 sets its font on .ag-root-wrapper from --ag-font-family, so a
   font-family on .ag-theme-alpine is inherited-over by the grid's own rule.
   Setting the variable is the supported override. */
.expenses-page .ag-theme-alpine {
    --ag-font-family: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI",
        Roboto, sans-serif;
    font-family: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        sans-serif;
}
.expenses-page .ag-theme-alpine .ag-cell {
    font-variant-numeric: tabular-nums;
}

/* ===== Timeline range slicer =====
   Replaces the Lookback + Forecast pill rows. One axis, Today fixed in the
   middle, a teal band spanning the selected range so the *span* is legible
   before any label is read. Stops whose window exceeds the holding period are
   omitted server-side, so the axis ends where the history does.

   The bar's lift is deliberately stronger than the `raised` elevation token
   (0 1px 2px rgba(12,35,64,.04)) — against the #F7F8FA canvas that token was
   invisible. See docs/design/rollout-plan.md; the token needs revising rather
   than this rule being special-cased. */
.expenses-page .tl-wrap {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
.expenses-page .tl-bar {
    display: inline-flex;
    align-items: stretch;
    background: #ffffff;
    border: 1px solid var(--hairline);
    border-radius: 6px;
    padding: 4px;
    box-shadow: var(--raised);
}
.expenses-page .tl-stop {
    padding: 9px 15px;
    font-size: 0.78rem;
    color: var(--mute);
    white-space: nowrap;
    display: flex;
    align-items: center;
    cursor: pointer;
    user-select: none;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.expenses-page .tl-stop:hover {
    color: var(--ink);
}
.expenses-page .tl-mid {
    background: #ccfbf1;
    color: #0f766e;
}
.expenses-page .tl-end {
    background: #0d9488;
    color: #ffffff;
    font-weight: 600;
    border-radius: 6px;
}
.expenses-page .tl-now {
    font-weight: 600;
}
/* The two anchors are matched in width rather than sized to their text, so the
   axis reads symmetrical even though "Purchase" and "Payoff" differ by two
   characters. */
.expenses-page .tl-stop:first-child,
.expenses-page .tl-stop:last-child {
    min-width: 104px;
    justify-content: center;
}
.expenses-page .tl-stop.tl-now:not(.tl-mid):not(.tl-end) {
    color: var(--ink);
}
.expenses-page .tl-range {
    font-size: 0.78rem;
    color: var(--ink);
    white-space: nowrap;
}
.expenses-page .tl-sep {
    width: 1px;
    height: 16px;
    background: var(--hairline);
}
.expenses-page .tl-span {
    font-size: 0.78rem;
    color: var(--mute);
    white-space: nowrap;
}

/* ===== Category tabs =====
   Underline tabs, not pills. Unselected tabs carry no border and no fill —
   that is the whole point: seven bordered boxes above the content read as a
   grid of controls, plain text does not. Hue identity lives in the selected
   tab's underline and text. */
.expenses-page .cat-tabs {
    display: flex;
    gap: 2px;
    border-bottom: 1px solid var(--hairline);
    /* Defaults; the category callback overrides these inline per selection. */
    --cat-ink: #0C2340;
    --cat-hue: #0C2340;
}
.expenses-page .cat-tabs label {
    padding: 9px 14px;
    font-size: 0.82rem;
    color: var(--mute);
    cursor: pointer;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin: 0 !important;
}
.expenses-page .cat-tabs label:not(.selected):hover {
    color: var(--ink) !important;
}

/* Hue identity — the selected tab's underline and text carry the category's
   own color, so the tab row teaches the chart legend without a legend. The
   hue arrives as a CSS variable set on the container by a callback, rather
   than seven :has(input[value=...]) rules: Dash's own .dash-options-list-option
   rule wins the `color` property against those, and .selected is the class
   Dash already puts on the chosen label. "All" keeps navy — it isn't a
   category and isn't in the legend. */
.expenses-page .cat-tabs label.selected {
    color: var(--cat-ink) !important;
    font-weight: 600;
    border-bottom-color: var(--cat-hue);
}

/* ===== Panel header =====
   Chart title with the controls that scope it sitting to the right. */
.expenses-page .panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.expenses-page .panel-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--ink);
}
.expenses-page .panel-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}
.expenses-page .seg-label {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mute);
    white-space: nowrap;
    margin-right: 2px;
}
.expenses-page .seg-label + .seg-toggle {
    margin-right: 6px;
}
/* The one segmented control. Every mutually-exclusive view switch on this
   page uses it — $/%, CapEx, View, the reserve period, the calendar's Order
   and Color, and Catch-All's mode — replacing five separate implementations
   that each invented their own selected state (teal, near-black, dark slate,
   indigo). Selected is a raised white pill with ink text, never a color:
   a chosen segment is a *state*, and color here would collide with `action`
   (which means "do something") and with the semantic greens and reds.

   Matches both markups: RadioItems render <label> and mark the chosen one
   `.selected`; the calendar's custom control renders <button> and marks it
   `.active`. Inputs are hidden here rather than per call site. */
.expenses-page .seg-toggle {
    display: inline-flex;
    align-items: stretch;
    background: var(--card-sunken);
    border-radius: 6px;
    padding: 3px;
    gap: 2px;
}
.expenses-page .seg-toggle input {
    display: none;
}
.expenses-page .seg-toggle label,
.expenses-page .seg-toggle button {
    padding: 4px 11px;
    font: inherit;
    font-size: 0.72rem;
    /* Weight is fixed across states on purpose: bolding the selected option
       widens its text and shoves the rest of the row sideways, which was very
       visible on the calendar's long "Chronological". The raised white pill
       already carries selection without it. */
    font-weight: 500;
    line-height: 1.5;
    color: var(--mute);
    background: transparent;
    border: 0;
    cursor: pointer;
    white-space: nowrap;
    border-radius: 4px;
    margin: 0 !important;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.expenses-page .seg-toggle label:hover,
.expenses-page .seg-toggle button:hover {
    color: var(--ink);
}
.expenses-page .seg-toggle label.selected,
.expenses-page .seg-toggle button.active,
.expenses-page .seg-toggle .form-check-input:checked + .form-check-label {
    background: var(--card);
    color: var(--ink);
    box-shadow: 0 1px 2px rgba(12, 35, 64, 0.12);
}

/* dbc.RadioItems wraps each option in a .form-check with its own padding and
   inline margin, which would break the track's flex row. dcc.RadioItems and
   the calendar's buttons need none of this. */
.expenses-page .seg-toggle .form-check {
    display: flex;
    padding: 0;
    margin: 0 !important;
    min-height: 0;
}

/* Sized down to sit inside a card header alongside a card title. */
.expenses-page .seg-toggle-sm label,
.expenses-page .seg-toggle-sm button {
    padding: 2px 9px;
    font-size: 0.68rem;
}

/* Catch-All's Simple/Bank switches the whole panel's method rather than one
   card's presentation, so it gets equal-width halves and room to breathe. */
.expenses-page .seg-toggle-wide {
    width: 340px;
    padding: 4px;
    gap: 3px;
}
/* The flex child is the .form-check wrapper under dbc, and the label itself
   under dcc — so both have to stretch or the halves come out uneven. */
.expenses-page .seg-toggle-wide .form-check,
.expenses-page .seg-toggle-wide > label,
.expenses-page .seg-toggle-wide > button {
    flex: 1;
}
.expenses-page .seg-toggle-wide label,
.expenses-page .seg-toggle-wide button {
    flex: 1;
    justify-content: center;
    text-align: center;
    padding: 9px 0;
    font-size: 0.82rem;
}

/* HOA / MGMT ask a yes-no question about the property rather than switching a
   view, so they stay switches — restyled to the system, not converted. */
.expenses-page .form-switch .form-check-input {
    width: 34px;
    height: 19px;
    background-color: var(--card-sunken);
    border-color: var(--hairline-strong);
    cursor: pointer;
    box-shadow: none;
}
.expenses-page .form-switch .form-check-input:checked {
    background-color: var(--action);
    border-color: var(--action);
}
.expenses-page .form-switch .form-check-input:focus {
    box-shadow: 0 0 0 3px var(--action-soft);
    border-color: var(--action);
}
.expenses-page .form-switch .form-check-label {
    font-size: 0.85rem;
    color: var(--ink);
    cursor: pointer;
    padding-left: 4px;
}

/* ===== Buttons =====
   Until now every button on this page was raw Bootswatch LUX (app.py loads
   dbc.themes.LUX and nothing here touched `.btn`): uppercase, square-cornered,
   near-black primary. That was never drift — it was an untouched theme.

   This block is CSS-only on purpose. Every `dbc.Button` call in
   pages/expenses.py already encodes its role through `color=` / `outline=`,
   so Bootstrap's own class is the role token and no Python has to change.

   Bootswatch 5.3 splits the two halves of a button, and they have to be
   overridden differently:

   * **Color** is exposed as `--bs-btn-*` custom properties, so setting those
     lets Bootstrap keep resolving hover/active/disabled itself.
   * **Geometry is not.** LUX re-declares `border-radius`, `border-width`,
     `font-size` and `line-height` as *literal* values on `.btn` / `.btn-sm`,
     which beat the variables entirely — a `--bs-btn-border-radius: 6px` that
     computes to `border-radius: 0px` was the first symptom. Geometry
     therefore has to be set as real properties, not vars.

   `.expenses-page .btn` is (0,2,0) and beats every bare `.btn-*` rule in the
   theme, which also means `.btn-sm` has to be re-scoped below or this rule's
   sizing would swallow the modifier. */
.expenses-page .btn {
    --bs-btn-font-weight: 500;
    /* Disabled is a state we draw ourselves (see the destructive rules), not
       a dimmed version of the enabled one — so no global opacity fade. */
    --bs-btn-disabled-opacity: 1;
    /* Literal, not --bs-btn-*: LUX hard-codes these. 36px tall. */
    border-radius: 6px;
    border-width: 1px;
    padding: 8px 14px;
    font-size: 0.85rem;
    line-height: 1.35;
    font-weight: 500;
    font-family: inherit;
    text-transform: none;
    letter-spacing: 0;
    box-shadow: none;
    transition: background-color 0.12s ease, border-color 0.12s ease,
        color 0.12s ease;
}
.expenses-page .btn:disabled,
.expenses-page .btn.disabled {
    cursor: not-allowed;
}
/* The in-card variant, 32px — same relationship to the base button that
   .seg-toggle-sm has to .seg-toggle. It is the page's *de facto* standard:
   21 of the 23 dbc.Button calls in pages/expenses.py pass size="sm", because
   almost every button here sits inside a card next to a form row. Same
   specificity as the base rule above, so this has to come after it.

   LUX ships `.btn-sm { font-size: 10px }` as a literal, which is why an
   unstyled sm button rendered at 10px — restate the size here. */
.expenses-page .btn-sm {
    border-radius: 6px;
    padding: 6px 12px;
    font-size: 0.78rem;
    line-height: 1.35;
}
/* Focus ring per DESIGN.md, replacing Bootstrap's .25rem 50%-alpha halo. */
.expenses-page .btn:focus-visible {
    box-shadow: 0 0 0 3px var(--action-soft);
    outline: none;
}

/* Primary — one per logical form/section, not per page. CapEx's entry form,
   its edit modal and Catch-All's two lists each own a local primary. */
.expenses-page .btn-primary {
    --bs-btn-color: #fff;
    --bs-btn-bg: var(--action);
    --bs-btn-border-color: var(--action);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--action-hover);
    --bs-btn-hover-border-color: var(--action-hover);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--action-hover);
    --bs-btn-active-border-color: var(--action-hover);
    --bs-btn-disabled-color: var(--mute);
    --bs-btn-disabled-bg: var(--card-sunken);
    --bs-btn-disabled-border-color: var(--hairline-strong);
}

/* Secondary — white field, hairline-strong edge, ink text. Both the filled
   and outline classes land here; the page only uses `outline=True`, but a
   plain color="secondary" shouldn't silently render as LUX gray. */
.expenses-page .btn-secondary,
.expenses-page .btn-outline-secondary {
    --bs-btn-color: var(--ink);
    --bs-btn-bg: var(--card);
    --bs-btn-border-color: var(--hairline-strong);
    --bs-btn-hover-color: var(--ink);
    --bs-btn-hover-bg: var(--card-sunken);
    --bs-btn-hover-border-color: var(--hairline-strong);
    --bs-btn-active-color: var(--ink);
    --bs-btn-active-bg: var(--card-sunken);
    --bs-btn-active-border-color: var(--hairline-strong);
    --bs-btn-disabled-color: var(--mute);
    --bs-btn-disabled-bg: var(--card);
    --bs-btn-disabled-border-color: var(--hairline);
}

/* Destructive — three distinct states, not one color at three opacities.
   At rest it's an outline: an audit of the running page found at most one
   danger button visible at a time, so a solid red field bought nothing and
   cost a loud red sitting next to Add in three places. The fill is saved for
   hover — the moment of intent, right before the click lands. */
.expenses-page .btn-danger,
.expenses-page .btn-outline-danger {
    --bs-btn-color: var(--danger);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--danger);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--danger);
    --bs-btn-hover-border-color: var(--danger);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--danger-deep);
    --bs-btn-active-border-color: var(--danger-deep);
    /* Third state. Delete Entry before a row is selected must read as inert
       at a glance, not as a quieter red — a disabled button has no hover to
       explain itself with. */
    --bs-btn-disabled-color: var(--mute);
    --bs-btn-disabled-bg: var(--card);
    --bs-btn-disabled-border-color: var(--hairline-strong);
}
.expenses-page .btn-outline-danger:focus-visible,
.expenses-page .btn-danger:focus-visible {
    box-shadow: 0 0 0 3px var(--danger-soft);
}

/* Tertiary / ghost — no field, action text, action-soft on hover. */
.expenses-page .btn-link {
    --bs-btn-color: var(--action);
    --bs-btn-hover-color: var(--action-hover);
    --bs-btn-active-color: var(--action-hover);
    --bs-btn-disabled-color: var(--mute);
    text-decoration: none;
}
.expenses-page .btn-link:hover {
    background: var(--action-soft);
}
/* The disclosure ghost ("Other adjustments") used p-0 to sit flush with the
   text above it, which leaves a hover tint no room to breathe. Padding it and
   pulling it back by the same amount keeps the optical alignment. */
.expenses-page .btn-ghost-inline {
    padding: 3px 8px;
    margin-left: -8px;
    border-radius: 6px;
}

/* Data grid: 36px rows, hairline row separators (never vertical gridlines —
   columns separate by alignment), card-hover on hover, action-soft on
   selection. Alpine is configured through its own custom properties rather
   than fighting its selectors.

   The header carries no fill. DESIGN.md line 511 specs `card-sunken` here,
   but a flat tint doesn't read as sunken — it just reads as a gray band, and
   with a hairline bottom border the header already separates cleanly. Revisit
   only if the grid needs a stronger header on a denser page. */
.expenses-page .ag-theme-alpine {
    --ag-header-background-color: transparent;
    --ag-header-column-separator-display: none;
    --ag-row-height: 36px;
    --ag-header-height: 36px;
    --ag-font-size: 13px;
    --ag-borders: solid;
    --ag-border-color: var(--hairline);
    --ag-row-border-color: var(--hairline);
    --ag-cell-horizontal-border: none;
    --ag-row-hover-color: var(--card-hover);
    --ag-selected-row-background-color: var(--action-soft);
}
.expenses-page .ag-theme-alpine .ag-header-cell-label {
    color: var(--mute);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.6px;
    text-transform: uppercase;
}

/* Read-only cells carry no resting fill. Editable is the *minority* in these
   grids (Amount alone in most), so tinting everything else turned the table
   gray. Hover on the genuinely-editable cells carries the affordance instead
   — .ro-cell exists only to exclude the rest from that hover, and is applied
   via cellClassRules (cellClass loses to `type: "numericColumn"`). */
.expenses-page .ag-theme-alpine .ag-cell:not(.ro-cell):not(.ag-cell-inline-editing):hover {
    background-color: var(--action-soft);
    cursor: text;
}

/* Columns auto-size to their content, so on a wide screen the last column
   stops short of the grid's right edge — leaving row separators hanging in
   white space. AG Grid sets these container widths inline from the summed
   column widths; min-width overrides that without touching the columns
   themselves, and stays inert when the columns genuinely overflow. */
.expenses-page .ag-theme-alpine .ag-center-cols-container,
.expenses-page .ag-theme-alpine .ag-header-container {
    min-width: 100%;
}

/* Plotly writes font-family as an inline style on every SVG <text>, defaulting
   to Open Sans, so only !important reaches it. Doing it here rather than adding
   a font to six separate update_layout() calls keeps the pilot in one place and
   trivially reversible. */
.expenses-page .js-plotly-plot text {
    font-family: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        sans-serif !important;
}

/* ===== App Container ===== */
.app-container {
    display: flex;
    min-height: 100vh;
}

/* ===== Sidebar ===== */
.sidebar {
    width: 240px;
    min-width: 240px;
    background-color: #1a1d23;
    color: #c9d1d9;
    padding: 0;
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    overflow-y: hidden;
    z-index: 100;
    display: flex;
    flex-direction: column;
}

/* Scrolls independently between the frozen brand header and footer */
.sidebar-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 20px 20px 12px 20px;
    flex-shrink: 0;
}

.sidebar-logo {
    width: 32px;
    height: 32px;
    object-fit: contain;
}

.sidebar-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: #ffffff;
    letter-spacing: 0.02em;
}

.sidebar-divider {
    border-color: rgba(255, 255, 255, 0.08);
    margin: 0 16px 8px 16px;
}

.sidebar-nav {
    display: flex;
    flex-direction: column;
    padding: 0 8px;
}

/* ===== Live financial summary ===== */
.sidebar-live-link {
    display: block;
    text-decoration: none !important;
    padding: 0 12px;
    margin-top: 6px;
    margin-bottom: 18px;
}
/* Spec: Claude Design project ce8a7e98 (PeakCard.dc.html). Colors, weights and
   tracking are copied verbatim; sizes are the design's ratios rescaled — the
   component is authored on a 380px card and this sidebar is 216px, where the
   literal px values overflow. The 40px hero is the anchor and every other size
   is its design ratio against that. */
.sidebar-live-inner {
    background: #1b1e25;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 13px;
    padding: 17px 16px;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}
.sidebar-live-link:hover .sidebar-live-inner {
    background: #222630;
    border-color: rgba(255, 255, 255, 0.16);
}
.live-idle { color: #8b93a3; font-size: 0.75rem; line-height: 1.4; }

/* Sub-captions — AT PEAK IN / IF SOLD TODAY (16px of 40 in the spec) */
.live-cap {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: #8b93a3;
}
/* Section headers — AHEAD OF S&P / BEHIND S&P (22px of 40 in the spec) */
.live-cap-lg {
    font-size: 0.9rem;
    letter-spacing: 0.06em;
    line-height: 1.15;
    color: #8b93a3;
}
.live-cap-row { line-height: 1; }
.live-cap-year { font-size: 0.6rem; font-weight: 600; color: #8b93a3; }
.live-cap-spaced { display: block; margin-top: 0; }
.live-muted { font-size: 0.8rem; color: #8b93a3; margin-top: 2px; }

/* "AT PEAK IN  [17 yrs · 2043]" */
.live-peak-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 2px;
}
/* At 216px sidebar width the caption + pill only fit on one line if the caption
   can't wrap and the slack between them is reclaimed (tighter tracking, gap and
   pill padding). */
.live-peak-row .live-cap {
    white-space: nowrap;
    letter-spacing: 0.04em;
    flex: 0 0 auto;
}
.live-peak-row .live-pill {
    padding: 4px 9px;
    letter-spacing: 0;
}
.live-pill {
    background: #2a2e37;
    border-radius: 999px;
    padding: 5px 12px;
    font-size: 0.66rem;
    font-weight: 600;
    color: #f5f6f7;
    white-space: nowrap;
}

/* Peak IRR comparison, fenced by a 1px rule above and below */
.live-irr-block {
    margin: 13px 0;
    padding: 13px 0;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.live-irr-row {
    display: flex;
    align-items: center;
    gap: 8px;
}
/* "PEAK / IRR" — same flex-column + gap as .live-irr-col, so this line gap is
   identical to the value/sub-label gap below, not just visually close. */
.live-irr-label {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex-shrink: 0;
}
.live-irr-label-line {
    font-size: 0.825rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    line-height: 1;
    color: #8b93a3;
    white-space: nowrap;
}
/* S&P and Prop. sit close together as one comparison unit — no "vs" divider,
   so the gap between them is tight while the label/flash keep their own
   breathing room via the row's larger gap. */
.live-irr-pair {
    display: flex;
    align-items: center;
    gap: 5px;
}
/* Each figure stacks its percentage over its label, left-aligned. */
.live-irr-col {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    flex-shrink: 0;
}
.live-irr-val { font-size: 0.825rem; line-height: 1; white-space: nowrap; }
.live-irr-sub {
    font-size: 0.825rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
}
.live-irr-sp { color: #8b93a3; font-weight: 600; }
.live-irr-sub-sp { color: #8b93a3; }
.live-irr-prop { color: #f5f6f7; font-weight: 700; }
.live-irr-sub-prop { color: #f5f6f7; }
/* The flash gets its own lane on the right so nothing shifts when it fires. */
.live-irr-row .ghost-a, .live-irr-row .ghost-b { margin-left: auto; }

/* IRR change tint — deliberately quieter than the hero background pulse so the
   dollar figures stay the loudest thing in the widget. Distinct keyframe names
   per parity for the same animation-restart reason as the hero pulses. */
@keyframes irrUpA { 0% { color: #22c55e; } 100% { color: #f5f6f7; } }
@keyframes irrUpB { 0% { color: #22c55e; } 100% { color: #f5f6f7; } }
@keyframes irrDownA { 0% { color: #f87171; } 100% { color: #f5f6f7; } }
@keyframes irrDownB { 0% { color: #f87171; } 100% { color: #f5f6f7; } }
.irr-up-a { animation: irrUpA 2.25s ease; }
.irr-up-b { animation: irrUpB 2.25s ease; }
.irr-down-a { animation: irrDownA 2.25s ease; }
.irr-down-b { animation: irrDownB 2.25s ease; }

/* Hero numbers — the two figures that move on every assumption tweak */
.live-hero-row {
    display: flex;
    align-items: baseline;
    /* Only a floor — margin-left:auto on the flash sets the real spacing. Small
       enough that the widest hero + widest flash still fit the 182px line. */
    gap: 4px;
    flex-wrap: nowrap;
    margin: 6px 0;
}
/* Flash sits to the right of the hero number in its own lane — pushed there
   rather than sharing flow, so the number never shifts when it appears. */
.live-hero-row .ghost-a, .live-hero-row .ghost-b { margin-left: auto; }
.live-hero {
    font-size: 1.65rem;
    font-weight: 700;
    color: #f5f6f7;
    line-height: 1;
    letter-spacing: -0.01em;
    border-radius: 4px;
    padding: 0 3px;
    margin-left: -3px;
}

/* SELL alert — shown only when the verdict turns (HOLD stays silent) */
.live-alert {
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: rgba(220, 38, 38, 0.14);
    border: 1px solid rgba(220, 38, 38, 0.4);
    border-radius: 6px;
    padding: 5px 8px;
    margin-bottom: 8px;
}
.live-alert-word { color: #f87171; font-weight: 800; font-size: 0.8rem; letter-spacing: 0.04em; }
.live-alert-reason { display: block; color: #fca5a5; font-size: 0.7rem; }

/* Directional pulse on change. Two parities (a/b) with DISTINCT keyframe names
   per direction — a changed animation-name is what forces the browser to restart
   the animation, so every change re-fires (a shared name only plays once). */
@keyframes pulseUpA { 0% { background: rgba(34, 197, 94, 0.5); } 100% { background: transparent; } }
@keyframes pulseUpB { 0% { background: rgba(34, 197, 94, 0.5); } 100% { background: transparent; } }
@keyframes pulseDownA { 0% { background: rgba(248, 113, 113, 0.5); } 100% { background: transparent; } }
@keyframes pulseDownB { 0% { background: rgba(248, 113, 113, 0.5); } 100% { background: transparent; } }
.pulse-up-a { animation: pulseUpA 2.25s ease; }
.pulse-up-b { animation: pulseUpB 2.25s ease; }
.pulse-down-a { animation: pulseDownA 2.25s ease; }
.pulse-down-b { animation: pulseDownB 2.25s ease; }

/* Inline +/- delta that fades out (distinct keyframe names per parity, same reason) */
@keyframes ghostFadeA { 0% { opacity: 1; } 60% { opacity: 1; } 100% { opacity: 0; } }
@keyframes ghostFadeB { 0% { opacity: 1; } 60% { opacity: 1; } 100% { opacity: 0; } }
.ghost-a { animation: ghostFadeA 4s ease forwards; }
.ghost-b { animation: ghostFadeB 4s ease forwards; }
.ghost-a, .ghost-b {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 700;
    /* "−$82.1k" is one token — without these the right-pushed lane gets squeezed
       and the sign breaks onto a second line. */
    white-space: nowrap;
    flex: 0 0 auto;
}
.ghost-up { color: #22c55e; }
.ghost-down { color: #f87171; }

/* ===== Nav Links (Top-Level) ===== */
.nav-link-item {
    color: #9ca3af !important;
    padding: 10px 16px !important;
    border-radius: 6px !important;
    margin-bottom: 2px;
    font-size: 0.9rem;
    font-weight: 500;
    transition: background-color 0.15s ease, color 0.15s ease;
    text-decoration: none !important;
}

.nav-link-item:hover {
    color: #e5e7eb !important;
    background-color: rgba(255, 255, 255, 0.06) !important;
}

.nav-link-item.active {
    color: #ffffff !important;
    background-color: rgba(99, 102, 241, 0.15) !important;
    font-weight: 600;
}

/* Parent items with sub-nav: label left, chevron right */
.nav-link-item.has-subnav {
    display: flex !important;
    align-items: center;
    justify-content: space-between;
}

.nav-chevron {
    display: flex;
    align-items: center;
    margin-left: 8px;
}

/* Tailless arrow built from two borders; points down when collapsed */
.nav-chevron-icon {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg);
    transition: transform 0.15s ease;
    opacity: 0.8;
}

/* Rotates to point up when the sub-nav is expanded */
.nav-chevron.open .nav-chevron-icon {
    transform: rotate(225deg);
}

/* ===== Nav Sub-Items (Indented, Subordinate) ===== */
.nav-sub-item {
    color: #6b7280 !important;
    padding: 7px 16px 7px 40px !important;
    border-radius: 6px !important;
    margin-bottom: 1px;
    font-size: 0.82rem;
    font-weight: 400;
    transition: background-color 0.15s ease, color 0.15s ease;
    text-decoration: none !important;
}

.nav-sub-item:hover {
    color: #d1d5db !important;
    background-color: rgba(255, 255, 255, 0.04) !important;
}

.nav-sub-item.active {
    color: #e5e7eb !important;
    background-color: rgba(99, 102, 241, 0.1) !important;
    font-weight: 500;
}

/* ===== Content Area ===== */
.content-area {
    margin-left: 240px;
    padding: 32px 40px;
    flex: 1;
    min-height: 100vh;
    background-color: var(--canvas);
}

/* ===== Onboarding gate (blur + unlock overlay) ===== */

/* Blur the analysis charts underneath the gate. pointer-events off so the
   dimmed content can't be interacted with while locked. */
.content-area.content-gated > * {
    filter: blur(6px);
    pointer-events: none;
    user-select: none;
}

.onboarding-gate {
    position: fixed;
    top: 0;
    left: 240px;
    right: 0;
    bottom: 0;
    z-index: 500;
    background: rgba(255, 255, 255, 0.55);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 80px 24px;
    overflow-y: auto;
}

.gate-overlay-inner {
    width: 100%;
    max-width: 440px;
}

.gate-card {
    background: #ffffff;
    border: 1px solid #e5e7eb;
    border-radius: 16px;
    box-shadow: 0 12px 40px rgba(15, 23, 42, 0.14);
    padding: 28px 28px 24px;
}

.gate-title {
    font-size: 1.35rem;
    font-weight: 700;
    color: #111827;
    margin-bottom: 6px;
}

.gate-subtitle {
    font-size: 0.9rem;
    color: #6b7280;
    line-height: 1.5;
    margin-bottom: 18px;
}

.gate-progress-track {
    height: 6px;
    background: #f1f5f9;
    border-radius: 99px;
    overflow: hidden;
    margin-bottom: 6px;
}

.gate-progress-fill {
    height: 100%;
    background: #38bdf8;
    border-radius: 99px;
    transition: width 0.3s ease;
}

.gate-progress-label {
    font-size: 0.78rem;
    color: #9ca3af;
    margin-bottom: 16px;
}

.gate-item-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Fine-tuning (collapsed) inside the gate card — mirrors the sidebar checklist */
.gate-tuning-group {
    margin-top: 14px;
    border-top: 1px solid #eef2f7;
    padding-top: 10px;
}
.gate-group-summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #64748b;
}
.gate-group-summary::-webkit-details-marker { display: none; }
.gate-group-summary::before {
    content: "▼";
    font-size: 0.72rem;
    color: #94a3b8;
}
.gate-tuning-group[open] > .gate-group-summary::before,
.gate-essentials-group[open] > .gate-group-summary::before {
    content: "▲";
}

.gate-essentials-group {
    margin-top: 6px;
}
.gate-essentials-group .gate-item-list { margin-top: 4px; }
.gate-tuning-group .gate-item-list { margin-top: 4px; }

.gate-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 4px;
    border-top: 1px solid #f1f5f9;
}
.gate-item:first-child {
    border-top: none;
}

.gate-item-icon {
    font-size: 0.95rem;
    width: 16px;
    text-align: center;
    flex-shrink: 0;
}
.gate-icon-done { color: #22c55e; }
.gate-icon-empty { color: #38bdf8; }
.gate-icon-default { color: #9ca3af; }

.gate-item-label {
    font-size: 0.92rem;
    color: #111827;
    flex: 1;
}
.gate-item-done .gate-item-label { color: #6b7280; }

.gate-item-add {
    font-size: 0.85rem;
    font-weight: 600;
    color: #ffffff !important;
    text-decoration: none !important;
    background: #2563eb;
    padding: 4px 14px;
    border-radius: 6px;
}
.gate-item-add:hover { background: #1d4ed8; }

.gate-item-done {
    font-size: 0.8rem;
    color: #22c55e;
    font-weight: 600;
}

/* ===== Page Container ===== */
.page-container {
    max-width: 1200px;
}

.page-container h2 {
    color: #111827;
    font-weight: 700;
    font-size: 1.75rem;
    margin-bottom: 8px;
}

.page-container h4 {
    color: #374151;
    font-weight: 600;
    font-size: 1.1rem;
    margin-bottom: 16px;
}

.page-container p {
    color: #6b7280;
    font-size: 0.95rem;
}

/* ===== Hide Dash default dev tools ribbon in production ===== */
._dash-loading {
    display: none;
}

/* ===== Property Setup Page ===== */

.page-subtitle {
    color: #6b7280;
    font-size: 0.95rem;
    margin-bottom: 28px;
}

.setup-section {
    background-color: var(--card);
    border: 1px solid var(--hairline);
    border-radius: 10px;
    box-shadow: var(--raised);
    padding: 24px 28px;
    margin-bottom: 24px;
}

.section-heading {
    color: #111827;
    font-weight: 600;
    font-size: 1rem;
    margin-bottom: 20px;
    padding-bottom: 10px;
    border-bottom: 1px solid #e5e7eb;
}

.section-subtext {
    color: #9ca3af;
    font-size: 0.82rem;
    margin-top: -12px;
    margin-bottom: 18px;
}

.form-label {
    color: #374151;
    font-size: 0.88rem;
    font-weight: 500;
    margin-bottom: 0;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* ===== Performance assumptions row =====
   Flex, not a 12-column grid: each control takes only the width it needs, so
   five fit comfortably and the labels never wrap. The boxes themselves reuse
   .value-box / .value-box-input (see Property Setup's tax matrix) rather than a
   parallel style — a bespoke max-width let the "%" addon wrap onto its own line. */

.assumption-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    column-gap: 20px;
    row-gap: 14px;
}
/* Natural width only — without this the cells stretch to fill and push the
   last two onto a second line. */
.assumption-cell {
    flex: 0 0 auto;
}
.assumption-cell label,
.assumption-cell .form-label {
    white-space: nowrap;
    font-size: 0.8rem;
}
/* The addon must sit beside the input, never below it. */
.assumption-cell .value-box {
    flex-wrap: nowrap;
}

/* ===== Segmented Toggle (e.g. Tax View: Pre-tax / After-tax) ===== */

/* Bootstrap's form-check-inline puts a 1rem margin between the options, which
   reads as two separate buttons rather than one segmented control. */
.segmented-toggle .form-check-inline {
    margin-right: 0;
}
.segmented-toggle .btn {
    white-space: nowrap;
    border: 1px solid #d1d5db !important;
    background-color: #ffffff;
    color: #374151;
    font-weight: 600;
    font-size: 0.78rem;
    letter-spacing: 0.02em;
    padding: 6px 16px;
}

.segmented-toggle .btn:hover {
    background-color: #f3f4f6;
}

.segmented-toggle .btn-check:checked + .btn {
    background-color: #111827;
    border-color: #111827 !important;
    color: #ffffff;
}

.segmented-toggle .btn-check:checked + .btn:hover {
    background-color: #111827;
}

/* ===== Info Icon & Benchmark Tooltips (CSS-only, hoverable) ===== */

.info-icon {
    color: #9ca3af;
    font-size: 0.8rem;
    cursor: default;
    vertical-align: middle;
    transition: color 0.15s ease;
    user-select: none;
}

.custom-tooltip-wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
}

/* Invisible bridge fills the gap between icon and tooltip panel so the
   mouse doesn't leave the hover zone while traveling between them. */
.custom-tooltip-wrapper::after {
    content: "";
    position: absolute;
    left: 100%;
    top: 0;
    width: 12px;        /* matches the gap + tooltip arrow area */
    height: 100%;
    display: block;
}

.custom-tooltip-content {
    display: none;
    position: absolute;
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%);
    background-color: #1f2937;
    color: #e5e7eb;
    font-size: 0.8rem;
    text-align: left;
    max-width: 280px;
    padding: 8px 12px;
    border-radius: 6px;
    line-height: 1.5;
    white-space: normal;
    pointer-events: auto;   /* allow mouse events so links are clickable */
    z-index: 9999;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
    /* small left-pointing arrow */
    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3));
}

/* Show the panel when hovering the wrapper OR the panel itself */
.custom-tooltip-wrapper:hover .custom-tooltip-content,
.custom-tooltip-content:hover {
    display: block;
}

.custom-tooltip-wrapper:hover .info-icon {
    color: #6366f1;
}

/* ===== Dropdowns (Dash dcc.Dropdown override) ===== */

.dr-dropdown .Select-control {
    border-color: #d1d5db !important;
    border-radius: 6px !important;
    font-size: 0.88rem;
}

.dr-dropdown .Select-menu-outer {
    font-size: 0.88rem;
    border-color: #d1d5db;
}

/* ===== Nominal Badge ===== */

.badge-nominal {
    font-size: 0.7rem;
    font-weight: 500;
    vertical-align: middle;
    background-color: #6366f1 !important;
}

/* ===== Auto-calc hint beneath rent field ===== */

.form-hint {
    color: #9ca3af;
    font-size: 0.78rem;
    font-style: italic;
}

/* ===== Slider tooltip bubbles — uniform width ===== */

.rc-slider-tooltip-inner {
    min-width: 52px !important;
    text-align: center !important;
}

/* ===== Date Slicer Pills ===== */

.slicer-group {
    display: flex;
    align-items: center;
    gap: 6px;
}

.slicer-label {
    font-size: 0.78rem;
    font-weight: 600;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
}

.slicer-pills {
    display: inline-flex !important;
    border: 1px solid #d1d5db;
    border-radius: 999px;
    overflow: hidden;
    background: #ffffff;
}

.slicer-pills label {
    /* Padding lives on .dash-options-list-option-text (below), not here — a
       tooltip target must be an element whose own box covers the full pill,
       and content-box sizing on a child can never reach a parent's padding. */
    padding: 0 !important;
    font-size: 0.82rem !important;
    font-weight: 500;
    color: #6b7280;
    cursor: pointer;
    border-right: 1px solid #e5e7eb;
    user-select: none;
    white-space: nowrap;
    transition: background-color 0.15s ease, color 0.15s ease;
    /* Dash 4 adds margin-right via .dash-radioitems-inline — zero it out so
       teal fill reaches both edges of every pill slot with no white gaps. */
    margin: 0 !important;
}

.slicer-pills label:last-child {
    border-right: none;
}

.slicer-pills label:has(input:checked) {
    background-color: #0d9488;
    color: #ffffff;
}

.slicer-pills label:hover:not(:has(input:checked)):not(:has(input:disabled)) {
    background-color: #f3f4f6;
}

/* Lookback windows longer than the holding period are dead (same range as
   Since Purchase), so they're disabled + grayed with a hover note. */
.slicer-pills label:has(input:disabled) {
    color: #cbd5e1;
    cursor: not-allowed;
    background-color: #f9fafb;
}

.slicer-pills label:has(input:disabled) span {
    cursor: not-allowed;
}

/* The generated .dash-options-list-option-text span only wraps the text
   glyphs; a tooltip targeting it (or a native title attribute) only fires
   over the letters themselves. The pill's visual padding is moved onto this
   span (see .slicer-pills label above) so the span's own box IS the full
   pill, and hover works anywhere on it. */
.slicer-pills .dash-options-list-option-text {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 5px 12px;
    height: 100%;
    box-sizing: border-box;
}

.date-range-text {
    font-size: 0.85rem;
    font-weight: 500;
    color: #374151;
    white-space: nowrap;
}

/* ===== KPI Cards ===== */

.kpi-card {
    border: 1px solid var(--hairline);
    border-radius: 8px;
    background: var(--card);
    box-shadow: var(--raised);
}

.kpi-card-wrapper {
    padding: 4px;
    border-radius: 12px;
    cursor: pointer;
    transition: background-color 0.2s ease;
    height: 100%;
}

.kpi-card-wrapper .kpi-card {
    height: 100%;
}

.kpi-card-wrapper.active {
    background-color: #eff6ff;
}

.kpi-card-wrapper:hover:not(.active) {
    background-color: #f9fafb;
}

.kpi-card-label {
    font-size: 0.72rem;
    color: #6b7280;
    margin-bottom: 2px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.kpi-card-value {
    font-size: 1.25rem;
    font-weight: 700;
    color: #111827;
    margin-bottom: 4px;
}

.kpi-sparkline {
    margin: 0 -8px;
}

/* Status border — REMOVED 2026-08-01. The pastel left rail restated the verdict
   the thermometer pill already gives, so it was a second semantic cue competing
   with category color on the same card. The classes are kept as no-ops because
   ~10 call sites build `kpi-border-{status}` class strings; retiring the rule
   here avoids touching every one of them. */

.kpi-border-great,
.kpi-border-good,
.kpi-border-poor,
.kpi-border-neutral {
    border-left: 1px solid #e5e7eb;
}

/* Stat card — delta line + inline share bar */

.kpi-stat-delta {
    font-size: 0.72rem;
    font-weight: 600;
    margin-top: -2px;
    margin-bottom: 4px;
}

.kpi-delta-ok    { color: #16a34a; }
.kpi-delta-alert { color: #dc2626; }
.kpi-delta-neutral { color: #6b7280; }

.kpi-stat-bar {
    height: 12px;
    background: #f1f5f9;
    border-radius: 6px;
    overflow: hidden;
    /* Lands on the same baseline as .thermo-track (143px from card top) so the
       bar reads as one row across the card grid.
       CAUTION: this offset is the remainder after the label, value and subtitle
       above it — change .kpi-card-label min-height, .kpi-card-value font-size,
       or .kpi-card-subtitle metrics and this number must be re-measured, or the
       bars silently drift apart again. */
    margin-top: 35px;
}

.kpi-stat-bar-fill {
    height: 100%;
    background: #64748b;
    border-radius: 6px;
    transition: width 0.3s ease;
}

/* Benchmark bar — fill on a scale sized to fit both the value and the
   benchmark tick, so overshoot stays visible instead of clamping at full. */

.kpi-bench-track {
    position: relative;
    height: 12px;
    background: #f1f5f9;
    border-radius: 6px;
    margin-top: 8px;
}

.kpi-bench-fill {
    height: 100%;
    border-radius: 6px;
    transition: width 0.3s ease;
}

/* Slate rather than near-black, with a white ring: the share bar's fill is now
   navy, and a dark marker sitting on top of a dark fill vanished once the fill
   ran past the benchmark. The ring keeps the tick readable over either ground,
   and slate keeps the benchmark subordinate to the value it is a reference for. */
.kpi-bench-marker {
    position: absolute;
    top: -3px;
    bottom: -3px;
    width: 2px;
    background: #64748b;
    border-radius: 1px;
    box-shadow: 0 0 0 2px #ffffff;
}

.kpi-bench-caption {
    position: relative;
    height: 0.95rem;
    margin-top: 4px;
}

.kpi-bench-caption span {
    position: absolute;
    transform: translateX(-50%);
    white-space: nowrap;
    color: #6b7280;
    font-size: 0.68rem;
    font-weight: 600;
}

/* Ranked mini-bar list (Where the money goes) */

.kpi-rank-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0;
    font-size: 0.72rem;
}

.kpi-rank-name {
    flex: 0 0 68px;
    color: #4b5563;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.kpi-rank-track {
    flex: 1 1 auto;
    height: 10px;
    background: #f1f5f9;
    border-radius: 5px;
    overflow: hidden;
}

.kpi-rank-fill {
    height: 100%;
    border-radius: 5px;
}

.kpi-rank-val {
    flex: 0 0 auto;
    min-width: 46px;
    text-align: right;
    color: #1f2937;
    font-variant-numeric: tabular-nums;
}

/* Empty state for the ranked list — shown until a category has two years of
   actuals, in place of a full column of blank tracks. */
.kpi-rank-empty {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    min-height: 130px;
    padding: 0 6px;
}

.kpi-rank-empty-title {
    font-size: 0.78rem;
    font-weight: 600;
    color: #6b7280;
    margin-bottom: 4px;
}

.kpi-rank-empty-sub {
    font-size: 0.7rem;
    color: #9ca3af;
    line-height: 1.45;
    max-width: 210px;
}

/* Horizontal 100% composition bar + itemized legend (Expense Composition) */

/* Composition card — the per-row bar carries share *and* category colour, so
   there is no separate legend dot. Deliberately mirrors .kpi-rank-* above: the
   two cards sit side by side and should read as one family. */
.kpi-comp-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

.kpi-comp-legend {
    display: flex;
    flex-direction: column;
}

.kpi-comp-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0;
    font-size: 0.72rem;
}

.kpi-comp-name {
    flex: 0 0 68px;
    color: #4b5563;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.kpi-comp-track {
    flex: 1 1 auto;
    height: 10px;
    background: #f1f5f9;
    border-radius: 5px;
    overflow: hidden;
}

.kpi-comp-fill {
    height: 100%;
    border-radius: 5px;
}

.kpi-comp-val {
    flex: 0 0 auto;
    min-width: 46px;
    text-align: right;
    color: #1f2937;
    font-variant-numeric: tabular-nums;
}

/* $/% switcher — the reserve card's segmented control, shrunk to sit in a card
   header rather than a footer. */
/* Rounded on/off switches (HOA / MGMT tab toggles) */
#hoa-enabled-switch.form-check-input,
#mgmt-enabled-switch.form-check-input {
    border-radius: 2em !important;
}

/* Suggested Reserve headline: % on the left, $ conversion on the right */

.kpi-suggested-headline {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
}

.kpi-suggested-dollar {
    font-size: 0.9rem;
    font-weight: 600;
    color: #6b7280;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Compare bars (suggested vs current reserve) */

.kpi-compare-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
    font-size: 0.72rem;
}

.kpi-compare-label {
    flex: 0 0 76px;
    color: #6b7280;
    white-space: nowrap;   /* keep "Reserve /mo" on one line in both views */
}

.kpi-compare-track {
    flex: 1 1 auto;
    height: 10px;
    background: #f1f5f9;
    border-radius: 5px;
    overflow: hidden;
}

.kpi-compare-fill {
    height: 100%;
    border-radius: 5px;
    background: #f59e0b;
}

/* Suggested Reserve — label line + bar row ($ · % / yr) */

.kpi-reserve-rowlabel {
    color: #6b7280;
    font-size: 0.72rem;
    font-weight: 500;
    margin-top: 8px;
    margin-bottom: 3px;
}

.kpi-reserve-barrow {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.72rem;
}

.kpi-reserve-barrow .kpi-compare-track {
    flex: 1 1 auto;
}

.kpi-reserve-amt {
    color: #374151;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.kpi-reserve-dot {
    color: #cbd5e1;
    font-weight: 700;
}

.kpi-reserve-pct {
    color: #6b7280;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* In-card CapEx toggle (segmented) */

/* Pin the toggle footer to the bottom of the card body so the CapEx and
   Reserve-period toggles line up across cards of equal height. */
.kpi-card > .card-body {
    display: flex;
    flex-direction: column;
}

/* Keep every expense KPI card the same height across sub-tabs so switching
   tabs doesn't shift the chart/table below. Scoped to the expenses KPI row so
   the Dashboard cards are unaffected. */
#expense-kpi-row .kpi-card {
    min-height: 268px;
}

.kpi-card-footer {
    margin-top: auto;
    padding-top: 8px;
    border-top: 1px solid #f1f5f9;
}

/* Signal card — icon + message */

.kpi-signal-message {
    font-size: 0.95rem;
    font-weight: 600;
    color: #1f2937;
    line-height: 1.3;
}

.kpi-signal-icon { font-size: 1.05rem; }

.kpi-signal-great { color: #16a34a; }
.kpi-signal-good  { color: #ca8a04; }
.kpi-signal-poor  { color: #dc2626; }
.kpi-signal-neutral { color: #6b7280; }

/* CapEx treatment toggle above the KPI row */

/* Status badge — small pill below the sparkline */

.kpi-status-badge {
    font-size: 0.68rem;
    font-weight: 600;
    padding: 2px 10px;
    border-radius: 12px;
    display: inline-block;
    letter-spacing: 0.02em;
    /* .kpi-card > .card-body is a column flexbox; without this the badge
       (a flex item) stretches to the card's full width instead of hugging
       its own text, despite display:inline-block. */
    align-self: flex-start;
}

.kpi-status-great {
    background-color: #f0fdf4;
    color: #16a34a;
}

.kpi-status-good {
    background-color: #fefce8;
    color: #ca8a04;
}

.kpi-status-poor {
    background-color: #fef2f2;
    color: #dc2626;
}

/* ===== KPI Card Subtitle ===== */

.kpi-card-subtitle {
    font-size: 0.68rem;
    color: #9ca3af;
    margin-top: -2px;
    margin-bottom: 4px;
    font-weight: 500;
}


/* TTM tooltip — pure CSS hover */
.ttm-tooltip {
    position: relative;
    display: inline;
    cursor: help;
    border-bottom: 1px dotted #9ca3af;
}

.ttm-tooltip::after {
    content: "Trailing 12 Months";
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    background-color: #1f2937;
    color: #e5e7eb;
    font-size: 0.7rem;
    padding: 4px 8px;
    border-radius: 4px;
    white-space: nowrap;
    display: none;
    z-index: 999;
    margin-bottom: 4px;
    pointer-events: none;
}

.ttm-tooltip:hover::after {
    display: block;
}

/* ===== Benchmark Threshold Inputs (gradient bar) ===== */

.benchmark-row {
    padding: 12px 20px 16px;
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    margin-top: 12px;
}

.benchmark-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 14px;
}

.benchmark-label-group {
    display: flex;
    align-items: center;
    gap: 6px;
}

.benchmark-label {
    display: inline;
    font-size: 0.82rem;
    font-weight: 400;
    color: #6b7280;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.benchmark-label-prefix {
    font-weight: 800;
    font-size: 0.92rem;
    color: #374151;
}

.benchmark-info-icon {
    font-size: 0.85rem;
}

.benchmark-reset-btn {
    background: none;
    border: none;
    padding: 0;
    color: #6b7280;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    text-decoration: underline;
}

.benchmark-reset-btn:hover {
    color: #374151;
}

/* Relative frame: the bar sits at the top, the two chips are pinned
   absolutely under their zone boundaries (left set by the callback). */
.benchmark-bar-inner {
    position: relative;
    height: 66px;
    margin: 0 12px;
}

.benchmark-bar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 26px;
}

.benchmark-bar-track {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 26px;
    border-radius: 6px;
}

.benchmark-zone-label {
    position: absolute;
    top: 0;
    height: 26px;
    line-height: 26px;
    transform: translateX(-50%);
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    pointer-events: none;
}

/* Draggable handles: a RangeSlider overlaid on the gradient bar. Dash 4's
   RangeSlider renders as Radix primitives (dash-slider-*), not the old
   rc-slider markup — track/range are forced transparent so only the
   gradient bar shows, and the thumbs are restyled as thin vertical ticks
   instead of Dash's default purple circles. */
.benchmark-slider-layer {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 26px;
    /* The Radix slider's own container/root stay a fixed 34px tall and
       top-align by default, which pushed the thumb's overhang entirely to
       the bottom. Centering the whole stack here makes it symmetric. */
    display: flex;
    align-items: center;
}

.benchmark-slider-layer .dash-slider-root {
    align-items: center;
}

.benchmark-slider-layer .dash-slider-track,
.benchmark-slider-layer .dash-slider-range {
    background: transparent !important;
}

.benchmark-slider-layer .dash-slider-thumb {
    width: 3px;
    /* Taller than the 26px bar so it overhangs evenly top and bottom —
       the root is centered via align-items: center above. */
    height: 36px;
    border-radius: 1px;
    background: #374151;
    border: none;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    cursor: grab;
}

.benchmark-slider-layer .dash-slider-thumb:hover,
.benchmark-slider-layer .dash-slider-thumb:focus-visible {
    background: #111827;
    box-shadow: 0 0 0 4px rgba(55, 65, 81, 0.15);
}

.benchmark-slider-layer .dash-slider-thumb:active {
    cursor: grabbing;
}

/* Read-only value boxes pinned under each handle (full colored border). */
.benchmark-chip {
    position: absolute;
    top: 38px;
    transform: translateX(-50%);
}

.benchmark-value-box {
    padding: 3px 12px;
    font-size: 0.85rem;
    font-weight: 500;
    text-align: center;
    border-radius: 6px;
    background: #fff;
    white-space: nowrap;
}

.benchmark-value-box-good { border: 1.5px solid #eab308; color: #854d0e; }
.benchmark-value-box-great { border: 1.5px solid #22c55e; color: #166534; }

/* ===== Expense Controls Row ===== */

.expense-controls-row {
    padding: 8px 0;
}

/* ===== Expense Empty State (first-time entry) ===== */

/* Wraps the hero chart + content area so the empty-state form can float on
   top of the chart (blurred behind it) instead of requiring a scroll past
   the chart to reach a form stacked below. */
.expense-chart-content-wrap {
    position: relative;
}

.expense-chart-blurred {
    filter: blur(6px);
    pointer-events: none;
    user-select: none;
    /* Guarantees a backdrop tall enough to centre the guided card in, so the
       card sits in the same spot whether the tab's chart is full, sparse, or
       (Catch-All, empty) rendering nothing at all. */
    min-height: 380px;
}

.expense-content-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
}
.expense-content-overlay .expense-empty-wrap {
    padding: 0;
}
.expense-content-overlay .expense-empty-card {
    background-color: #ffffff;
    box-shadow: 0 8px 28px rgba(15, 23, 42, 0.18);
}

/* CapEx onboarding — two numbered steps, built from the same form controls as
   the real logging form so the real one is familiar the second time. */
.capex-ob-lede {
    font-size: 0.85rem;
    color: #6b7280;
    margin-bottom: 18px;
}

.capex-ob-step {
    border: 1px dashed var(--hairline-strong);
    border-radius: 12px;
    background-color: #f8fafc;
    padding: 20px 22px;
    margin-bottom: 16px;
}

/* Step 2 before the reserve is accepted — visibly next, not yet actionable. */
.capex-ob-step-waiting {
    opacity: 0.55;
}

.capex-ob-head {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 6px;
}

.capex-ob-num {
    flex: 0 0 22px;
    height: 22px;
    border-radius: 999px;
    background: #111827;
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

.capex-ob-title {
    font-size: 0.98rem;
    font-weight: 600;
    color: #111827;
}

.capex-ob-done {
    font-size: 0.72rem;
    font-weight: 700;
    color: #16a34a;
}

.capex-ob-desc {
    font-size: 0.82rem;
    color: #6b7280;
    line-height: 1.5;
    margin-bottom: 14px;
    max-width: 620px;
}

/* "$2,500  =  [0.5] %" — the figure leads, the rate explains it. */
.capex-ob-figure-row {
    display: flex;
    align-items: flex-end;
    gap: 18px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.capex-ob-figure-label {
    font-size: 0.72rem;
    font-weight: 600;
    color: #6b7280;
}

.capex-ob-figure {
    font-size: 1.7rem;
    font-weight: 700;
    color: #111827;
    line-height: 1.15;
}

.capex-ob-eq {
    font-size: 1.1rem;
    color: #9ca3af;
    padding-bottom: 4px;
}

.expense-empty-wrap {
    display: flex;
    justify-content: center;
    padding: 40px 0;
}

.expense-empty-card {
    width: 100%;
    max-width: 360px;
    text-align: center;
    padding: 28px 24px;
    border: 1px dashed var(--hairline-strong);
    border-radius: 12px;
    background-color: #f8fafc;
}

.expense-empty-title {
    font-size: 1.05rem;
    font-weight: 600;
    color: #111827;
    margin-bottom: 4px;
}

.expense-empty-desc {
    font-size: 0.85rem;
    color: #6b7280;
    margin-bottom: 16px;
}

.expense-empty-value-box {
    max-width: 200px;
    margin: 0 auto;
}

.expense-empty-input {
    text-align: center;
    font-weight: 600;
    font-size: 1rem;
}

.expense-empty-hint {
    font-size: 0.76rem;
    color: #9ca3af;
    margin: 10px 0 4px;
}

/* ===== Login Page ===== */

.login-page {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background-color: #0f1117;
}

.login-card {
    background-color: #1a1d23;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 12px;
    padding: 40px 36px;
    width: 100%;
    max-width: 380px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
}

.login-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
}

.login-logo {
    width: 36px;
    height: 36px;
    object-fit: contain;
}

.login-brand-name {
    font-size: 1.4rem;
    font-weight: 700;
    color: #ffffff;
    letter-spacing: 0.02em;
}

.login-tagline {
    color: #6b7280;
    font-size: 0.82rem;
    margin-bottom: 0;
}

.login-divider {
    border-color: rgba(255, 255, 255, 0.08);
    margin: 20px 0 24px 0;
}

.login-btn {
    font-weight: 600;
    letter-spacing: 0.02em;
}

.login-error {
    margin-top: 10px;
    font-size: 0.84rem;
    color: #f87171;
    min-height: 20px;
}

/* ===== Sidebar Setup Checklist ===== */

.sidebar-onboarding-wrap {
    position: relative;
    padding: 0 8px 8px;
}
/* When the checklist is hidden (gated pages) the wrap holds only empty
   placeholders — collapse it so it doesn't leave a gap under the brand. */
.sidebar-onboarding-wrap:not(:has(.onboarding-panel)):not(:has(.onboarding-toast)) {
    padding: 0;
}

.onboarding-panel {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 10px;
    padding: 10px 10px 22px;
    margin-bottom: 4px;
}

.onboarding-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 6px;
}

.onboarding-title {
    font-size: 0.82rem;
    font-weight: 700;
    color: #e5e7eb;
}

.onboarding-count {
    font-size: 0.72rem;
    color: #9ca3af;
}

.onboarding-progress-track {
    height: 4px;
    background: rgba(255, 255, 255, 0.08);
    border-radius: 99px;
    overflow: hidden;
    margin-bottom: 10px;
}

.onboarding-progress-fill {
    height: 100%;
    background: #38bdf8;
    border-radius: 99px;
    transition: width 0.3s ease;
}

.onboarding-group-label {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #6b7280;
    margin: 6px 0 3px;
}

/* Fine-tuning collapses by default via native <details> — no JS needed */
.onboarding-tuning-group {
    margin: 6px 0 0;
}

.onboarding-group-summary {
    margin: 0;
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 4px;
}
.onboarding-group-summary::-webkit-details-marker { display: none; }
.onboarding-group-summary::before {
    content: "▼";
    font-size: 0.66rem;
}
.onboarding-tuning-group[open] > .onboarding-group-summary::before,
.onboarding-essentials-group[open] > .onboarding-group-summary::before {
    content: "▲";
}

.onboarding-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 0;
}

.onboarding-item-icon {
    font-size: 0.78rem;
    width: 14px;
    text-align: center;
    flex-shrink: 0;
}
.onboarding-icon-done { color: #22c55e; }
.onboarding-icon-empty { color: #38bdf8; }
.onboarding-icon-default { color: #6b7280; }

.onboarding-item-label {
    font-size: 0.76rem;
    color: #c9d1d9;
    flex: 1;
}
.onboarding-item-done .onboarding-item-label { color: #9ca3af; }

.onboarding-item-add {
    font-size: 0.7rem;
    color: #38bdf8 !important;
    text-decoration: none !important;
    font-weight: 600;
}
.onboarding-item-add:hover { color: #7dd3fc !important; }

/* Anchored to the checklist card's bottom-right corner, inset just inside
   its border so it reads as part of the card rather than a floating link.
   The offset accounts for .sidebar-onboarding-wrap's own bottom padding
   (8px) plus .onboarding-panel's margin-bottom (4px) — those sit *outside*
   the panel's border, so a naive small offset lands the button below the
   card instead of inside it. */
.onboarding-dismiss-btn {
    position: absolute;
    right: 16px;
    bottom: 18px;
    background: rgba(255, 255, 255, 0.05);
    border: none;
    border-radius: 5px;
    color: #6b7280;
    font-size: 0.65rem;
    padding: 2px 7px;
    cursor: pointer;
    width: auto;
    text-align: right;
}
.onboarding-dismiss-btn:hover { color: #9ca3af; background: rgba(255, 255, 255, 0.1); }

.onboarding-toast {
    font-size: 0.74rem;
    color: #9ca3af;
    padding: 10px 12px;
    margin-bottom: 12px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 10px;
}

.onboarding-restore-btn {
    background: none;
    border: 1px solid #d1d5db;
    color: #374151;
    font-size: 0.82rem;
    padding: 6px 14px;
    border-radius: 8px;
    cursor: pointer;
    margin-bottom: 12px;
}
.onboarding-restore-btn:hover { background: #f3f4f6; }

/* ===== Sidebar Footer (Sign Out) ===== */

.sidebar-footer {
    flex-shrink: 0;
    margin-top: 0;
    padding: 8px 8px 16px 8px;
}

/* Autosave status — pinned above the account divider, always visible. */
.sidebar-save-status {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 4px 16px 10px;
    font-size: 0.8rem;
    color: #9ca3af;
    opacity: 0.7;
}

.save-status-icon {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 17.58A5 5 0 0 0 18 8h-1.26A8 8 0 1 0 4 16.25'/%3E%3Cpolyline points='8 16 11 19 16 12'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 17.58A5 5 0 0 0 18 8h-1.26A8 8 0 1 0 4 16.25'/%3E%3Cpolyline points='8 16 11 19 16 12'/%3E%3C/svg%3E") center / contain no-repeat;
}

.save-status-label {
    line-height: 1;
}

.sidebar-save-status.saved-pulse {
    animation: savePulse 1.1s ease;
}

@keyframes savePulse {
    0%   { color: #34d399; opacity: 1; }
    35%  { color: #34d399; opacity: 1; }
    100% { color: #9ca3af; opacity: 0.7; }
}

.sidebar-account {
    color: #9ca3af;
    font-size: 0.9rem;
    padding: 10px 16px 4px;
    text-align: left;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.sidebar-signout {
    color: #6b7280 !important;
    font-size: 0.84rem !important;
}

/* Capital Performance — time metric strip below the hero chart */
/* Footer band inside the chart card: full-width divider bleeds to the card
   edges (cancelling the card's 24px/28px padding) so the strip reads as one
   object with the graph above it. */
.time-strip-footer {
    border-top: 1px solid #e5e7eb;
    margin: 18px -28px -24px;
    padding: 14px 28px 4px;
}

.time-strip {
    display: flex;
    align-items: stretch;
    gap: 22px;
}

.time-strip-col {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 0 0 auto;
}

/* Fixed to each column's worst-case content (e.g. "24 years ago",
   "−$50.4k/yr") so the strip never reflows while scrubbing the chart. */
.time-strip-col-viewing  { width: 70px; }
.time-strip-col-holding  { width: 90px; }
.time-strip-col-horizon  { width: 110px; }
.time-strip-col-value    { width: 100px; }

.time-strip-label {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #9ca3af;
    white-space: nowrap;
}

.time-strip-value {
    font-size: 1.05rem;
    font-weight: 700;
    color: #1f2937;
    line-height: 1.2;
    white-space: nowrap;
}

.time-strip-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background-color: #4338ca;
    margin-right: 8px;
    vertical-align: middle;
}

.time-strip-divider {
    width: 1px;
    background: #e5e7eb;
    margin: 2px 0;
}

/* Unify hover info boxes: dbc.Tooltip is dark by default, dbc.Popover (used for
   richer content — links, multi-line text) is light by default. Both are used
   for the same "ⓘ" hover pattern across KPI cards and inputs, so the popover
   is re-themed to match the tooltip's dark style rather than leaving the two
   inconsistent. */
.popover {
    --bs-popover-bg: #1a1d23;
    --bs-popover-border-color: #1a1d23;
    --bs-popover-header-bg: #1a1d23;
    --bs-popover-header-color: #f3f4f6;
    --bs-popover-body-color: #e5e7eb;
    --bs-popover-arrow-border: #1a1d23;
}

.popover .popover-body a {
    color: #a5b4fc;
}

/* Hide dcc.Slider's built-in numeric input box — we supply our own value boxes */
.dash-slider-container .dash-input-container,
.dash-slider-container input.dash-range-slider-input {
    display: none !important;
}

/* ===== Property Setup — financing row layout ===== */

.fin-row {
    display: flex;
    align-items: center;
    gap: 20px;
    margin-bottom: 6px;
    padding: 16px 18px;
    border-radius: 8px;
}
/* Subtle alternating bands so each major section reads as its own block */
.fin-row:nth-of-type(odd) {
    background-color: rgba(15, 23, 42, 0.04);
}
.fin-row:nth-of-type(even) {
    background-color: rgba(15, 23, 42, 0.015);
}
.fin-row-label {
    flex: 0 0 150px;
    font-size: 0.88rem;
    font-weight: 500;
    color: #374151;
}
.fin-row-mid {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0 6px;
}
.fin-row-right {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 12px;
}

/* Fixed-width slot for %/yr value-box; always present (empty for rows without one)
   so the equation columns align at the same X across all rows. */
.fin-val-slot {
    flex: 0 0 96px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
}

/* Fixed-width editable boxes so they line up down the right edge */
.fin-box-price {
    width: 150px;
}
.fin-box-dollar {
    width: 150px;
}
.fin-box-price .form-control,
.fin-box-dollar .form-control {
    text-align: right;
    font-weight: 600;
    color: #111827;
}
/* Editable dollar prefix — visible box, darker gray */
.fin-box-dollar.fin-input .input-group-text {
    color: #4b5563;
    background-color: #e9ecef;
    font-weight: 600;
}
/* Calculated/disabled dollar prefix — no box, just a plain $ */
.fin-box-dollar:not(.fin-input) .input-group-text {
    background-color: transparent;
    border-color: transparent;
    color: #9ca3af;
    font-weight: 400;
    padding-left: 6px;
    padding-right: 2px;
}

/* ===== Property Setup — financing controls ===== */

/* Compact editable readout box on the right end of each slider */
.value-box {
    max-width: 92px;
}
.value-box .value-box-input {
    text-align: center;
    font-weight: 600;
    color: #111827;
    padding-left: 6px;
    padding-right: 6px;
}
.value-box .input-group-text {
    color: #4b5563;
    background-color: #e9ecef;
    font-weight: 600;
    padding-left: 8px;
    padding-right: 8px;
}

/* Vertical loan + down = purchase equation (down payment row) */
.fin-equation-stack {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.fin-eq-row {
    display: flex;
    align-items: center;
    gap: 0;
}
.fin-eq-op {
    flex: 0 0 20px;
    text-align: center;
    color: #9ca3af;
    font-weight: 700;
}
.fin-eq-cap {
    flex: 0 0 100px;
    margin-left: 8px;
    font-size: 0.72rem;
    color: #9ca3af;
    white-space: nowrap;
    overflow: hidden;
}
.fin-eq-sum-row {
    padding-top: 6px;
    border-top: 1.5px solid #d1d5db;
    margin-top: 1px;
}
.fin-box-dollar .form-control:disabled {
    background-color: #f9fafb;
    color: #374151;
    opacity: 1;
}

/* Purchase Date sits on the left of the Purchase Price row */
.fin-date-left {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}
.fin-date-label {
    font-size: 0.88rem;
    font-weight: 500;
    color: #374151;
    margin: 0;
    white-space: nowrap;
}
.fin-date-input {
    max-width: 180px;
}
.fin-price-label {
    font-size: 0.88rem;
    font-weight: 500;
    color: #374151;
    white-space: nowrap;
}

/* Property Configuration — units evenly span the full box width */
.unit-line {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    align-items: end;
    gap: 24px;
    margin-top: 8px;
}
.unit-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    min-width: 0;
}
.unit-line-label,
.unit-cell .unit-grid-label,
.unit-cell label {
    font-size: 0.82rem;
    font-weight: 500;
    color: #374151;
    margin: 0;
    white-space: nowrap;
}
.unit-cell label.disabled {
    color: #c0c5cd;
}
/* The redesign distributes width via the even grid columns, not by bloating
   any single control — each stays a modest size, centered in its column. */
.unit-count-dd {
    width: 180px;
}
.unit-name-input {
    width: 110px;
    text-align: center;
}

/* Tax Assumptions — Federal/State matrix; value columns flex to fill the box */
.tax-grid {
    display: grid;
    grid-template-columns: max-content 1fr 1fr;
    column-gap: 16px;
    row-gap: 10px;
    align-items: center;
}
/* Federal/State headers and value cells center within their flexible column */
.tax-grid-head:not(:first-child),
.tax-grid > .tax-cell {
    justify-self: center;
}
.tax-grid-head {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6b7280;
    text-align: center;
}
.tax-grid-label {
    font-size: 0.88rem;
    font-weight: 500;
    color: #374151;
    margin: 0;
    white-space: nowrap;
}
.tax-cell {
    display: flex;
    align-items: center;
    gap: 6px;
}
.tax-info-icon {
    color: #9ca3af;
    cursor: help;
    font-size: 0.8rem;
}

/* Disabled-state explainer (100% down → no mortgage) */
.slider-note {
    font-size: 0.78rem;
    color: #b45309;
    font-style: italic;
    margin-top: 6px;
    min-height: 1rem;
}

/* ── 10-K statement grid ──────────────────────────────────── */
.tk-statement-grid .tk-label-cell {
    font-weight: 600;
    color: #374151;
}
.tk-statement-grid .ag-row.tk-row-subtotal {
    font-weight: 700;
    background: #f8fafc;
    border-top: 1px solid #e5e7eb;
}
.tk-statement-grid .ag-row.tk-row-total {
    font-weight: 800;
    background: #fef3c7;
    border-top: 2px solid #f59e0b;
    border-bottom: 2px solid #f59e0b;
}
.tk-statement-grid .ag-row.tk-row-return {
    background: #eef2ff;
    color: #4338ca;
}
.tk-statement-grid .ag-row.tk-row-driver {
    color: #94a3b8;
    font-style: italic;
    font-size: 0.82rem;
}
.tk-statement-grid .ag-row.tk-row-signal {
    font-size: 0.82rem;
    font-weight: 500;
}
/* Blank separator between major sections — no border, no hover, not clickable. */
.tk-statement-grid .ag-row.tk-row-spacer,
.tk-statement-grid .ag-row.tk-row-spacer .ag-cell {
    background: transparent !important;
    border: none !important;
    cursor: default !important;
}
.tk-statement-grid .ag-row.tk-row-child .tk-label-cell {
    padding-left: 26px;
    font-weight: 400;
    color: #6b7280;
}
.tk-statement-grid .ag-cell {
    cursor: pointer;
}
/* ── Investment disclaimer box ─────────────────────────────────── */
.tk-disclaimer {
    margin-top: 24px;
    padding: 14px 18px;
    border: 1px solid #e5e7eb;
    border-left: 3px solid #d1d5db;
    border-radius: 6px;
    background: #f9fafb;
}
.tk-disc-heading {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #9ca3af;
    margin-bottom: 8px;
}
.tk-disc-list {
    margin: 0;
    padding-left: 18px;
    list-style: disc;
}
.tk-disc-list li {
    font-size: 0.75rem;
    color: #6b7280;
    margin-bottom: 4px;
    line-height: 1.5;
}
.tk-disc-title {
    font-weight: 600;
    color: #4b5563;
}
/* Current-year column tint ("Highlight Today" toggle). Semi-transparent so row
   backgrounds (subtotal/total) show through; click-to-explain inline styles win. */
.tk-statement-grid .ag-cell.tk-col-today {
    background-color: rgba(13, 148, 136, 0.07);
}
.tk-statement-grid .ag-header-cell.tk-col-today-header {
    background-color: rgba(13, 148, 136, 0.10);
}

/* Column-marker legend (shown below slicers when markers are present). */
.tk-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 2px;
}
.tk-legend-item {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.75rem;
    color: #6b7280;
}
.tk-legend-star {
    color: #b45309;
    font-weight: 700;
    font-size: 0.9rem;
    flex-shrink: 0;
}

/* First-sell optimal year column (amber accent, distinct from teal "today"). */
.tk-statement-grid .ag-cell.tk-col-sell {
    background-color: rgba(245, 158, 11, 0.08);
}
.tk-statement-grid .ag-header-cell.tk-col-sell-header {
    background-color: rgba(245, 158, 11, 0.15);
    font-weight: 700;
}

/* ── 10-K sticky header + formula explainer (Phase 3) ─────────── */
.tk-sticky-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: #fff;
    padding: 8px 0 10px;
    border-bottom: 1px solid #eef2f7;
    margin-bottom: 8px;
}
.tk-header-flex {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 20px;
    flex-wrap: wrap;
}
.tk-explainer {
    flex: 1 1 420px;
    min-width: 360px;
    max-width: 680px;
    height: 172px;             /* fixed — never resizes with the equation */
    position: relative;
    text-align: left;          /* equations & detail are left-justified */
    border: 1px solid #e5e7eb;
    border-radius: 10px;
    padding: 12px 16px 16px;
    background: #fafafa;
    overflow-y: auto;          /* scroll long explanations instead of clipping */
}
.tk-explainer-head {
    position: absolute;        /* pinned to the top-right corner (equation shown) */
    top: 10px;
    right: 16px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #9ca3af;
}
/* Idle state — title + prompt centered both ways */
.tk-explainer-idle {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px;
    text-align: center;
}
.tk-explainer-head-center {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #9ca3af;
}
.tk-idle-hint {
    color: #9ca3af;
    font-size: 0.9rem;
}
.tk-eq-title { font-weight: 700; color: #111827; }
.tk-eq-year { color: #6b7280; font-weight: 600; }
.tk-eq-formula { color: #6b7280; font-size: 0.8rem; margin-bottom: 6px; }
.tk-eq-line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px;
    font-size: 0.95rem;
    font-variant-numeric: tabular-nums;
}
.tk-eq-chip { padding: 1px 7px; border-radius: 5px; font-weight: 700; }
.tk-eq-op { color: #6b7280; font-weight: 600; }
.tk-eq-result { font-weight: 800; color: #111827; }
.tk-eq-muted { color: #9ca3af; font-style: italic; }
.tk-eq-source {
    margin-top: 6px;
    font-size: 0.75rem;
    color: #9ca3af;
}
.tk-eq-link {
    display: inline-block;
    margin-top: 6px;
    font-size: 0.75rem;
    font-weight: 600;
    color: #2563eb;
}
.tk-eq-link:hover { text-decoration: underline; }
.tk-eq-warn {
    margin-top: 8px;
    font-size: 0.8rem;
    font-weight: 600;
    color: #b45309;
}

/* CSS fraction — numerator stacked over a bar over denominator */
.tk-frac {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    vertical-align: middle;
    margin: 0 4px;
}
.tk-frac-num {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 0 6px 3px;
}
.tk-frac-den {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px 6px 0;
    border-top: 2px solid #374151;
}

/* ===== Rent Health & Target (Property Performance bottom section) ===== */
.rt-section {
    margin-top: 2.5rem;
    padding-top: 1.75rem;
    border-top: 1px solid #e5e7eb;
}

.rt-section-title {
    font-size: 1.15rem;
    font-weight: 600;
    color: #111827;
    margin-bottom: 0.15rem;
}

.rt-section-subtitle {
    font-size: 0.9rem;
    color: #6b7280;
    margin-bottom: 1.25rem;
}

.rt-panel {
    background: #ffffff;
    border: 1px solid #e5e7eb;
    border-radius: 12px;
    padding: 1rem 1.15rem;
    height: 100%;
}

.rt-panel-label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #9ca3af;
    margin-bottom: 0.1rem;
}

.rt-panel-title {
    font-size: 1rem;
    font-weight: 500;
    color: #111827;
    margin-bottom: 0.75rem;
}

.rt-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-bottom: 0.35rem;
}

.rt-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    color: #6b7280;
}

.rt-swatch {
    display: inline-block;
    width: 12px;
    height: 2.5px;
    border-radius: 2px;
}

.rt-swatch-rent { background: #2a78d6; }
.rt-swatch-expense { background: #D85A30; }
.rt-swatch-required { background: #BA7517; }
.rt-swatch-breakeven { background: #888780; }

.rt-chart-note {
    font-size: 0.72rem;
    line-height: 1.35;
    color: #9ca3af;
    margin-top: 0.25rem;
}

.rt-cards-row {
    display: grid;
    gap: 10px;
    margin-top: 0.5rem;
}

.rt-cards-2 { grid-template-columns: 1fr 1fr; }
.rt-cards-3 { grid-template-columns: 1fr 1fr 1fr; }

.rt-target-badge {
    display: inline-flex;
    align-items: center;
    padding: 6px 16px;
    font-size: 0.82rem;
    font-weight: 500;
    color: #1d4ed8;
    background: #eff6ff;
    border-radius: 999px;
    white-space: nowrap;
}

.rt-card {
    background: #f8f9fa;
    border-radius: 8px;
    padding: 0.6rem 0.75rem;
    text-align: center;
}

.rt-card-accent {
    background: #eff6ff;
}

.rt-card-label {
    font-size: 0.72rem;
    color: #6b7280;
    margin-bottom: 0.1rem;
}

.rt-card-accent .rt-card-label {
    color: #1d4ed8;
}

.rt-card-value {
    font-size: 1.05rem;
    font-weight: 600;
    color: #111827;
}

.rt-card-accent .rt-card-value {
    color: #1d4ed8;
}

.rt-sensitivity-wrap {
    background: #f8f9fa;
    border-radius: 12px;
    padding: 0.9rem 1.1rem;
    margin-top: 1rem;
}

.rt-sensitivity-intro {
    font-size: 0.85rem;
    color: #6b7280;
    margin-bottom: 0.85rem;
}

.rt-sensitivity-table {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    font-size: 0.8rem;
    text-align: center;
}

.rt-sensitivity-table th,
.rt-sensitivity-table td {
    padding: 5px 4px;
}

.rt-row-label {
    text-align: left !important;
    color: #6b7280;
    width: 100px;
    font-weight: 500;
    white-space: nowrap;
}

.rt-col-head {
    font-weight: 400;
    color: #9ca3af;
}

.rt-col-current {
    font-weight: 600;
    color: #111827;
}

.rt-col-breakeven {
    background: #fef3e2;
    font-weight: 500;
}

.rt-col-target {
    background: #eff6ff;
    color: #1d4ed8;
    font-weight: 600;
}

.rt-col-head.rt-col-breakeven { color: #854d0e; }

.rt-coc-up { color: #0f6e56; }
.rt-coc-down { color: #993c1d; }


/* ===== CapEx replacement calendar (Phase A) ============================== */
.capex-cal { border: 1px solid var(--hairline); border-radius: 12px; overflow: hidden;
  background: #fff; }
.capex-cal-scroll { max-height: 640px; overflow: auto; }
.capex-cal-head { display: flex; position: sticky; top: 0; z-index: 6;
  background: #fff; min-width: max-content; border-bottom: 1px solid var(--hairline-strong); }
.capex-cal-corner { position: sticky; left: 0; z-index: 8; background: #fff; }
.capex-cal-gutter { width: 96px; flex: 0 0 96px; position: sticky; left: 0;
  z-index: 4; background: #fff; border-right: 1px solid var(--hairline-strong); }
.capex-cal-gutterhead { padding: 8px; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .05em; color: #94a3b8; font-weight: 600; display: flex;
  justify-content: space-between; }
.capex-cal-cols { display: flex; }
.capex-cal-colhead { width: 104px; flex: 0 0 104px; padding: 8px;
  border-right: 1px solid var(--hairline); text-align: left; min-height: 66px;
  display: flex; flex-direction: column; justify-content: space-between; }
.capex-cal-colhead > :first-child { align-self: flex-start; }
.capex-cal-colhead > :last-child { align-self: flex-start; margin-top: auto; }
.capex-cal-cat { font-size: 12.5px; font-weight: 600; line-height: 1.15; color: #1e293b; }
.capex-cal-unitplain { font-size: 11px; color: #94a3b8; font-weight: 600; margin-top: 5px; }
.capex-cal-pill { display: inline-block; font-size: 11px; font-weight: 600;
  padding: 2px 9px; border-radius: 20px; color: #fff; }
.capex-cal-catpill { font-size: 12px; line-height: 1.15; }
.capex-cal-gridrow { display: flex; min-width: max-content; }
.capex-cal-col { width: 104px; flex: 0 0 104px; border-right: 1px solid var(--hairline); }
.capex-cal-lane { position: relative; }
.capex-cal-yearcell { position: relative; overflow: hidden; border-bottom: 1px solid var(--hairline);
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: 2px 8px 0 8px; font-size: 11px; font-variant-numeric: tabular-nums; }
.capex-cal-yr { color: #475569; }
.capex-cal-amt { font-size: 10.5px; color: #94a3b8; position: relative; z-index: 2; }
/* Reserve inputs integrated at the bottom of the CapEx chart card */
.capex-reserve-controls {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 14px;
    padding-top: 16px;
    border-top: 1px solid var(--hairline);
}

.capex-cal-yearcell.dense .capex-cal-amt { color: #f59e0b; font-weight: 700; }
.capex-cal-yearcell.current { background: #fff5e6; }
.capex-cal-yearcell.current .capex-cal-yr { color: #f59e0b; font-weight: 700; }
.capex-cal-spendbar { position: absolute; right: 0; bottom: 3px; height: 4px;
  background: #f59e0b; opacity: .45; border-radius: 2px; z-index: 1; }
.capex-cal-curband { position: absolute; left: 0; right: 0; background: #fff5e6; z-index: 0; }
/* Click-to-latch year highlight (one at a time). The rule is pointer-events:none
   and nothing changes block geometry, so drag/extend targets are unaffected. */
.capex-cal-yearcell[data-year] { cursor: pointer; }
.capex-cal-yearcell.capex-cal-yearsel { background: #eef2ff; }
.capex-cal-yearcell.capex-cal-yearsel .capex-cal-yr { color: #4f46e5; font-weight: 700; }
.capex-cal-selline { position: absolute; left: 0; right: 0; height: 2px;
  background: #4f46e5; pointer-events: none; z-index: 5; }
/* Hover preview of the rule a click would commit — dashed and faint so it reads
   as "not yet", and pointer-events:none so it never eats a click on a block. */
.capex-cal-hovline { position: absolute; left: 0; right: 0; height: 0;
  border-top: 2px dashed rgba(79, 70, 229, 0.45); pointer-events: none;
  z-index: 4; display: none; }
.capex-cal-yearcell.capex-cal-yearhover { background: #f5f6ff; }
.capex-cal-yearcell.capex-cal-yearhover .capex-cal-yr { color: #4f46e5; }

/* Basis line under the Add-a-Lease rent field. */
.rent-suggest-caption {
    font-size: 0.75rem;
    color: #6b7280;
    margin-top: 6px;
}
.rent-suggest-info { color: #9ca3af; cursor: help; }

/* One-time hint that the year rail is clickable (touch users get no hover). */
.capex-tip {
    display: flex;
    align-items: center;
    gap: 9px;
    background: #eef2ff;
    border: 1px solid #c7d2fe;
    border-radius: 8px;
    padding: 8px 10px;
    margin-bottom: 12px;
}
.capex-tip-badge {
    flex: 0 0 auto;
    background: #4f46e5;
    color: #fff;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    border-radius: 999px;
    padding: 2px 8px;
}
.capex-tip-text { font-size: 0.8rem; color: #3730a3; line-height: 1.4; }
.capex-tip-x {
    margin-left: auto;
    flex: 0 0 auto;
    background: transparent;
    border: none;
    color: #6366f1;
    font-size: 0.85rem;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
}
.capex-tip-x:hover { color: #3730a3; }
/* Blocks outside the latched year invert: white fill, own color as ink + border.
   --blk-fill is set from the block's data-fill (the true hue, not a faded rgba). */
.capex-cal-blk.capex-cal-dim {
    background: #ffffff !important;
    color: var(--blk-fill) !important;
    border-color: var(--blk-fill) !important;
    text-shadow: none;
}
.capex-cal-blk { position: absolute; left: 5px; right: 5px; border-radius: 6px;
  overflow: hidden; padding: 5px 7px 4px; font-size: 10.5px; line-height: 1.25;
  display: flex; flex-direction: column; justify-content: space-between; }
.capex-cal-blk.future { color: #fff; }
.capex-cal-blk.active { color: #1e293b; }
.capex-cal-blk.b-over { border: 3.5px solid #0f172a; }
.capex-cal-blk.b-dash { border: 2.5px dashed #334155; }
.capex-cal-blk.b-solid { border: 1px solid rgba(15,23,42,.14); }
.capex-cal-btop { display: flex; flex-direction: column; }
.capex-cal-bt { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.capex-cal-bprice { font-weight: 600; opacity: .9; }
.capex-cal-bbot { display: flex; flex-direction: column; }
.capex-cal-byr { font-variant-numeric: tabular-nums; font-weight: 600; }
.capex-cal-blife, .capex-cal-bact { opacity: .82; font-size: 10px; }
.capex-cal-bact { font-weight: 600; opacity: .95; }

/* ----- CapEx calendar toolbar + legend (prototype styling) --------------- */
.capex-cal-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding: 10px 12px; background: #f8fafc; border: 1px solid var(--hairline);
  border-radius: 10px; margin-bottom: 12px; }
.capex-cal-tgroup { display: flex; align-items: center; gap: 8px; }
.capex-cal-tlabel { font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: #94a3b8; font-weight: 600; }
/* Icon role. Stays bespoke (a 30px square is not a text button) but tracks the
   6px control radius and the surface tokens. */
.capex-zoom-btn.btn { width: 30px; height: 30px; padding: 0; border-radius: 6px;
  border: 1px solid var(--hairline-strong); background: var(--card); color: var(--ink); font-size: 16px;
  line-height: 1; margin-left: 6px; box-shadow: none; }
.capex-zoom-btn.btn:hover { background: var(--card-sunken); color: var(--ink); }
.capex-cal-legend { display: flex; flex-wrap: wrap; gap: 14px; margin: 0 2px 12px;
  font-size: 12px; color: #475569; }
.capex-cal-legitem { display: inline-flex; align-items: center; gap: 6px; }
.capex-cal-sw { width: 26px; height: 13px; border-radius: 3px; background: #eef2f7;
  display: inline-block; box-sizing: border-box; }
.capex-cal-sw.sw-dash { border: 1.5px dashed #334155; }
.capex-cal-sw.sw-solid { border: 1px solid #cbd5e1; }
.capex-cal-sw.sw-over { border: 2.5px solid #0f172a; }
.capex-cal-legnote { color: #94a3b8; }

.capex-cal-blk { cursor: pointer; transition: box-shadow .12s ease, transform .12s ease; }
.capex-cal-blk:hover { box-shadow: 0 2px 8px rgba(15,23,42,.22); z-index: 3; }

.capex-cal-blk { user-select: none; -webkit-user-select: none; }
.capex-cal-blk:hover { cursor: grab; }

/* Repositioning the whole bar — a bigger, more obvious lift than hover. */
.capex-cal-blk.capex-cal-moving {
    box-shadow: 0 12px 28px rgba(15,23,42,.4);
    transform: scale(1.05);
    z-index: 6;
    cursor: grabbing;
}

/* ----- CapEx "Not planned" strip (under the calendar) ------------------- */
.np-strip {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 14px;
    padding-top: 16px;
    border-top: 1px solid var(--hairline);
}
.np-strip-label {
    flex: 0 0 auto;
    line-height: 26px;   /* == chip height, so it centers on the first chip row */
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #b45309;
    white-space: nowrap;
}
.np-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    flex: 1 1 auto;
}
.np-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 9px;
    background: #fef3c7;
    border: 1px dashed #d97706;
    border-radius: 8px;
}
.np-chip-name {
    font-size: 0.8rem;
    font-weight: 600;
    color: #b45309;
    white-space: nowrap;
}
.np-chip-badges { display: inline-flex; gap: 5px; }
.np-chip-badge {
    font-size: 0.72rem;
    font-weight: 600;
    color: #92400e;
    background: #ffffff;
    border: 1px solid #fcd34d;
    border-radius: 5px;
    padding: 1px 7px;
    cursor: pointer;
    transition: background .1s ease, border-color .1s ease;
}
.np-chip-badge:hover { background: #d97706; border-color: #d97706; color: #ffffff; }
.np-chip-more {
    font-size: 0.72rem;
    font-weight: 600;
    color: #92400e;
    padding: 1px 4px;
    align-self: center;
}

/* ----- CapEx calendar: resize handle + legend row 2 --------------------- */
.capex-cal-resize { position: absolute; left: 0; right: 0; bottom: 0; height: 9px;
  cursor: ns-resize; z-index: 4; }
.capex-cal-legend.capex-cal-legend-color { margin-top: 6px; }

/* ----- CapEx calendar: re-sort (refresh) button ------------------------- */
.capex-cal-refresh.btn { font-size: 12px; padding: 5px 12px; border-radius: 6px;
  border: 1px solid #fca5a5; background: #fef2f2; color: #b91c1c;
  box-shadow: none; white-space: nowrap; font-weight: 600; }
.capex-cal-refresh.btn:hover { background: #fee2e2; color: #991b1b;
  border-color: #f87171; }

/* ---- Catch-All method toggle (Simple vs Advanced) ---- */
.ca-mode-bar { display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; }
.ca-mode-copy { max-width: 70%; }
.ca-mode-title { font-weight: 700; font-size: 0.95rem; color: #1f2937;
  margin-bottom: 3px; }
.ca-mode-desc { font-size: 0.8rem; color: #6b7280; line-height: 1.4; }
/* Stacked rather than inline: at 340px the wide control is too big to sit
   beside its label without the label reading as a stray word. */
.ca-mode-switch { display: flex; flex-direction: column; align-items: flex-start;
  gap: 6px; flex-shrink: 0; }
.ca-mode-switch-label { font-size: 0.78rem; font-weight: 600; color: #6b7280;
  text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }
/* Inline caveat — carries the same warning as the old full-width Alert without
   claiming the same visual weight. */
.ca-mode-warn { display: flex; gap: 6px; margin-top: 6px; font-size: 0.75rem;
  line-height: 1.35; color: #92400e; }
.ca-mode-warn-icon { flex-shrink: 0; color: #d97706; font-size: 0.8rem;
  line-height: 1.3; }

/* ===== Tax Profile — heading row with inline action ===== */

/* The hairline normally belongs to .section-heading. When a button shares the
   header line, the border moves up to this wrapper so both sit above it. */
.section-heading-row {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 20px;
    padding-bottom: 10px;
    border-bottom: 1px solid #e5e7eb;
}

.section-heading-row .section-heading {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

/* margin-left rather than justify-content, so the button stays pinned right
   even if the header later gains a third element (badge, subtext). */
.section-heading-row .tax-reset-btn {
    margin-left: auto;
}

/* Filled variant of .onboarding-restore-btn — same radius and geometry, but
   solid so it reads as an action rather than a link. #111827 is the same
   accent the segmented toggles use for their active state. */
.tax-reset-btn {
    background: #111827;
    border: 1px solid #111827;
    color: #ffffff;
    font-size: 0.9rem;
    font-weight: 500;
    padding: 5px 18px;
    border-radius: 8px;
    cursor: pointer;
    line-height: 1.4;
}

.tax-reset-btn:hover,
.tax-reset-btn:focus {
    background: #1f2937;
    border-color: #1f2937;
    color: #ffffff;
}

/* Reserve three lines so switching states never resizes the panel. Notes are
   capped at ~140 chars (see config/state_tax.py) to fit this box. */
#setup-tax-notes {
    min-height: 3.4rem;
}

/* ===== KPI band card (thermometer replacement) ===== */
.thermo-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    min-height: 1.9rem;
}

.thermo-eyebrow,
.thermo-scope {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.6px;
    color: #8a94a6;
}

.thermo-eyebrow {
    text-transform: uppercase;
}

.thermo-scope {
    white-space: nowrap;
    flex: none;
}

.thermo-numrow {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: 2px;
}

.thermo-metric {
    font-size: 1.9rem;
    font-weight: 700;
    line-height: 2.05rem;
    letter-spacing: -0.4px;
    font-variant-numeric: tabular-nums;
    color: #101828;
}

.thermo-vs {
    font-size: 0.78rem;
    color: #8a94a6;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Tightened against the headline; the breathing room is spent below instead,
   so the pill's tail clears the actual marker rather than hiding behind it. */
.thermo {
    position: relative;
    margin-top: 1.05rem;
}

.thermo-pillrow {
    position: relative;
    height: 34px;
}

.thermo-pill {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
    border-radius: 999px;
    padding: 5px 15px;
    font-size: 0.85rem;
    font-weight: 700;
    line-height: 1.15rem;
    white-space: nowrap;
}

.thermo-tail {
    position: absolute;
    bottom: 2px;
    transform: translateX(-50%);
    width: 0;
    height: 0;
    border-left: 6px solid transparent;
    border-right: 6px solid transparent;
}

.thermo-pill--good { background: #e6f4ea; color: #137333; }
.thermo-pill--okay { background: #fef7e0; color: #b06000; }
.thermo-pill--bad  { background: #fce8e6; color: #c5221f; }

.thermo-tail--good { border-top: 6px solid #e6f4ea; }
.thermo-tail--okay { border-top: 6px solid #fef7e0; }
.thermo-tail--bad  { border-top: 6px solid #fce8e6; }

/* 10px of clearance below the tail so the actual marker's white ring can
   never overlap the tail tip. */
.thermo-track {
    position: relative;
    height: 6px;
    margin-top: 10px;
}

.thermo-seg {
    position: absolute;
    top: 0;
    height: 6px;
    border-radius: 999px;
}

.thermo-seg--good { background: #34a853; }
.thermo-seg--okay { background: #fbbc04; }
.thermo-seg--bad  { background: #ea4335; }

.thermo-mark-actual {
    position: absolute;
    top: 50%;
    width: 15px;
    height: 15px;
    border-radius: 999px;
    background: #ffffff;
    border: 3px solid #101828;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 0 2px #ffffff;
    z-index: 3;
}

.thermo-mark-actual--projected {
    border-style: dashed;
    border-color: #5b6273;
}

.thermo-mark-assumption {
    position: absolute;
    top: 50%;
    width: 3px;
    height: 15px;
    border-radius: 1.5px;
    background: #1a3e7a;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 0 2px #ffffff;
    z-index: 2;
}

.thermo-axis {
    position: relative;
    height: 15px;
    margin-top: 8px;
}

.thermo-axlab {
    position: absolute;
    transform: translateX(-50%);
    font-size: 0.6875rem;
    line-height: 15px;
    color: #8a94a6;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.thermo-legend {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 20px;
    margin-top: 14px;
}

.thermo-key {
    display: flex;
    align-items: center;
    gap: 7px;
}

.thermo-key-actual {
    width: 12px;
    height: 12px;
    border-radius: 999px;
    background: #ffffff;
    border: 2.5px solid #101828;
    flex: none;
}

.thermo-key-actual--projected {
    border-style: dashed;
    border-color: #5b6273;
}

.thermo-key-assumption {
    width: 3px;
    height: 13px;
    border-radius: 1.5px;
    background: #1a3e7a;
    flex: none;
}

.thermo-key-label {
    font-size: 0.78rem;
    font-weight: 600;
    color: #1a3e7a;
    line-height: 13px;
}
