:root {
    color-scheme: light dark;
    --bg: #0f172a;
    --panel: #1e293b;
    --panel-2: #273449;
    --text: #e2e8f0;
    --muted: #94a3b8;
    --border: #334155;
    --green: #22c55e;
    --red: #ef4444;
    --amber: #f59e0b;
    --accent: #38bdf8;
    font-family: -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    overflow-x: hidden;
}

.table-scroll { overflow-x: auto; }

h1:focus { outline: none; }

.app-shell { min-height: 100vh; display: flex; flex-direction: column; }

.auth-shell { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 1.5rem; }
.auth-card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 2rem;
    width: 100%;
    max-width: 360px;
}
.auth-card h1 { font-size: 1.2rem; margin: 0 0 1rem 0; }
.auth-card form { display: flex; flex-direction: column; gap: 1rem; margin-top: 1rem; }
.auth-card input { width: 100%; }
.auth-error { color: var(--red); font-size: 0.88rem; margin: 0.5rem 0 0 0; }

.topnav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.9rem 1.5rem;
    background: var(--panel);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 100;
}
.topnav-left { display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.topnav .brand { font-weight: 700; font-size: 1.05rem; }
.topnav .ticker { font-size: 0.85rem; color: var(--text); }
.topnav .ticker strong { color: var(--accent); }
/* Tabular figures so the price and its change don't shuffle sideways on every tick - a
   header number that jitters reads as broken even when it is perfectly correct. */
.topnav .ticker-index { font-variant-numeric: tabular-nums; }
.topnav .ticker-gap { margin-left: 0.9rem; }
.topnav .ticker-up { color: var(--green); margin-left: 0.3rem; }
.topnav .ticker-down { color: var(--red); margin-left: 0.3rem; }
.topnav .ticker-warn { color: var(--amber); margin-left: 0.5rem; cursor: help; }
.topnav nav a {
    color: var(--muted);
    text-decoration: none;
    margin-left: 1.25rem;
    font-size: 0.92rem;
    padding-bottom: 2px;
}
.topnav nav a.active { color: var(--accent); border-bottom: 2px solid var(--accent); }

main { padding: 1.5rem; max-width: 1200px; margin: 0 auto; width: 100%; }

.card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 1.1rem 1.3rem;
    margin-bottom: 1.25rem;
}

.card h2, .card h3 { margin-top: 0; }

.pnl-hero { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; }
.pnl-hero .value { font-size: 2.2rem; font-weight: 700; }
.pnl-positive { color: var(--green); }
.pnl-negative { color: var(--red); }
.badge {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    background: var(--panel-2);
    border: 1px solid var(--border);
}
.badge-fake { color: var(--amber); border-color: var(--amber); }
.badge-live { color: var(--red); border-color: var(--red); }

.page-header-row { display: flex; align-items: center; flex-wrap: wrap; gap: 1rem; }
.page-header-row h1 { margin: 0; }
.page-header-actions { display: flex; align-items: center; gap: 0.75rem; margin-left: auto; }

/* Keeps Save settings reachable without scrolling back up a long settings page. --topnav-h is
   published at runtime by order-scroll.js's syncStickyOffsets() (see Settings.razor's
   OnAfterRenderAsync) - a fixed px guess would overlap the nav once it wraps below 640px. */
.settings-header-sticky {
    position: sticky;
    top: var(--topnav-h, 90px);
    z-index: 90;
    background: var(--bg);
    padding-top: 0.6rem;
    padding-bottom: 0.6rem;
}

.form-row { display: flex; gap: 1rem; flex-wrap: wrap; align-items: flex-end; margin-bottom: 0.5rem; }
.form-field { display: flex; flex-direction: column; gap: 0.3rem; min-width: 140px; }
.form-field label { font-size: 0.8rem; color: var(--muted); }
input, select {
    background: var(--panel-2);
    border: 1px solid var(--border);
    color: var(--text);
    border-radius: 6px;
    padding: 0.45rem 0.6rem;
    font-size: 0.92rem;
}
input[type=checkbox] { width: 1.1rem; height: 1.1rem; }

