:root {
    --bg: #0d1015;
    --surface: #161a22;
    --surface-2: #1b2030;
    --border: rgba(255, 255, 255, 0.06);
    --border-strong: rgba(255, 255, 255, 0.12);
    --text: #e6e8ec;
    --muted: #8b93a1;
    --subtle: #5c6374;
    --portfolio: #60a5fa;
    --benchmark: #a78bfa;
    --positive: #22c55e;
    --negative: #ef4444;
    --warning: #f59e0b;
    --radius: 6px;
    --topbar-height: 104px;
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    color-scheme: dark;
}

body {
    min-height: 100vh;
    background: var(--bg);
    color: var(--text);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Arial, sans-serif;
    font-size: 14px;
    line-height: 1.45;
    font-variant-numeric: tabular-nums;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

button {
    font: inherit;
    color: inherit;
    cursor: pointer;
    background: transparent;
    border: none;
}

h1, h2, h3, h4 {
    font-weight: 600;
    letter-spacing: -0.01em;
}

/* ---------- Top bar ---------- */
.topbar {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
}

/* Intrinsic-flex layout so the topbar packs content naturally at every width:
 * brand and meta chips stay grouped on the left; controls sit to the right of
 * them if room exists, otherwise wrap to their own row. No grid + no
 * "1fr" columns pushing content to the opposite edge of empty space. */
.topbar-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 24px;
    padding: 10px 24px;
    max-width: 1440px;
    margin: 0 auto;
}

.topbar-brand {
    flex: 0 0 auto;
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-size: 13px;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.brand-mark {
    font-weight: 700;
    color: var(--text);
}

.brand-sep {
    color: var(--subtle);
}

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

.topbar-meta {
    /* Grow to fill remaining row-1 space; chips left-anchor next to the
     * brand. At widths where controls fit on row 1, this pushes controls to
     * the visual end of the row. At narrower widths controls wrap to row 2
     * and meta still sits left-anchored on row 1. */
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
}

.chip {
    display: inline-flex;
    align-items: center;
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    font-size: 12px;
    font-weight: 500;
}

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

.chip-referral {
    margin-left: auto;
    color: var(--portfolio);
    text-decoration: none;
    background: var(--surface-2);
    border-color: var(--border-strong);
    transition: color 0.12s ease, border-color 0.12s ease;
}

.chip-referral:hover {
    color: var(--text);
    border-color: var(--portfolio);
}

.topbar-controls {
    /* Wrap as a unit to the next row when the 4 groups don't fit alongside
     * brand + meta. On the fallback row the controls still sit left-aligned
     * and will wrap internally via the flex-wrap below and on .pill-group. */
    flex: 1 1 100%;
    display: flex;
    gap: 10px 16px;
    align-items: center;
    flex-wrap: wrap;
}

.control {
    display: flex;
    gap: 8px;
    align-items: center;
}

.control-stack {
    align-items: flex-start;
    flex-direction: column;
    gap: 4px;
}

.control-label {
    color: var(--subtle);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

.pill-group {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    padding: 2px;
}

.pill {
    padding: 4px 9px;
    border-radius: 4px;
    color: var(--muted);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.2;
    transition: color 0.12s ease, background 0.12s ease;
}

.pill:hover {
    color: var(--text);
    background: var(--surface-2);
}

.pill.active,
.pill[aria-pressed="true"] {
    color: var(--text);
    background: var(--surface-2);
    box-shadow: inset 0 0 0 1px var(--border-strong);
}

.pill:disabled {
    color: var(--subtle);
    background: transparent;
    box-shadow: none;
    cursor: not-allowed;
    opacity: 0.55;
}

.control-note {
    color: var(--warning);
    font-size: 11px;
    min-height: 1.2em;
}

/* ---------- Tabs ---------- */
.tabs {
    border-top: 1px solid var(--border);
}

.tabs-inner {
    display: flex;
    gap: 0;
    padding: 0 24px;
    /* Match the topbar-inner cap so the tab strip aligns with the brand /
     * meta / controls content above at wide viewports. Without this the
     * tabs run edge-to-edge while the topbar content is centered at 1440px,
     * creating a visible left-edge misalignment on >1440px monitors. */
    max-width: 1440px;
    margin: 0 auto;
}

.tab {
    padding: 10px 14px;
    color: var(--muted);
    font-size: 13px;
    font-weight: 500;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

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

.tab.active {
    color: var(--text);
    border-bottom-color: var(--portfolio);
}

/* ---------- Page & panels ---------- */
.page {
    max-width: 1440px;
    margin: 0 auto;
    padding: 20px 24px 40px;
}

.tab-panel {
    display: grid;
    gap: 16px;
}

.tab-panel[hidden] {
    display: none;
}

/* ---------- Cards ---------- */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px 16px;
}

.card-chart {
    padding-bottom: 14px;
}

.card-heatmap {
    display: flex;
    flex-direction: column;
}

.card-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 12px;
}

.card-head-action {
    align-items: center;
}

.card-head h3 {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.card-sub {
    color: var(--subtle);
    font-size: 12px;
}

.action-button {
    transition:
        border-color 0.12s ease,
        background 0.12s ease,
        color 0.12s ease;
}

.action-button:hover {
    border-color: var(--border-strong);
    background: var(--surface-2);
}

.action-button:disabled {
    color: var(--subtle);
    cursor: not-allowed;
    opacity: 0.6;
}

/* ---------- KPI row ---------- */
.kpi-row {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
}

.kpi {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
    display: grid;
    gap: 6px;
}

.kpi-label {
    color: var(--muted);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 500;
}

.kpi-value {
    font-size: 24px;
    font-weight: 600;
    letter-spacing: -0.02em;
}

.kpi-sub {
    color: var(--subtle);
    font-size: 12px;
}

/* ---------- Overview layout ---------- */
.overview-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 16px;
    /* align-items defaults to stretch so the right rail matches the left
     * card's height — lets the Exposure card grow to close the bottom gap
     * underneath Signals. */
}

.overview-rail {
    display: grid;
    gap: 16px;
    /* Signals sized to content; Exposure absorbs whatever vertical space
     * is left in the stretched rail, so both columns end on the same line
     * as the Equity Curve card. */
    grid-template-rows: auto 1fr;
}

.chart-wrap {
    position: relative;
    height: 280px;
}

.chart-wrap-tall {
    height: 420px;
}

/* ---------- Performance grid ---------- */
.chart-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
}

