/* Backtest chart dialog (BacktestLiveChart): replay, live run and live-rule activity.
   Global rather than scoped because MudBlazor renders the dialog outside the component's
   scope; dialog selectors use the `.mud-dialog.backtest-live-dialog` form (no space). */

/* ------------------------------------------------------------------ dialog shell */

.mud-dialog.backtest-live-dialog {
    background-color: var(--degen-bg-secondary);
    min-width: 960px;
}

/* No title padding or border here: mudblazor-overrides.css sets both on
   `.mud-dialog .mud-dialog-title` with `!important`, so every dialog in the app gets 16px 20px
   and a subtle bottom border whatever this file asks for. That `!important` also cancels
   MudBlazor's own `padding-inline-end: 64px` reservation for the absolutely positioned close
   button, which is why the activity header reserves room for it itself (see below). */

.mud-dialog.backtest-live-dialog .mud-dialog-content {
    padding: 12px 18px;
    overflow: hidden;
}

/* ------------------------------------------------------------------ shared atoms */

.bt-lbl {
    font-size: 10px;
    color: var(--degen-text-tertiary);
    letter-spacing: .04em;
    text-transform: uppercase;
}

.bt-mono {
    font-family: var(--degen-font-mono);
    color: var(--degen-text-primary);
}

.bt-pos { color: var(--degen-pnl-positive); }
.bt-neg { color: var(--degen-pnl-negative); }

.bt-clamp-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.bt-link {
    font-size: 11px;
    color: var(--degen-color-primary);
    cursor: pointer;
}

.bt-link:hover { text-decoration: underline; }

.bt-reason {
    font-size: 12px;
    line-height: 1.5;
    color: var(--degen-text-secondary);
    word-break: break-word;
}

.bt-empty {
    padding: 10px;
    font-size: 11px;
    color: var(--degen-text-tertiary);
}

/* ------------------------------------------------------------------ title row */

.bt-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    min-width: 0;
}

.bt-title-mode {
    font-family: var(--degen-font-sans);
    font-size: 17px;
    font-weight: 500;
    color: var(--degen-text-secondary);
    margin-right: -4px;
}

.bt-title-asset {
    font-family: var(--degen-font-sans);
    font-size: 17px;
    font-weight: 600;
    color: var(--degen-text-primary);
}

.bt-meta {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 3px 8px;
    border: 1px solid var(--degen-border-default);
    border-radius: 4px;
    font-size: 12px;
}

.bt-meta .bt-lbl { font-size: 9px; }

.bt-rule-pill,
.bt-status-chip {
    padding: 2px 8px;
    border-radius: 4px;
    background: var(--degen-color-primary-muted);
    color: var(--degen-color-primary);
    font-family: var(--degen-font-mono);
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
}

.bt-rule-pill {
    max-width: 280px;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: help;
}

.bt-status-chip {
    background: var(--degen-bg-surface);
    color: var(--degen-text-secondary);
    font-size: 10px;
}

/* ------------------------------------------------------------------ activity header (control center) */

.bt-activity-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
}

/* The two groups contribute no box of their own on desktop, so the header stays one flat flex
   row. The phone media query turns them into the two rows it lays out. */
.bt-activity-ident,
.bt-activity-controls {
    display: contents;
}

.bt-back-btn {
    color: var(--degen-text-secondary);
    margin-left: -6px;
}

.bt-rule-badge {
    padding: 2px 8px;
    border-radius: 4px;
    border: 1px solid var(--degen-border-default);
    color: var(--degen-text-tertiary);
    font-family: var(--degen-font-mono);
    font-size: 11px;
}