button {
    background: var(--accent);
    color: #05202e;
    border: none;
    border-radius: 6px;
    padding: 0.5rem 0.9rem;
    font-weight: 600;
    cursor: pointer;
    font-size: 0.88rem;
}
button:hover { filter: brightness(1.08); }
button.secondary { background: var(--panel-2); color: var(--text); border: 1px solid var(--border); }
button.danger { background: var(--red); color: white; }
button.small { padding: 0.3rem 0.6rem; font-size: 0.8rem; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
th, td { text-align: left; padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--border); white-space: nowrap; }
th { color: var(--muted); font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.02em; }
tr:last-child td { border-bottom: none; }

.role-buy { color: var(--green); font-weight: 600; }
.role-sell { color: var(--red); font-weight: 600; }

.banner {
    background: linear-gradient(135deg, #422006, #1e293b);
    border: 1px solid var(--amber);
    border-radius: 10px;
    padding: 1rem 1.25rem;
    margin-bottom: 1.25rem;
}
.banner h3 { margin: 0 0 0.4rem 0; color: var(--amber); }
.banner ul { margin: 0.5rem 0; padding-left: 1.2rem; }
.banner-success { background: linear-gradient(135deg, #052e1a, #1e293b); border-color: var(--green); }
.banner-danger { background: linear-gradient(135deg, #3a0d0d, #1e293b); border-color: var(--red); }
.banner .actions { margin-top: 0.75rem; display: flex; gap: 0.6rem; }

/* In-app confirmation dialog (ConfirmDialog.razor) - replaces native confirm(), which
   browsers silently suppress once "prevent additional dialogs" is ticked. */
.modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(2, 6, 23, 0.72);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    z-index: 200;
}
.modal {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 1.25rem 1.4rem;
    width: 100%;
    max-width: 460px;
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.5);
}
.modal h3 { margin: 0 0 0.6rem 0; }
.modal p { margin: 0; color: var(--muted); line-height: 1.45; }
.modal .actions { margin-top: 1.1rem; display: flex; gap: 0.6rem; justify-content: flex-end; }

/* The trigger panel's Status column explains what each trigger will do - truncating it behind
   a horizontal scrollbar hides exactly the part that needs reading. Let it wrap instead.
   No min-widths: the panel sits in the narrow left column, and a floor on two columns is what
   pushed the table wider than the panel and produced the horizontal scrollbar. Wrapping costs
   a little height; scrolling sideways costs you the sentence. */
.trigger-table { table-layout: auto; width: 100%; }
.trigger-table td, .trigger-table th { white-space: normal; word-break: break-word; }
.trigger-table td:first-child { min-width: 0; }
/* "Fires at" (3rd column) used to be short everywhere ("≥ ₹1,500", "0/4"), so forcing it
   onto one line was harmless - but the Trigger 2/2b threshold cells now carry a sentence
   ("< -₹20,475 (50% of credit)", "no positive combined BUY cost captured (...)"), and
   nowrap on THAT column forced the browser to give it however much width that sentence
   needed, which - under auto layout - it took from column 1, which has no such floor and
   the same word-break:break-all as below. The result was "1 · Overall profit" wrapped one
   character per line. Column 3 wraps normally now, same as column 1 always has; columns 2
   and 4 stay nowrap since their content (a P&L figure, a streak count) is still always short. */
.trigger-table td:nth-child(2), .trigger-table td:nth-child(4),
.trigger-table th:nth-child(2), .trigger-table th:nth-child(4) {
    white-space: nowrap;
}
/* The delta rows carry a full contract symbol next to the trigger name - the one string long
   enough to force the table wide on its own. */
.trigger-table td:first-child .hint { word-break: break-all; }

.muted { color: var(--muted); }
.hint { font-size: 0.82rem; color: var(--muted); margin-top: 0.3rem; }

/* Small inline toggle that reveals a hint paragraph on click, instead of it always showing -
   used on Settings' Trigger 1 / ProfitLoss / Delta / Delta Spike sections (2026-09-26), which
   accumulated enough explanatory prose to bury the actual settings. */
.help-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.3rem;
    height: 1.3rem;
    margin-left: 0.4rem;
    padding: 0;
    font-size: 0.75rem;
    line-height: 1;
    color: var(--muted);
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 50%;
    cursor: pointer;
    vertical-align: middle;
}
.help-toggle:hover { color: var(--text); border-color: var(--accent); }

/* Puts Delta PE and Delta CE side by side on the Trigger Delta settings tab, so Fire 1/2/3
   line up for comparison instead of scrolling through PE's three tables then CE's three. */
.pe-ce-columns { display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: flex-start; min-width: 0; }
.pe-ce-col { flex: 1 1 360px; min-width: 300px; }
/* The default `th, td { white-space: nowrap; }` (below) is fine everywhere else on this page,
   but a long setting label (e.g. Pair PE/CE's "PUT pair loss before firing (%...)") can't
   shrink to fit a ~360px flex column while staying on one line - the table then grows past
   its column's width and visibly overlaps the sibling column next to it. Letting just the
   label column wrap fixes that; the two value columns next to it stay nowrap since they're
   short, fixed-width inputs. */
.pe-ce-col td:first-child, .pe-ce-col th:first-child { white-space: normal; }

.strategy-group + .strategy-group { margin-top: 1rem; }

/* While the option chain is open, its expiry tabs (dual-expiry only) stay pinned at the top
   of whichever element is actually scrolling, and the table's own column headers stay pinned
   right below THEM - so scrolling through ~90 strikes never loses track of which expiry is
   being browsed or what each column is. The chain table intentionally isn't wrapped in
   .table-scroll: overflow-x:auto forces overflow-y to compute as auto too (CSS overflow spec
   - the two axes can't independently be "auto" and "visible"), which makes that div - not
   whatever's actually scrolling - the sticky-positioning container, breaking the sticky
   header entirely. The chain's 7 columns fit without horizontal scrolling, so skip the
   wrapper. */
/* --chain-tabs-top / --chain-thead-top are set at runtime by order-scroll.js's
   syncStickyOffsets(). What they need to be depends on whether the chain's own panel scrolls
   internally (two-column shell: top nav is outside that scroll context, doesn't count) or the
   whole page scrolls instead (single-column: the top nav IS in that scroll context and sits
   in front of anything else at top:0, so it does count) - see that function for the full
   reasoning. A hardcoded guess broke as soon as any of these varied: which layout is active,
   the nav wrapping at a narrow width, tabs wrapping, font scaling, one expiry vs two. */
.chain-expiry-tabs-sticky { position: sticky; top: var(--chain-tabs-top, 0px); z-index: 71; background: var(--panel); padding-bottom: 0.3rem; }
/* .pos-panel-body table th (below) generically pins every panel's table header at top:0 and
   would otherwise win this fight - it's one class + two elements vs. this rule's one class +
   one element, a more specific selector regardless of source order, so this needs the extra
   .pos-panel-body prefix purely to out-specify it, not because the nesting means anything. */
.pos-panel-body .chain-thead-sticky th { position: sticky; top: var(--chain-thead-top, 0px); background: var(--panel); z-index: 70; }
.atm-row { background: rgba(56, 189, 248, 0.10); box-shadow: inset 3px 0 0 var(--accent); }

.account-section { margin-bottom: 2.5rem; padding-bottom: 2rem; border-bottom: 1px solid var(--border); }
.account-section:last-child { border-bottom: none; }
.account-section h2 { display: flex; align-items: center; flex-wrap: wrap; gap: 0.6rem; font-size: 1.3rem; margin: 0 0 1rem 0; }

.tabs { display: flex; gap: 0.3rem; border-bottom: 1px solid var(--border); margin-bottom: 1.5rem; flex-wrap: wrap; }
.tab {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    background: transparent;
    color: var(--muted);
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 6px 6px 0 0;
    padding: 0.6rem 1rem;
    font-weight: 600;
    font-size: 0.92rem;
    cursor: pointer;
}
.tab:hover { color: var(--text); background: var(--panel); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); background: var(--panel); }
.tab-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; display: inline-block; }
.tab-dot-pending { background: var(--amber); }
.tab-dot-success { background: var(--green); }
.tab-dot-danger { background: var(--red); }