/* ---------- Signals ---------- */
.signal-stack {
    display: grid;
    gap: 6px;
}

.signal-badge {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2);
}

.signal-badge-main {
    display: flex;
    align-items: center;
    gap: 8px;
}

.signal-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--subtle);
    display: inline-block;
}

.signal-dot.Flat     { background: var(--subtle); }
.signal-dot.Moderate { background: var(--warning); }
.signal-dot.Strong   { background: var(--positive); }

.signal-name {
    font-weight: 500;
    font-size: 13px;
}

.signal-strength {
    color: var(--muted);
    font-size: 12px;
}

/* ---------- Exposure action + DL ---------- */
.exposure-action-row {
    display: flex;
    justify-content: center;
    padding: 6px 0 14px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 12px;
}

.exposure-action {
    font-size: 24px;
    font-weight: 700;
    letter-spacing: 0.12em;
    font-variant-numeric: tabular-nums;
}

.exposure-action-positive {
    color: var(--positive);
}

.exposure-action-negative {
    color: var(--negative);
}

.exposure-action-neutral {
    color: var(--muted);
}

.exposure-dl {
    display: grid;
    gap: 8px;
}

.exposure-dl > div {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
}

.exposure-dl > div:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.exposure-dl dt {
    color: var(--muted);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.exposure-dl dd {
    font-size: 15px;
    font-weight: 600;
}

/* ---------- Position-delta heatmap ---------- */
.heatmap-wrap {
    padding: 0;
    max-width: 100%;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* Belt-and-suspenders: the JS downsampler sizes the grid to fit, but
     * clip any 1-2px rounding overflow so the heatmap never bleeds past
     * the card edge. */
    overflow: hidden;
}

.heatmap-plot {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.heatmap-cal {
    display: grid;
    grid-auto-flow: column;
    /* Rows stretch to fill the plot height (Sun..Sat). Columns (weeks)
     * still share the container width evenly via minmax(0, 1fr), so the
     * grid fits without horizontal scroll regardless of the Window span. */
    grid-template-rows: repeat(7, minmax(0, 1fr));
    grid-auto-columns: minmax(0, 1fr);
    gap: 1px;
    font-variant-numeric: tabular-nums;
    width: 100%;
    flex: 1 1 auto;
    min-height: 0;
}

.heatmap-cell {
    min-width: 0;
    height: auto;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.03);
}

.heatmap-months {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 15px;
    gap: 0;
    color: var(--muted);
    font-size: 10px;
    margin-bottom: 4px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.heatmap-month-label {
    grid-row: 1;
    white-space: nowrap;
    padding-right: 4px;
}

.heatmap-legend {
    display: flex;
    gap: 6px;
    align-items: center;
    margin-top: 6px;
    color: var(--muted);
    font-size: 11px;
}

.heatmap-legend .heatmap-cell {
    width: 10px;
    min-width: 10px;
    height: 10px;
}

/* ---------- Metric groups ---------- */
.metric-groups {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
}

.metric-group {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px 16px;
}

.metric-group-head {
    margin-bottom: 12px;
}

.metric-group-head h3 {
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.metric-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

.metric-card {
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--bg);
}

.metric-label {
    color: var(--muted);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 4px;
}

.metric-value {
    font-size: 16px;
    font-weight: 600;
}

.metric-benchmark {
    color: var(--subtle);
    font-size: 11px;
    margin-top: 4px;
}

/* ---------- Tables ---------- */
.table-wrap {
    overflow-x: auto;
}

.table {
    width: 100%;
    border-collapse: collapse;
}

.table th,
.table td {
    padding: 8px 12px;
    text-align: right;
    font-size: 13px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

.table th:first-child,
.table td:first-child {
    text-align: left;
}

.table th {
    color: var(--muted);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 500;
    padding-top: 4px;
    padding-bottom: 6px;
}

.table tr:last-child td {
    border-bottom: none;
}

.table tbody tr:hover td {
    background: var(--surface-2);
}

.table-empty {
    padding: 16px;
    color: var(--subtle);
    text-align: center;
    font-size: 13px;
}

/* ---------- Heatmap ---------- */
.heatmap {
    width: 100%;
    border-collapse: separate;
    border-spacing: 3px;
}

.heatmap th,
.heatmap td {
    padding: 6px 4px;
    text-align: center;
    font-size: 12px;
    border-radius: 3px;
    white-space: nowrap;
}

.heatmap th {
    color: var(--muted);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 500;
    background: transparent;
}

.heatmap td {
    background: var(--bg);
}

.heatmap .year-label {
    background: transparent;
    color: var(--muted);
    font-weight: 600;
    text-align: left;
    padding-left: 8px;
}

/* ---------- Colors on values ---------- */
.positive { color: var(--positive); }
.negative { color: var(--negative); }
.neutral  { color: var(--text); }

/* ---------- States ---------- */
.state {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 32px;
    text-align: center;
    color: var(--muted);
}

.state h2 {
    font-size: 16px;
    color: var(--text);
    margin-bottom: 6px;
}

.state-error {
    border-color: rgba(239, 68, 68, 0.3);
}

.state-loading {
    display: grid;
    justify-items: center;
    gap: 2px;
}

/* Author-level display declarations (grid, flex, etc.) override the UA's
 * [hidden] { display: none } rule, so state panels that set display stay
 * visible even after el.hidden = true. Reinstate none with author weight. */
[hidden] {
    display: none !important;
}

.spinner {
    width: 32px;
    height: 32px;
    border: 2px solid var(--border-strong);
    border-top-color: var(--portfolio);
    border-radius: 50%;
    margin-bottom: 12px;
    animation: spin 0.8s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

@media (prefers-reduced-motion: reduce) {
    .spinner {
        animation-duration: 2s;
    }
}

/* ---------- Footer ---------- */
.footer {
    color: var(--subtle);
    font-size: 11px;
    padding: 12px 4px 0;
    border-top: 1px solid var(--border);
    margin-top: 8px;
    font-variant-numeric: tabular-nums;
}

/* ---------- Responsive ----------
 *
 * Topology notes:
 *   - The topbar layout is intrinsically responsive (grid-template-areas +
 *     flex-wrap on controls + flex-wrap on pill-groups). These media queries
 *     do NOT fight the topbar layout any more; they only tune content density
 *     (grids, font, padding, touch targets).
 *
 *   - Mobile-first defaults live in the base styles above; these max-width
 *     queries progressively tighten as the viewport shrinks.
 */

@media (max-width: 1100px) {
    .overview-grid {
        grid-template-columns: 1fr;
    }

    .chart-grid,
    .metric-groups {
        grid-template-columns: 1fr;
    }

    .kpi-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 780px) {
    .topbar-inner {
        padding: 10px 16px;
    }

    .tabs-inner {
        overflow-x: auto;
        padding: 0 12px;
        /* Hide the scrollbar — Chrome desktop shows it on hover, iOS Safari
         * shows a slim one during scroll. Tabs only need to hint scrollability,
         * not expose a persistent scrollbar. */
        scrollbar-width: none;
    }
    .tabs-inner::-webkit-scrollbar {
        display: none;
    }
    /* Stop tab labels from wrapping mid-word, which looks like a layout bug. */
    .tab {
        white-space: nowrap;
        flex-shrink: 0;
    }

    .page {
        padding: 16px 12px 32px;
    }

    .kpi-row {
        grid-template-columns: 1fr 1fr;
    }

    .metric-grid {
        grid-template-columns: 1fr;
    }
}

/* Narrow phone / very tight viewports (≤ ~560px): brand hides, meta takes the
 * full row 1 on its own. The grid flips to a single column so nothing has to
 * share horizontal space with the brand. */
@media (max-width: 560px) {
    .topbar-inner {
        grid-template-columns: 1fr;
        grid-template-areas:
            "meta"
            "controls";
    }
    .topbar-brand {
        display: none;
    }
    .topbar-meta {
        justify-content: flex-start;
    }
}

/* Phone portrait. Below this width the desktop-shrunken layout stops working:
 * charts get too short vertically, KPIs truncate their values, pills become
 * too small to tap, and the monthly-returns matrix has to reflow. */
@media (max-width: 480px) {
    body {
        /* 13px on small phones leaves more room for the tables + KPI numbers
         * without feeling tiny — iOS default body text on web is ~14–16px so
         * this still renders comfortably. */
        font-size: 13px;
    }

    .topbar-inner {
        padding: 10px 12px;
    }

    /* Brand is already hidden at ≤560px (see that breakpoint); no duplicate
     * rule needed here. */

    .topbar-meta {
        gap: 4px;
    }
    .chip {
        font-size: 11px;
        padding: 3px 8px;
    }

    .topbar-controls {
        gap: 8px 12px;
    }
    .control-label {
        /* Compact labels so the Asset / Leverage / Window / Scale rows don't
         * push controls onto too many vertical rows. */
        font-size: 10px;
    }

    /* Bigger tap targets on all pills. Apple HIG recommends ≥44pt; Google
     * Material ≥48dp. 38px interior + 2+2 pill-group padding puts the total
     * group at ~42px which is within the acceptable range. The desktop rules
     * at 4px/9px padding stay untouched — this only fires on phone. */
    .pill {
        padding: 9px 12px;
        font-size: 13px;
    }
    .pill-group {
        gap: 4px;
    }

    .page {
        padding: 12px 10px 28px;
    }

    .tab {
        padding: 12px 14px;
        font-size: 13px;
    }

    /* KPIs: single column on phone, tighter padding so the value number
     * (often 4–6 digits for CAGR or 7+ for balance) stays on one line. */
    .kpi-row {
        grid-template-columns: 1fr;
        gap: 8px;
    }
    .kpi {
        padding: 10px 12px;
        grid-template-columns: auto 1fr;
        grid-template-areas:
            "label value"
            "sub   sub";
        align-items: baseline;
        gap: 4px 10px;
    }
    .kpi-label {
        grid-area: label;
    }
    .kpi-value {
        grid-area: value;
        font-size: 20px;
        text-align: right;
    }
    .kpi-sub {
        grid-area: sub;
    }

    /* Charts: taller than a 1:1 square would suggest so axis labels get room,
     * but shorter than desktop so users don't have to swipe three screens to
     * see the controls again. */
    .chart-wrap {
        height: 240px;
    }
    .chart-wrap-tall {
        height: 280px;
    }

    /* Signals card: tighter vertical rhythm. */
    .signal-stack {
        gap: 6px;
    }

    /* Monthly-returns matrix reflow: card-per-year with each month's value
     * labeled inline. The desktop heatmap's 13-column grid (Year + 12 months)
     * would be unreadable at phone widths; at 480px and below each year row
     * becomes its own card with 3-column month/value pairs inside. Driven by
     * data-month attributes set in renderHeatCell() so CSS doesn't have to
     * use :nth-child positioning. */
    .monthly-returns-wrap {
        overflow-x: visible;
    }
    .monthly-returns {
        border-spacing: 0;
        display: block;
    }
    .monthly-returns thead {
        display: none;
    }
    .monthly-returns tbody {
        display: block;
    }
    .monthly-returns tr {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 6px 8px;
        background: var(--surface-2);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        padding: 10px 12px;
        margin-bottom: 10px;
    }
    .monthly-returns tr:last-child {
        margin-bottom: 0;
    }
    .monthly-returns td {
        padding: 4px 8px;
        border-radius: 4px;
        font-size: 12px;
        text-align: left;
        white-space: nowrap;
    }
    .monthly-returns td.year-label {
        grid-column: 1 / -1;
        background: transparent !important;
        color: var(--muted);
        font-weight: 700;
        font-size: 13px;
        padding: 0 0 2px;
        border-bottom: 1px solid var(--border);
        margin-bottom: 2px;
    }
    .monthly-returns td:not(.year-label)::before {
        content: attr(data-month);
        display: inline-block;
        min-width: 28px;
        color: inherit;
        opacity: 0.7;
        font-weight: 500;
        margin-right: 6px;
    }
    /* Suppress the muted "·" placeholder on pre-history / future months —
     * cleaner than showing empty cells in the reflowed layout. */
    .monthly-returns td.heat-empty {
        display: none;
    }

    /* Footer: allow wrapping and use a subtle separator, not the 11px desktop
     * single-line treatment. */
    .footer {
        font-size: 11px;
        line-height: 1.5;
        word-break: break-word;
    }
}