.bt-activity-rule-name {
    font-family: var(--degen-font-sans);
    font-size: 16px;
    font-weight: 600;
    color: var(--degen-text-primary);
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ------------------------------------------------------------------ KPI strip */

/* Flex rather than grid on purpose: the tiles have to consume the whole row whatever their
   number is. With auto-fit columns the full-width banner below them kept every track open, so a
   strip holding a single tile pinned it to one 110px column (clipping its text) and painted the
   rest of the row in the strip's own separator colour, which read as a grey bar. */
.bt-kpis {
    display: flex;
    flex-wrap: wrap;
    gap: 1px;
    background: var(--degen-border-default);
    border-bottom: 1px solid var(--degen-border-default);
    /* Full dialog width: cancel the content padding above and at the sides. */
    margin: -12px -18px 12px;
}

.bt-kpi {
    background: var(--degen-bg-secondary);
    padding: 8px 14px;
    min-width: 0;
    flex: 1 1 110px;
}

.bt-kpi-v {
    font-family: var(--degen-font-mono);
    font-size: 16px;
    font-weight: 600;
    margin-top: 2px;
    color: var(--degen-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bt-kpi-v.bt-pos { color: var(--degen-pnl-positive); }
.bt-kpi-v.bt-neg { color: var(--degen-pnl-negative); }

.bt-kpi-hero .bt-kpi-v { font-size: 22px; }

.bt-kpi-v-sm { font-size: 12px; }

.bt-kpi-s {
    font-family: var(--degen-font-mono);
    font-size: 10px;
    color: var(--degen-text-tertiary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bt-kpi-live {
    display: flex;
    align-items: center;
    gap: 6px;
}

.bt-kpi-progress { margin-top: 4px; height: 3px; }

/* Activity + Backtest: the "simulated on past prices" disclaimer spans the full strip width
   below the tiles, rather than fighting them for a column of their own. */
.bt-kpis .bt-kpi-banner {
    flex-basis: 100%;
    padding: 4px 14px 8px;
}

.bt-kpis .bt-kpi-caveat {
    white-space: normal;
    color: var(--degen-color-warning);
}

.bt-kpi-controls {
    display: flex;
    align-items: center;
    justify-content: flex-end;
}

.bt-run-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.bt-days-select { width: 110px; font-size: 12px; }

.bt-grade-chip {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 4px;
    font-family: var(--degen-font-mono);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    vertical-align: middle;
}

.bt-grade-good { background: var(--degen-color-primary-muted); color: var(--degen-color-primary); }
.bt-grade-fair { background: var(--degen-color-warning-muted); color: var(--degen-color-warning); }
.bt-grade-poor { background: var(--degen-color-sell-muted); color: var(--degen-color-error); }
.bt-grade-rejected {
    background: var(--degen-color-sell-muted);
    color: var(--degen-color-error);
    box-shadow: inset 0 0 0 1px var(--degen-color-error);
}
.bt-grade-none { background: var(--degen-bg-surface); color: var(--degen-text-secondary); }

/* ------------------------------------------------------------------ chart + timeline */

.chart-layout {
    display: flex;
    gap: 12px;
    /* Equity-lane toggle adds vertical room. The JS timeline owns the value
       via --bt-equity-lane-extra (set in syncEquityLayoutProperty) so the
       CSS never duplicates the lane height -- single source of truth. */
    height: calc(600px + var(--bt-equity-lane-extra, 0px));
}

.backtest-chart-column {
    /* Label gutter shared by the timeline (read by backtest-timeline.js) and the chart
       inset below, so a candle's x matches its timeline dot's x. */
    --bt-lane-gutter: 84px;
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    min-height: 0;
}

.backtest-chart-area {
    flex: 1;
    position: relative;
    min-width: 0;
    min-height: 0;
    margin-left: var(--bt-lane-gutter);
}

.backtest-timeline-host {
    flex: 0 0 auto;
}

/* Full-cover state over the chart: the loading spinner, and the message shown when there is
   nothing to draw. Must sit ABOVE the chart library's own canvases (which carry their own
   stacking context) and above the notice strip and colour key below, or an empty chart reads as
   a hang rather than as an explanation. */
.chart-cover-overlay {
    position: absolute;
    inset: 0;
    z-index: 6;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--degen-bg-primary);
}

.chart-setup-strip {
    position: absolute;
    bottom: 8px;
    left: 8px;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px;
    border-radius: 4px;
    border: 1px solid var(--degen-color-primary-muted);
    background: var(--degen-bg-surface);
}

.chart-load-notice {
    position: absolute;
    top: 8px;
    left: 8px;
    right: 8px;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 4px 6px 4px 10px;
    border-radius: 4px;
    border: 1px solid var(--degen-color-warning);
    background: var(--degen-bg-surface);
}

/* Colour key over the chart, top right. Left of it is the load notice, which spans the full
   width when it is up, so the legend deliberately sits BELOW the notice's height.

   The right offset clears the chart's price axis: --bt-price-axis-w is the axis width the
   timeline measures off the live chart and publishes on .backtest-chart-column (the axis grows
   with the price's digit count, so it cannot be a constant). Pinned at plain right: 8px the
   legend sat on top of the price labels. The fallback covers the moment before the timeline
   has painted once. */
.chart-color-legend {
    position: absolute;
    top: 38px;
    right: calc(var(--bt-price-axis-w, 64px) + 8px);
    z-index: 4;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 3px 8px;
    border-radius: 4px;
    border: 1px solid var(--degen-border-subtle);
    background: var(--degen-bg-surface);
    font-family: var(--degen-font-mono);
    font-size: 10px;
    color: var(--degen-text-secondary);
    pointer-events: none;
}

.chart-color-legend .legend-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.chart-color-legend .legend-swatch {
    width: 8px;
    height: 8px;
    border-radius: 2px;
}

.chart-color-legend .sw-buy { background: var(--degen-chart-up); }
.chart-color-legend .sw-sell { background: var(--degen-chart-down); }
.chart-color-legend .sw-order { background: var(--degen-color-info); }
.chart-color-legend .sw-wake { background: var(--degen-color-warning); }
.chart-color-legend .sw-context {
    background: var(--degen-chart-context);
    border: 1px solid var(--degen-chart-context-border);
}
.chart-color-legend .sw-stopped {
    background: color-mix(in srgb, var(--degen-color-error) 25%, transparent);
    border: 1px solid var(--degen-color-error);
}
.chart-color-legend .sw-paused {
    background: color-mix(in srgb, var(--degen-color-warning) 25%, transparent);
    border: 1px solid var(--degen-color-warning);
}
/* A backtest jumped over this stretch because the exchange has no candles for it. */
.chart-color-legend .sw-nodata {
    background: color-mix(in srgb, var(--degen-color-info) 25%, transparent);
    border: 1px solid var(--degen-color-info);
}

/* A live rule that is not running: the next-check cell and the sidebar line say so in colour. */
.bt-kpi-v.bt-not-running-stopped,
.bt-reason.bt-not-running-stopped { color: var(--degen-color-error); }
.bt-kpi-v.bt-not-running-paused,
.bt-reason.bt-not-running-paused { color: var(--degen-color-warning); }

/* ------------------------------------------------------------------ sidebar */

.chart-sidebar {
    /* Trades and decisions sit LEFT of the chart on desktop. The markup keeps the chart first
       so the phone layout, which resets this order, stacks chart above sidebar. */
    order: -1;
    width: 300px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    overflow-y: auto;
}

.sidebar-card {
    background: var(--degen-bg-surface);
    border-radius: 4px;
    padding: 8px 10px;
}

.bt-card-title { margin-bottom: 6px; }

.bt-trades-card { padding: 0; }

.bt-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 10px;
}

.bt-seg {
    display: inline-flex;
    border: 1px solid var(--degen-border-default);
    border-radius: 4px;
    overflow: hidden;
}

.bt-seg span {
    padding: 4px 9px;
    font-size: 11px;
    color: var(--degen-text-tertiary);
    font-family: var(--degen-font-mono);
    cursor: pointer;
    user-select: none;
}

.bt-seg span:hover { background: var(--degen-hover-overlay); }

.bt-seg span.on {
    background: var(--degen-color-primary-muted);
    color: var(--degen-color-primary);
}

/* The Trades/Now switch is the only route back to the trade list, and the Now tab is
   long enough to scroll the switch off the top -- which stranded the user on Now with
   no way back. Pinned, it stays reachable from anywhere in the sidebar.
   Which element scrolls differs by breakpoint: the sidebar itself on desktop, the
   dialog content on phone (see the media query below, where the sidebar goes
   overflow-y: visible). Sticky resolves against whichever is the scroll container,
   so this one rule covers both. */
.bt-sidebar-tabs {
    position: sticky;
    top: 0;
    z-index: 3;
    flex-shrink: 0;
    /* Opaque, or the cards sliding underneath show through the switch. The spread ring
       paints the sidebar's own background over the flex gap and the rounded corners,
       which the element's border box alone leaves transparent; the second shadow is the
       separating edge under it. */
    background: var(--degen-bg-secondary);
    box-shadow: 0 0 0 4px var(--degen-bg-secondary),
                0 7px 6px -6px var(--degen-bg-primary);
    margin-top: 4px;
}

.bt-trades-scroll {
    max-height: 240px;
    overflow-y: auto;
}

.bt-trades-table {
    border-collapse: collapse;
    width: 100%;
    font-family: var(--degen-font-mono);
    font-size: 11px;
}

.bt-trades-table th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--degen-bg-surface);
    text-align: left;
    font-weight: 500;
    color: var(--degen-text-tertiary);
    font-size: 10px;
    padding: 5px 6px;
    border-bottom: 1px solid var(--degen-border-default);
    text-transform: uppercase;
}

.bt-trades-table td {
    padding: 6px;
    border-bottom: 1px solid var(--degen-border-subtle);
    color: var(--degen-text-secondary);
    white-space: nowrap;
}

.bt-trades-table tbody tr { cursor: pointer; }

.bt-trades-table tbody tr:hover td { background: var(--degen-hover-overlay); }

.bt-trades-table tr.sel td {
    background: var(--degen-color-primary-faint);
    color: var(--degen-color-primary);
}

.bt-trades-table tr.sel td:first-child { box-shadow: inset 2px 0 0 var(--degen-color-primary); }

.bt-trades-table .bt-num { text-align: right; }

.bt-trades-table td.bt-pos { color: var(--degen-pnl-positive); }
.bt-trades-table td.bt-neg { color: var(--degen-pnl-negative); }

.bt-side-l { color: var(--degen-color-long); font-weight: 600; }
.bt-trades-table td.bt-side-l { color: var(--degen-color-long); }
.bt-side-s { color: var(--degen-color-short); font-weight: 600; }
.bt-trades-table td.bt-side-s { color: var(--degen-color-short); }

.bt-trades-table td.bt-open { color: var(--degen-color-warning); }

.bt-closing-decision {
    padding: 8px 10px;
    border-top: 1px solid var(--degen-border-subtle);
    cursor: pointer;
}

.bt-closing-decision:hover { background: var(--degen-hover-overlay); }

.bt-closing-decision .bt-reason { margin-top: 3px; }

/* The last review's finding about this trade, under the reasoning it is about. */
.bt-review-note {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-top: 6px;
    font-family: var(--degen-font-mono);
    font-size: 10px;
    line-height: 1.4;
    color: var(--degen-text-secondary);
}

.bt-review-tag {
    flex: 0 0 auto;
    padding: 1px 5px;
    border-radius: 3px;
    border: 1px solid var(--degen-color-primary-muted);
    color: var(--degen-color-primary);
    font-size: 9px;
    letter-spacing: 0.06em;
}

/* Compact trades table (the automation's own chart): closed time, price move, result. */
.bt-trades-compact td { white-space: normal; }
.bt-trades-compact td.bt-mono { color: var(--degen-text-primary); }

/* ------------------------------------------------------------------ Now tab (Activity + Live) */

.bt-now-order-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 4px 0;
    font-family: var(--degen-font-mono);
    font-size: 12px;
}