.emergency-banner {
    background: linear-gradient(135deg, #3a0d0d, #1e293b);
    border-bottom: 1px solid var(--red);
    color: var(--text);
    padding: 0.7rem 1.5rem;
    font-size: 0.92rem;
    text-align: center;
}

#blazor-error-ui {
    background: #b32121;
    color: white;
    display: none;
    left: 0;
    bottom: 0;
    position: fixed;
    width: 100%;
    z-index: 1000;
    padding: 0.9rem 1rem;
}
#blazor-error-ui .dismiss { cursor: pointer; float: right; }

/* Row - flexbox based */
.row {
    display: flex;
    flex-wrap: wrap;
    margin-right: -15px;
    margin-left: -15px;
}

/* Common column styles */
[class*="col-"] {
    position: relative;
    width: 100%;
    padding-right: 15px;
    padding-left: 15px;
}

/* Column classes */
.col {
    flex-basis: 0;
    flex-grow: 1;
    max-width: 100%;
}

.col-1 {
    flex: 0 0 8.333333%;
    max-width: 8.333333%;
}

.col-2 {
    flex: 0 0 16.666667%;
    max-width: 16.666667%;
}

.col-3 {
    flex: 0 0 25%;
    max-width: 25%;
}

.col-4 {
    flex: 0 0 33.333333%;
    max-width: 33.333333%;
}

.col-5 {
    flex: 0 0 41.666667%;
    max-width: 41.666667%;
}

.col-6 {
    flex: 0 0 50%;
    max-width: 50%;
}

.col-7 {
    flex: 0 0 58.333333%;
    max-width: 58.333333%;
}

.col-8 {
    flex: 0 0 66.666667%;
    max-width: 66.666667%;
}

.col-9 {
    flex: 0 0 75%;
    max-width: 75%;
}

.col-10 {
    flex: 0 0 83.333333%;
    max-width: 83.333333%;
}

.col-11 {
    flex: 0 0 91.666667%;
    max-width: 91.666667%;
}

.col-12 {
    flex: 0 0 100%;
    max-width: 100%;
}

/* ---------- Responsive breakpoints ---------- */

@media (max-width: 900px) {
    main { padding: 1.25rem; }
}

/* Tablet: stack the two-column row layout (e.g. hero P&L + trigger card) */
@media (max-width: 768px) {
    [class*="col-"] {
        flex: 0 0 100%;
        max-width: 100%;
    }
}

/* Mobile */
@media (max-width: 640px) {
    main { padding: 0.85rem; }

    .topnav {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.6rem;
        padding: 0.8rem 1rem;
    }
    .topnav nav {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        row-gap: 0.5rem;
        width: 100%;
    }
    .topnav nav a { margin-left: 0; margin-right: 1.1rem; }
    .topnav nav form { margin-left: 0 !important; }

    .page-header-row h1 { font-size: 1.25rem; }
    .page-header-actions { margin-left: 0; }

    .pnl-hero .value { font-size: 1.7rem; }

    .card { padding: 0.9rem 1rem; }

    .form-row { gap: 0.75rem; }
    .form-field { min-width: 100%; }

    table { font-size: 0.8rem; }
    th, td { padding: 0.45rem 0.5rem; }

    .tab { padding: 0.55rem 0.75rem; font-size: 0.85rem; }
}