.bt-now-order-row + .bt-now-order-row { border-top: 1px solid var(--degen-border-subtle); }

.bt-now-away {
    margin-left: auto;
    color: var(--degen-text-tertiary);
    font-size: 11px;
}

.bt-pnl-row {
    display: grid;
    grid-template-columns: 18px 1fr 64px;
    align-items: center;
    gap: 8px;
    padding: 2px 0;
    font-family: var(--degen-font-mono);
    font-size: 11px;
    cursor: pointer;
}

.bt-pnl-row:hover { background: var(--degen-hover-overlay); }

.bt-pnl-row.sel .bt-pnl-n { color: var(--degen-color-primary); }

.bt-pnl-n { color: var(--degen-text-tertiary); }

.bt-pnl-v { text-align: right; color: var(--degen-text-secondary); }

.bt-bar {
    height: 6px;
    border-radius: 4px;
    background: var(--degen-bg-elevated);
    overflow: hidden;
}

.bt-bar i { display: block; height: 100%; }

.bt-bar-pos { background: var(--degen-pnl-positive); }
.bt-bar-neg { background: var(--degen-pnl-negative); }

.bt-rule-text {
    font-size: 12px;
    line-height: 1.5;
    color: var(--degen-text-secondary);
    word-break: break-word;
}