@media (max-width: 380px) {
    .topnav .brand { font-size: 0.92rem; }
    .pnl-hero .value { font-size: 1.4rem; }
}
/* ============================================================================
   Positions page (Home.razor)
   ----------------------------------------------------------------------------
   This is a live monitoring screen, so the design constraint is that a whole
   session - account switcher, trigger state and every open leg - has to be
   readable in one viewport without scrolling. Vertical space is therefore the
   scarce resource: headings, hero cards and explanatory paragraphs that only
   restate a number shown elsewhere were removed, what is left is packed into
   two strips and two panels, and anything that explains behaviour rather than
   reporting a value moved into a title= tooltip.
   ============================================================================ */

/* The 1200px cap costs height on this page: it forces the trigger table's
   Status column and the 10-column leg table to wrap, and every wrapped line is
   a row of legs pushed off screen. Applied by MainLayout, on this route only. */
main.main-wide { max-width: none; padding: 0.6rem 1.15rem; }

/* On this route the shell is pinned to the viewport and the panels scroll inside
   themselves, so the page as a whole never scrolls: with a normal 4-leg position
   nothing scrolls at all, and when the position outgrows the screen (averaging
   doubles a pair, a second expiry opens) the account strip, the P&L and the
   trigger state stay put instead of sliding off the top.
   :has() scopes this to the one route without needing a class on <body>. Where it
   isn't supported the rules simply don't apply and the page scrolls as it used to,
   which is a fine fallback rather than a broken layout. */
body:has(main.main-wide) .app-shell { height: 100vh; }
main.main-wide { flex: 1 1 auto; min-height: 0; overflow: hidden; }

.pos-page { display: flex; flex-direction: column; gap: 0.32rem; height: 100%; min-height: 0; }

/* Row 1: account switcher + all-accounts total. The tabs already carry each
   account's name and P&L, which is what made the old summary table redundant. */
.pos-bar { display: flex; align-items: flex-end; gap: 1rem; flex-wrap: wrap; border-bottom: 1px solid var(--border); }
.pos-tabs { display: flex; gap: 0.25rem; flex-wrap: wrap; }
.pos-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    background: transparent;
    color: var(--muted);
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 6px 6px 0 0;
    padding: 0.45rem 0.85rem;
    font-weight: 600;
    font-size: 0.9rem;
    cursor: pointer;
}
.pos-tab:hover { color: var(--text); background: var(--panel); }
.pos-tab.active { color: var(--text); background: var(--panel); }
.pos-total { display: flex; align-items: center; gap: 0.6rem; margin-left: auto; padding-bottom: 0.3rem; font-size: 0.85rem; }
.pos-total-value { font-size: 1.25rem; font-weight: 700; }

.acct-dot { width: 0.7rem; height: 0.7rem; border-radius: 50%; flex-shrink: 0; display: inline-block; }

/* Row 2: everything identifying the selected account, on one line. */
.pos-strip {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    background: var(--panel);
    border: 1px solid var(--border);
    border-left: 4px solid var(--accent);
    border-radius: 8px;
    padding: 0.28rem 0.75rem;
}
.pos-strip-pnl { font-size: 1.35rem; font-weight: 700; }
.pos-strip .hint { margin-top: 0; }
.pos-strip-action { margin-left: auto; }
.pos-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    border: 1px solid var(--accent);
    color: var(--accent);
    text-decoration: none;
    border-radius: 999px;
    padding: 0.1rem 0.6rem;
    font-size: 0.8rem;
    font-weight: 600;
}

/* Transient banners sit between the strips and the panels, so they are one line
   high - they push the actual position down for as long as they are on screen. */
.banner-compact { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; padding: 0.45rem 0.8rem; margin-bottom: 0; }
.banner-compact .hint { margin-top: 0; }

/* Flex rather than grid so the panels can share a bounded height: in a grid, auto
   rows size to their content and overflow the container instead of shrinking. */
/* The single-screen workspace: chain and triggers on the left, chart and positions on the
   right. The left column is deliberately the narrower of the two - the chain is a fixed set
   of columns, whereas the chart and the positions table both want room. */
.work-split { display: flex; flex-direction: column; gap: 0.5rem; flex: 1 1 auto; min-height: 0; }
.work-left, .work-right { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; min-height: 0; }
@media (min-width: 1280px) {
    .work-split { flex-direction: row; align-items: stretch; }
    /* Sized by the option chain, which is the widest thing in this column: seven columns
       plus two button pairs. Below this it scrolls sideways, and a chain you have to scroll
       to read the far delta of is a chain you misread. */
    .work-left { flex: 0 0 46%; max-width: 46%; }
    .work-right { flex: 1 1 0; }
}

/* Same "takes whatever height is left and scrolls inside it" treatment as .pos-panel-body
   (see that rule's own comment) - this panel just never had it, because it holds a chart
   instead of a table. The chart's height scales with the column's width (no fixed height,
   so it can't stretch), and at a wide enough browser window that made it tall enough to push
   the margin/breakevens line below it clean off the page's fixed-height shell - with no
   scrollbar anywhere to reach it, since nothing here was carrying that responsibility. */
.payoff-block { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* Buy/sell in the chain. Fixed widths throughout so the pair lines up down the column
   whatever the price is, and the selection tick sits in a reserved slot rather than
   widening the button and nudging its neighbour along. */
.chain-cell { display: flex; align-items: center; gap: 0.35rem; }
.chain-ltp { flex: 1 1 auto; text-align: right; font-variant-numeric: tabular-nums; }
.chain-btns { display: flex; gap: 0.2rem; flex: 0 0 auto; }
.chain-bs {
    width: 2.5rem;
    padding: 0.1rem 0;
    font-size: 0.72rem;
    text-align: center;
    margin: 0;
}
.chain-bs .tick { display: inline-block; width: 0.75rem; }
.chain-b { background: var(--green); color: #05202e; }
.chain-s { background: var(--red); color: #fff; }

.ticket-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    padding-top: 0.45rem;
    border-top: 1px solid var(--border);
    margin-top: 0.35rem;
}

.pos-panel {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 0.4rem 0.75rem 0.45rem;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.pos-panel-head {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    flex-wrap: wrap;
    padding-bottom: 0.35rem;
    margin-bottom: 0.2rem;
    border-bottom: 1px solid var(--border);
    font-size: 0.95rem;
}
.pos-panel-head .hint { margin-top: 0; }
.pos-panel-end { margin-left: auto; }

/* Takes whatever height is left and scrolls inside it, so a position that outgrows
   the viewport never pushes the other panel off the screen. Under that height
   nothing scrolls at all. */
.pos-panel-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.pos-panel-body th, .pos-panel-body td { padding: 0.2rem 0.5rem; }
.pos-panel-body table th { position: sticky; top: 0; background: var(--panel); z-index: 2; }

.leg-group-caption {
    display: flex;
    gap: 0.6rem;
    align-items: baseline;
    font-size: 0.78rem;
    color: var(--muted);
    padding: 0.05rem 0.5rem 0;
}
.leg-group-caption + table { margin-bottom: 0.35rem; }

/* Side by side only on a genuinely wide monitor: below this the 10-column leg table
   would have to scroll sideways in its half, trading one scrollbar for another. */


/* Below tablet width the pinned-viewport layout stops helping - there is not enough
   height left for two scrollable panels - so hand scrolling back to the page. */
@media (max-width: 900px) {
    body:has(main.main-wide) .app-shell { height: auto; }
    main.main-wide { overflow: visible; }
    .pos-page { height: auto; }
    .work-split { flex: none; }
    .pos-panel-body { flex: none; overflow: visible; }
}

@media (max-width: 640px) {
    main.main-wide { padding: 0.85rem; }
    .pos-tab { padding: 0.4rem 0.6rem; font-size: 0.82rem; }
    .pos-total { margin-left: 0; }
    .pos-strip-pnl { font-size: 1.15rem; }
    .pos-strip-action { margin-left: 0; }
}

/* ---- Payoff, inside the Automatic triggers panel -------------------------------
   The chart and the trigger rows sit side by side so the shape of the position and
   the rules watching it are read together. Below 1400px they stack, because a
   240-point payoff squeezed into half of a narrow window says nothing. */
.trigger-body { display: flex; flex-direction: column; gap: 0.5rem; }
.trigger-split { display: flex; flex-direction: column; gap: 0.6rem; min-width: 0; }
/* Its own full-width row above the trigger table. The chart is the widest thing on the page
   and the only one whose shape carries meaning, so it gets the room. */
.trigger-payoff { display: flex; flex-direction: column; gap: 0.25rem; width: 100%; min-width: 0; }
.trigger-rows { min-width: 0; }

.payoff { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.payoff-title { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; font-size: 0.92rem; }

/* One line: margin then breakevens, each followed by its own qualifier. Wraps rather than
   truncating when the column is narrow - the qualifiers are the part worth reading. */
.payoff-stats {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.15rem 0.45rem;
    line-height: 1.5;
}
.payoff-stat { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 0.3rem; min-width: 0; }
.payoff-stat .k {
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
    white-space: nowrap;
}
.payoff-stat .v { font-size: 0.95rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.payoff-stat .sub { font-size: 0.74rem; color: var(--muted); }
.payoff-sep { color: var(--border); }

/* Height follows the width at the chart's own 3.8:1 ratio - no fixed height, because
   forcing one is what stretched it. */
.payoff-canvas {
    position: relative;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface, var(--panel-2));
    padding: 0.2rem;
}

/* Hover read-out. Positioned by payoff-chart.js; pointer-events off so the box can never
   sit between the cursor and the chart and make the reading flicker. */
.payoff-cross {
    position: absolute;
    top: 0.2rem;
    bottom: 0.2rem;
    width: 1px;
    background: var(--accent);
    opacity: 0.6;
    pointer-events: none;
}
.payoff-tip {
    position: absolute;
    top: 0.4rem;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.35rem 0.55rem;
    font-size: 0.78rem;
    line-height: 1.5;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
    z-index: 5;
}

/* Hides the SVG's static "Spot: <value>" marker (see PayoffChart.razor's own comment on
   .pf-spot-mark) for as long as the hover tooltip is showing - tied to the tooltip's `hidden`
   attribute rather than toggled by payoff-chart.js directly, because the SVG markup itself gets
   replaced on every poll-tick re-render while this page is live: a JS-applied inline style on
   the marker would get silently wiped the next time positions refresh mid-hover, and the two
   markers would flash back into view together. A CSS rule keyed off .payoff-tip's own state
   re-applies itself the instant a fresh SVG lands, with nothing to go stale. */
.payoff-canvas:has(.payoff-tip:not([hidden])) .pf-spot-mark {
    display: none;
}
.payoff-tip-head { font-weight: 700; display: flex; gap: 0.4rem; align-items: baseline; margin-bottom: 0.15rem; }
.payoff-tip-head span { font-size: 0.72rem; font-weight: 600; }
.payoff-tip-row { display: flex; align-items: center; gap: 0.35rem; color: var(--muted); }
.payoff-tip-row b { margin-left: auto; padding-left: 0.9rem; font-variant-numeric: tabular-nums; }
.payoff-tip .sw { width: 0.6rem; height: 0.6rem; border-radius: 2px; flex-shrink: 0; }
.payoff-tip .sw-expiry { background: var(--accent); }
.payoff-tip .sw-today { background: var(--muted); }
.payoff-canvas svg { display: block; width: 100%; height: auto; }

/* ---- CalendarDatePicker (Replay trading day) ---- */
.cal-picker { display: inline-block; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 0.6rem; }
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.4rem; font-size: 0.88rem; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1.9rem); gap: 0.15rem; text-align: center; }
.cal-dow { color: var(--muted); font-size: 0.72rem; margin-bottom: 0.15rem; }
.cal-day {
    height: 2.1rem;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text);
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
}
.cal-day:hover:not(.cal-disabled) { background: var(--panel-2); }
.cal-day.cal-expiry { color: var(--green); font-weight: 700; box-shadow: inset 0 0 0 1px var(--green); }
.cal-day.cal-selected { background: var(--accent); color: #05202e; font-weight: 700; }
.cal-day.cal-disabled { color: var(--muted); opacity: 0.4; cursor: not-allowed; }
.cal-legend { display: flex; gap: 0.9rem; margin-top: 0.5rem; font-size: 0.74rem; color: var(--muted); }
.cal-dot { display: inline-block; width: 0.55rem; height: 0.55rem; border-radius: 50%; margin-right: 0.3rem; }
.cal-dot-expiry { background: var(--green); }
.cal-dot-holiday { background: var(--muted); }

/* ---- Draft ticket strike ± roll ---- */
.strike-adjust { display: inline-flex; align-items: center; gap: 0.3rem; }
.strike-adjust button { width: 1.6rem; height: 1.6rem; padding: 0; line-height: 1; font-weight: 700; }
.strike-adjust .v { font-variant-numeric: tabular-nums; min-width: 3.2rem; text-align: center; display: inline-block; }

/* ---- Replay session load: indeterminate progress ----
   The historical fetch reports no real percentage back to the page - it's a fixed sequence
   of throttled requests with no per-contract callback wired through - so this is honestly
   indeterminate (a sliding highlight), not a fake number climbing to 100. */
.loading-bar { height: 0.35rem; border-radius: 999px; background: var(--panel-2); overflow: hidden; margin: 0.4rem 0; }
.loading-bar-fill {
    height: 100%;
    width: 40%;
    border-radius: 999px;
    background: var(--accent);
    animation: loading-bar-slide 1.1s ease-in-out infinite;
}
@keyframes loading-bar-slide {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(350%); }
}

/* ---- Historical cache warmup: determinate progress ----
   Unlike the Replay session loader above, the warmup counts trading days itself as it goes, so
   a real percentage exists to show - a plain width-driven fill, no slide animation. */
.progress-bar { height: 0.35rem; border-radius: 999px; background: var(--panel-2); overflow: hidden; margin: 0.4rem 0; }
.progress-bar-fill { height: 100%; border-radius: 999px; background: var(--accent); transition: width 0.3s ease; }

/* ---- Replay setup: calendar left, everything else fills the row beside it ----
   The calendar is a tall block, not a one-line input like its siblings - inside a plain
   flex-wrap row that height mismatch pushed every field after it onto its own line below,
   leaving the whole width to the calendar's right empty: flex-wrap only wraps the second
   item down, it doesn't stop the first item's row from being exactly as wide as it would've
   been side by side, so the gap where the second item would have gone just sits empty
   instead of being reclaimed. Sized tight enough (see .cal-grid and the nowrap row below)
   that side by side actually fits within .work-left's 46%-of-viewport width (see .work-split)
   from .work-split's own two-column breakpoint upward - a real laptop at 100% zoom, not just
   an extra-wide monitor. Below that breakpoint .work-left is the full single-column width,
   which fits easily too. Only a narrow phone-width viewport still needs the stacked fallback,
   which is what flex-wrap here is for. */
.replay-setup-grid { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 1rem; }
.replay-setup-right { display: flex; flex-direction: column; gap: 0.7rem; flex: 1; min-width: 260px; }
/* Un-forces .form-field's default 140px min-width for just this row: Start at and Speed
   both already have an explicit input width, so the wrapper only needs to match that -
   the 140px floor otherwise padded ~30-50px of dead space per field into a row that's
   supposed to read as one compact line. */
.replay-nowrap { flex-wrap: nowrap; }
.replay-nowrap .form-field { min-width: 0; }