.bt-rule-text p { margin: 0; display: inline; }

.bt-rule-text p + p::before { content: " "; }

.bt-rule-text strong { color: var(--degen-text-primary); font-weight: 600; }

.bt-rule-indicators { margin-top: 6px; }

.bt-ind-row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    line-height: 1.5;
}

.bt-ind-tf {
    color: var(--degen-color-primary);
    font-size: 10px;
    font-family: var(--degen-font-mono);
    font-weight: 600;
    flex-shrink: 0;
}

.bt-ind-names {
    color: var(--degen-text-primary);
    font-size: 11px;
    font-family: var(--degen-font-mono);
    word-break: break-word;
}

.bt-highlight-toggle {
    padding: 0 4px;
    color: var(--degen-text-secondary);
    font-size: 11px;
}

.pulse-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--degen-color-primary);
    flex-shrink: 0;
    animation: pulse-backtest 1.5s ease-in-out infinite;
}

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

/* ------------------------------------------------------------------ tablet */

@media (max-width: 960px) {
    .mud-dialog.backtest-live-dialog {
        min-width: unset;
        width: 100%;
    }

    .bt-kpi { flex-basis: 22%; }
}

/* ------------------------------------------------------------------ phone */

@media (max-width: 768px) {
    .mud-dialog.backtest-live-dialog {
        max-height: 90vh;
        max-height: 90dvh;
    }

    /* Two deliberate rows: the rule's identity, then the controls. Left to wrap on its own the
       header made three ragged rows, and the name ran underneath the close button. */
    .bt-activity-ident,
    .bt-activity-controls {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-basis: 100%;
        min-width: 0;
    }

    /* The identity row never wraps: the name shortens instead, so the row stays one line however
       long the rule is called. The controls row does wrap, since its buttons cannot shrink. */
    .bt-activity-ident { flex-wrap: nowrap; }
    .bt-activity-controls { flex-wrap: wrap; }

    /* The back button and the id badge are fixed furniture on that row: only the name gives way,
       or a squeezed badge breaks "#653" across two lines. */
    .bt-activity-ident .bt-back-btn,
    .bt-activity-ident .bt-rule-badge {
        flex: none;
        white-space: nowrap;
    }

    /* MudBlazor pins the close button at top 8px / right 8px at 48px square, and the app-wide
       title padding (16px 20px !important) leaves only 20px of that clear, so the identity row
       reserves the remaining 36px plus a little air. Measured in the browser, not guessed. */
    .bt-activity-ident { padding-inline-end: 40px; }

    /* The name takes whatever the badge and back button leave, and ellipsises there rather than
       at a fixed 260px that a 393px screen does not have. */
    .bt-activity-rule-name {
        flex: 1 1 auto;
        min-width: 0;
        max-width: none;
    }

    .mud-dialog.backtest-live-dialog .mud-dialog-content {
        padding: 12px;
        overflow-y: auto;
    }

    .bt-title { gap: 6px; }
    .bt-title-mode,
    .bt-title-asset { font-size: 15px; }
    .bt-rule-pill { max-width: 100%; }

    .bt-kpis { margin: -12px -12px 12px; }

    .bt-kpi {
        padding: 6px 10px;
        flex-basis: 30%;
    }

    .bt-kpi-v { font-size: 14px; }

    /* The small values are sentences ("Stopped since 25 Aug"), not figures. On a phone tile they
       get a second line instead of being cut off mid-word. */
    .bt-kpi-v-sm {
        white-space: normal;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        line-height: 1.3;
    }

    /* Net PnL (or the live eval readout) and the run controls span the full row. */
    .bt-kpis .bt-kpi-hero,
    .bt-kpis .bt-kpi-controls { flex-basis: 100%; }

    .bt-kpi-controls { justify-content: flex-start; }

    .chart-layout {
        flex-direction: column;
        height: auto;
    }

    .backtest-chart-column {
        flex: none;
    }

    .backtest-chart-area {
        height: 350px;
        flex: none;
        touch-action: none;
    }

    .chart-sidebar {
        order: 0;
        width: 100%;
        overflow-y: visible;
    }
}

/* ------------------------------------------------------------------ small phone */

@media (max-width: 480px) {
    .backtest-chart-column { --bt-lane-gutter: 60px; }

    .backtest-chart-area {
        height: 260px;
    }

    .bt-kpi { flex-basis: 46%; }
}

/* ---------------------------------------------------------------- reasoning dialog frame
   MudBlazor renders the dialog and its action buttons outside CandleReasoningDialog's CSS
   scope, so these cannot live in CandleReasoningDialog.razor.css. */

.mud-dialog.candle-reasoning-dialog .jump-btn {
    color: var(--degen-text-secondary);
    border-color: var(--degen-border-default);
    border-radius: 4px;
    font-size: 12px;
}

.mud-dialog.candle-reasoning-dialog .close-btn-primary {
    border-radius: 4px;
    font-size: 12px;
    font-weight: 700;
}

@media (max-width: 600px) {
    .mud-dialog.candle-reasoning-dialog {
        width: 100vw;
        max-width: 100vw;
        height: 100vh;
        max-height: 100vh;
        margin: 0;
        border-radius: 0;
    }

    .mud-dialog.candle-reasoning-dialog .mud-dialog-content {
        max-height: calc(100vh - 128px);
        overflow-y: auto;
    }
}
