/* ============================================================================
   AiStocksPro — Bloomberg-style terminal theme
   Dark, dense, data-first. Built on Bootstrap 5 grid + utilities.
   ============================================================================ */

:root {
    --bg:          #0a0e14;
    --bg-panel:    #10151f;
    --bg-panel-2:  #141a26;
    --border:      #1d2533;
    --text:        #d7dde7;
    --text-dim:    #7b8596;
   --accent:      #f5a623;   /* terminal amber 
    /*--accent:       #7c6af7; */
    --up:          #18c47c;
    --down:        #f6465d;
    --flat:        #8d97a8;
    --mono:        "IBM Plex Mono", SFMono-Regular, Consolas, monospace;
    --sans:        "Inter", system-ui, -apple-system, sans-serif;
}

html, body { background: var(--bg); color: var(--text); font-family: var(--sans); font-size: 14px; }
/* Stop any one wide element (a table, a tooltip bubble) from letting the whole
   page drift sideways on mobile. overflow-x: CLIP (not hidden) so it doesn't
   create a scroll container that would break the sticky .app-header. */
html { overflow-x: clip; }
body { overflow-x: clip; max-width: 100%; }
.app-main  { min-height: calc(100vh - 170px); max-width: 1600px; margin: 0 auto; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: #ffc44d; }
/*a:hover { color: #7c6af7; }*/

/* ── Ticker strip ─────────────────────────────────────────────────────── */
.ticker-strip {
    display: flex; align-items: center; gap: 12px;
    background: #070a0f; border-bottom: 1px solid var(--border);
    padding: 4px 14px; overflow: hidden; white-space: nowrap;
    font-family: var(--mono); font-size: 12px;
}
/* Auto-scrolling marquee: the viewport clips, the track slides continuously.
   No manual swipe needed (nobody scrolls a header strip on mobile). min-width:0
   lets this flex:1 child be clipped by the strip's overflow:hidden. */
.ticker-inner { flex: 1; min-width: 0; overflow: hidden; }
/* The track holds the items rendered TWICE back-to-back; animating to -50%
   lands exactly on the duplicate's start, so the loop is seamless (no jump).
   --ticker-dur is set inline by app.js, scaled to item count for steady speed. */
.ticker-track { display: inline-flex; gap: 14px; white-space: nowrap; will-change: transform;
    animation: ticker-marquee var(--ticker-dur, 40s) linear infinite; }
.ticker-strip:hover .ticker-track,
.ticker-strip:focus-within .ticker-track { animation-play-state: paused; }
@keyframes ticker-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}
/* Accessibility + the degenerate "content fits, no need to scroll" case:
   no duplicate is rendered, so freeze the track in place. */
@media (prefers-reduced-motion: reduce) { .ticker-track { animation: none; } }
.ticker-track.no-loop { animation: none; }
/* Each item stays on one line and never shrinks — without flex:0 0 auto a flex
   item collapses to its narrowest content (one char per line: "lau/rus/lab/s"). */
.ticker-item { flex: 0 0 auto; white-space: nowrap; }
/* Separator dot between indices so each reads as a distinct unit (the values
   themselves contain spaces). A dot BEFORE every item except the strip's first
   gives clean "A · B · C"; on the duplicated loop the seam also gets a dot, so
   the marquee stays evenly punctuated all the way round. */
.ticker-item:not(:first-child)::before {
    content: "·"; color: var(--text-dim); margin-right: 14px; font-weight: 700;
}
.ticker-item strong { color: var(--text); font-weight: 500; margin-right: 6px; }
/* Pinned to the right, never shrinks, with a divider so the scrolling indices
   visually stop before it (the gap also prevents the last item touching LIVE). */
.ticker-status { flex: 0 0 auto; font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
    padding-left: 12px; border-left: 1px solid var(--border); background: #070a0f; }
.ticker-status .dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; }
.dot-open   { background: var(--up);   box-shadow: 0 0 6px var(--up); }
.dot-closed { background: var(--down); }

/* ── Sticky header ────────────────────────────────────────────────────── */
/* Pin the whole header block (ticker + navbar + admin sub-nav) to the top so
   the menu — and the live index ticker — stay visible on long pages. Wrapping
   them keeps it robust to height changes and to the logged-out layout (no
   ticker). z-index sits above page content but below the dropdowns it opens. */
.app-header { position: sticky; top: 0; z-index: 1030; }
/* When the mobile drawer is open, raise the whole header's stacking context
   above the body-level backdrop — otherwise the drawer (a child of .app-header,
   z-index 1030) stays trapped BELOW the backdrop (1084), which then blurs it and
   eats its clicks. */
body.nav-open .app-header { z-index: 1086; }

/* ── Navbar ───────────────────────────────────────────────────────────── */
.app-navbar { background: var(--bg-panel); border-bottom: 1px solid var(--border); padding: .45rem 0; }
.app-navbar .navbar-brand { font-family: var(--mono); font-weight: 600; letter-spacing: .04em; color: var(--text); font-size: 1.1rem; }
.app-navbar .navbar-brand span  { color: var(--accent); }
.app-navbar .navbar-brand small { color: var(--text-dim); font-size: .6em; margin-left: 5px; letter-spacing: .25em; }
.app-navbar .nav-link { color: var(--text-dim); font-size: 13px; font-weight: 500; letter-spacing: .03em; padding: .5rem .8rem; }
.app-navbar .nav-link:hover  { color: var(--text); }
.app-navbar .nav-link.active { color: var(--accent); border-bottom: 2px solid var(--accent); }

/* ── Mobile nav drawer ──────────────────────────────────────────────────────
   Below lg the Bootstrap collapse is restyled as a right-side slide-in drawer
   instead of pushing page content down. Bootstrap's collapse JS still toggles
   .show; we only change how the open state looks + add a backdrop (app.js). */
@media (max-width: 991.98px) {
    .navbar-collapse {
        position: fixed; top: 0; right: 0; z-index: 1085;
        width: min(82vw, 320px); height: 100dvh !important; max-height: 100dvh;
        background: var(--bg-panel); border-left: 1px solid var(--border);
        box-shadow: -18px 0 50px rgba(0,0,0,.5);
        padding: 64px 18px 24px; overflow-y: auto;
        /* Keep it in the layout (override Bootstrap's display:none) and drive the
           slide purely from our transform on .show — disable Bootstrap's height
           animation so it can't fight the transform. */
        display: block !important;
        transform: translateX(100%); visibility: hidden;
        transition: transform .26s ease, visibility 0s linear .26s;
    }
    .navbar-collapse.show {
        transform: translateX(0); visibility: visible;
        transition: transform .26s ease, visibility 0s;
    }
    /* Neutralise Bootstrap's collapsing height animation on this drawer. */
    .navbar-collapse.collapsing { height: 100dvh !important; transition: transform .26s ease; }

    /* Stack the two nav groups vertically and give links breathing room. */
    .navbar-collapse .navbar-nav { width: 100%; }
    .app-navbar .navbar-nav .nav-link { padding: .7rem .2rem; font-size: 15px; }
    .app-navbar .nav-link.active { border-bottom: 0; color: var(--accent); }
    .navbar-collapse .navbar-nav.ms-auto { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 12px; }
    .navbar-collapse .research-btn { width: 100%; justify-content: center; margin-bottom: 10px; }
    .navbar-collapse .plan-chip { display: inline-block; margin-bottom: 10px; }
    /* User dropdown opens inline inside the drawer (not a floating popover). */
    .navbar-collapse .dropdown-menu { position: static; float: none; border: 0; background: transparent; box-shadow: none; padding-left: 4px; }
    .navbar-collapse .dropdown-toggle { padding-left: .2rem; }

    /* Backdrop behind the drawer (element added by app.js). */
    .nav-backdrop {
        position: fixed; inset: 0; z-index: 1084;
        background: rgba(4,7,12,.6); backdrop-filter: blur(1px);
        opacity: 0; transition: opacity .26s ease;
    }
    .nav-backdrop.show { opacity: 1; }
    /* Close (×) button pinned top-right of the open drawer (added by app.js). */
    .nav-drawer-close {
        position: absolute; top: 14px; right: 16px; z-index: 2;
        background: none; border: 0; color: var(--text-dim);
        font-size: 26px; line-height: 1; cursor: pointer; padding: 0 4px;
    }
    .nav-drawer-close:hover { color: var(--text); }
    body.nav-open { overflow: hidden; }
}
.plan-chip {
    font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
    border: 1px solid var(--accent); color: var(--accent); padding: 3px 10px; border-radius: 2px;
}
.btn-accent { background: var(--accent); border: none; color: #14100a; font-weight: 600; }
.btn-accent:hover { background: #ffc44d; color: #14100a; }
/*.btn-accent:hover { background: #7c6af7; color: #14100a; }*/

/* ── Admin sub-navigation ─────────────────────────────────────────────── */
/* Part of the sticky .app-header wrapper, so it pins along with the navbar. */
.admin-subnav { background: var(--bg-panel-2); border-bottom: 1px solid var(--border); }
.admin-subnav a {
    display: inline-block; padding: 8px 14px; color: var(--text-dim);
    font-size: 12.5px; font-weight: 500; letter-spacing: .05em; text-transform: uppercase;
}
.admin-subnav a.active { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); }

/* ── Panels (custom, not Bootstrap cards) ─────────────────────────────── */
.panel { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 3px; margin-bottom: 1rem; }
.panel-head {
    display: flex; justify-content: space-between; align-items: center; gap: 10px;
    padding: 9px 14px; border-bottom: 1px solid var(--border);
}
.panel-title { font-size: 11.5px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--text-dim); margin: 0; }
.panel-body  { padding: 14px; }
.panel-body.p-0 { padding: 0; }

/* ── KPI stat blocks ──────────────────────────────────────────────────── */
.kpi { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 3px; padding: 14px 16px; height: 100%; }
.kpi .kpi-label { font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim); }
.kpi .kpi-value { font-family: var(--mono); font-size: 1.55rem; font-weight: 600; margin-top: 2px; }
.kpi .kpi-sub   { font-size: 12px; color: var(--text-dim); }

/* ── Data tables ──────────────────────────────────────────────────────── */
.table-terminal { width: 100%; margin: 0; font-size: 13px; color: var(--text); }
.table-terminal thead th {
    background: var(--bg-panel-2); color: var(--text-dim); font-size: 10.5px;
    letter-spacing: .12em; text-transform: uppercase; font-weight: 600;
    border-bottom: 1px solid var(--border); padding: 8px 12px; white-space: nowrap;
}
.table-terminal tbody td { padding: 7px 12px; border-bottom: 1px solid #151b27; vertical-align: middle; }
.table-terminal tbody tr:hover td { background: #161d2b; }
.table-terminal .sym { font-family: var(--mono); font-weight: 600; color: var(--text); }

/* symbol cell: LTP + NSE link row, with an hourly sparkline below */
.sym-meta { display: flex; align-items: center; gap: 8px; margin-top: 1px; }
.sym-ltp  { font-size: 11px; }
.nse-link {
    font-family: var(--mono); font-size: 9.5px; font-weight: 600;
    letter-spacing: .06em; color: var(--text-dim); text-decoration: none;
    padding: 1px 5px; border: 1px solid var(--border); border-radius: 2px;
    white-space: nowrap; line-height: 1.4; transition: color .15s, border-color .15s;
}
.nse-link:hover { color: var(--accent); border-color: var(--accent); }
.pick-spark { display: block; width: 78px; height: 22px; margin-top: 4px; }
.pick-spark canvas { width: 78px !important; height: 22px !important; display: block; }
.pick-spark.spark-empty { display: none; }
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.num-up   { color: var(--up); }
.num-down { color: var(--down); }
.num-flat { color: var(--flat); }

/* direction + status badges */
.badge-dir { font-family: var(--mono); font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 2px; letter-spacing: .08em; }
.dir-gain { font-size: 11px; font-weight: 600; margin-top: 4px; white-space: nowrap; }
.dir-gain-pct { opacity: .75; font-weight: 500; }
.badge-buy  { background: rgba(24,196,124,.12); color: var(--up);   border: 1px solid rgba(24,196,124,.4); }
.badge-sell { background: rgba(246,70,93,.12);  color: var(--down); border: 1px solid rgba(246,70,93,.4); }
/* AI review chip (Part 2) — a quiet second-opinion mark, not a loud "approved"
   stamp. It doubles as a tooltip trigger inside a .tt-wrap (.ai-tt), so the help
   bubble matches every other tooltip on the site instead of a native title. */
.ai-chip { font-family: var(--mono); font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 2px; letter-spacing: .06em; white-space: nowrap; cursor: help; line-height: 1.4; display: inline-block; }
button.ai-chip { background: transparent; -webkit-appearance: none; appearance: none; }
.ai-clear   { background: rgba(24,196,124,.10); color: var(--up);     border: 1px solid rgba(24,196,124,.35); }
.ai-caution { background: rgba(245,166,35,.12); color: var(--accent); border: 1px solid rgba(245,166,35,.45); }
.ai-clear:hover, .ai-clear:focus     { border-color: rgba(24,196,124,.7); outline: none; }
.ai-caution:hover, .ai-caution:focus { border-color: rgba(245,166,35,.8);  outline: none; }
/* Market-closed / holiday banner — restrained editorial strip, amber accent.
   Shown on the dashboard when the NSE is closed (holiday / weekend / after-hours)
   so the stale last-close view reads as intentional, not a broken feed. */
.mkt-banner {
    display: flex; align-items: center; gap: 10px;
    background: rgba(246,70,93,.12); border: 1px solid rgba(246,70,93,.45);
    border-left: 3px solid var(--down); border-radius: 3px;
    padding: 10px 14px; margin-bottom: 1rem;
}
.mkt-banner .mkt-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--down); flex: 0 0 auto;
    box-shadow: 0 0 6px rgba(246,70,93,.6);
}
.mkt-banner .mkt-label {
    font-size: 12.5px; font-weight: 600; letter-spacing: .02em; color: var(--down);
}
.mkt-banner .mkt-sub { font-size: 11.5px; color: var(--text-dim); margin-left: auto; }
.mkt-banner[data-state="open"] { display: none; }
/* SELL "info only" chip (2026-07-08) — quiet grey mark beside every SELL badge:
   the short side is informational until it clears the profitability bar. */
.sell-info { background: rgba(141,151,168,.12); color: var(--flat); border: 1px solid rgba(141,151,168,.4); cursor: help; }
.sell-info:hover, .sell-info:focus { border-color: rgba(141,151,168,.75); outline: none; }
/* Instant-Research lightning chip — clickable (pointer, not help); amber accent. */
.rsr-chip { background: rgba(245,166,35,.12); color: var(--accent); border: 1px solid rgba(245,166,35,.45); cursor: pointer; padding: 2px 7px; }
.rsr-chip:hover, .rsr-chip:focus { background: rgba(245,166,35,.22); border-color: rgba(245,166,35,.85); outline: none; }
/* Position-health chips (Feature 1) — reuse .ai-chip box; own colour set. */
.hl-strong  { background: rgba(24,196,124,.10); color: var(--up);     border: 1px solid rgba(24,196,124,.35); }
.hl-neutral { background: rgba(150,150,150,.10); color: var(--text-dim); border: 1px solid rgba(150,150,150,.32); }
.hl-weak    { background: rgba(246,70,93,.12);  color: var(--down);   border: 1px solid rgba(246,70,93,.45); }
.hl-strong:hover, .hl-strong:focus   { border-color: rgba(24,196,124,.7); outline: none; }
.hl-neutral:hover, .hl-neutral:focus { border-color: rgba(150,150,150,.6); outline: none; }
.hl-weak:hover, .hl-weak:focus       { border-color: rgba(246,70,93,.8);  outline: none; }
/* Opening-gap chips — reuse the .ai-chip box geometry; up/down colour set. */
.gap-chip { font-family: var(--mono); font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 2px; letter-spacing: .04em; white-space: nowrap; cursor: help; line-height: 1.4; display: inline-block; }
.gap-up   { background: rgba(24,196,124,.10); color: var(--up);   border: 1px solid rgba(24,196,124,.35); }
.gap-down { background: rgba(246,70,93,.10);  color: var(--down); border: 1px solid rgba(246,70,93,.35); }
.gap-up.gap-strong   { background: rgba(24,196,124,.18); border-color: rgba(24,196,124,.6); }
.gap-down.gap-strong { background: rgba(246,70,93,.18);  border-color: rgba(246,70,93,.6); }
.gap-up:hover, .gap-up:focus     { border-color: rgba(24,196,124,.7); outline: none; }
.gap-down:hover, .gap-down:focus { border-color: rgba(246,70,93,.8);  outline: none; }
.gap-tt .tt-bubble strong { display: block; margin-bottom: 4px; font-weight: 600; font-size: 11.5px; letter-spacing: .04em; }
/* Health read placed UNDER the symbol (avoids a 7th column that overflows). */
.pos-read { margin-top: 3px; line-height: 1; }
.pos-read .ai-chip { font-size: 9.5px; padding: 1px 5px; }
.pos-read .gap-chip { font-size: 9.5px; padding: 1px 5px; }
/* Exit (square-off) button — sits under the symbol for the same reason.
   Fires on the first tap with no confirmation, so it is tinted like an exit
   rather than styled as just another neutral outline button. */
.pos-actions { margin-top: 4px; line-height: 1; }
.pos-actions .btn-pos-exit {
    font-size: 10.5px; font-weight: 600; letter-spacing: .04em; white-space: nowrap;
    color: var(--down); border-color: rgba(246, 70, 93, .45); background: rgba(246, 70, 93, .08);
}
.pos-actions .btn-pos-exit:hover:not(:disabled),
.pos-actions .btn-pos-exit:focus-visible:not(:disabled) {
    color: #fff; background: var(--down); border-color: var(--down);
}
.pos-actions .btn-pos-exit:disabled {
    opacity: .75; color: var(--flat); border-color: var(--border); background: transparent;
}
/* Broker orders in flight, above the positions table (dashboard Manual panel) */
.mo-flight { padding: 4px 8px 0; }
.mo-flight-row { font-size: 11.5px; font-family: var(--mono); padding: 2px 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.mo-flight-row.is-live { color: var(--accent); }
.mo-flight-row.is-ok   { color: var(--up); }
.mo-flight-row.is-err  { color: var(--down); }
.mo-flight-row .text-dim { font-family: inherit; }
/* heading line inside the AI tooltip bubble */
.ai-tt .tt-bubble strong { display: block; margin-bottom: 4px; font-weight: 600; font-size: 11.5px; letter-spacing: .04em; }
.ai-tt.ai-tt .tt-bubble { max-width: 240px; }
.badge-st { font-size: 10.5px; font-weight: 600; letter-spacing: .07em; padding: 3px 8px; border-radius: 2px; }
.st-OPEN       { background: rgba(245,166,35,.12); color: var(--accent); }
.st-TARGET_HIT { background: rgba(24,196,124,.15); color: var(--up); }
.st-SL_HIT     { background: rgba(246,70,93,.15);  color: var(--down); }
.st-EXPIRED    { background: rgba(141,151,168,.15); color: var(--flat); }
.st-INVALIDATED{ background: rgba(141,151,168,.15); color: var(--flat); }
.st-PENDING    { background: rgba(245,166,35,.12); color: var(--accent); }
.st-SENT       { background: rgba(24,196,124,.15); color: var(--up); }
.st-FAILED     { background: rgba(246,70,93,.15);  color: var(--down); }
.st-ACTIVE     { background: rgba(24,196,124,.15); color: var(--up); }
.st-EXPIRED_SUB{ background: rgba(141,151,168,.15); color: var(--flat); }
.st-SUCCESS    { background: rgba(24,196,124,.15); color: var(--up); }
.st-RUNNING    { background: rgba(245,166,35,.12); color: var(--accent); }

/* strategy maturity badge (review #21-24) — honest gate state, not a sales stamp */
.mat-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 10.5px;
    font-weight: 600; letter-spacing: .06em; padding: 3px 9px; border-radius: 2px;
    text-transform: uppercase; white-space: nowrap; }
.mat-watch { background: rgba(141,151,168,.12); color: var(--text-dim); border: 1px solid rgba(141,151,168,.35); }
.mat-paper { background: rgba(245,166,35,.12);  color: var(--accent);   border: 1px solid rgba(245,166,35,.4); }
.mat-real  { background: rgba(24,196,124,.13);  color: var(--up);       border: 1px solid rgba(24,196,124,.4); }
.mat-over  { font-size: 8.5px; letter-spacing: .1em; opacity: .7; padding: 1px 4px;
    border: 1px solid currentColor; border-radius: 2px; }

/* per-pick risk-sizing cell (review #15/#25) — advisory math, display only */
.risk-cell { font-family: var(--mono); font-size: 11.5px; line-height: 1.45; white-space: nowrap; }
.risk-cell .rk-qty { color: var(--text); font-weight: 600; }
.risk-cell .rk-sub { color: var(--text-dim); font-size: 10.5px; }
.risk-cell .rk-na  { color: var(--text-dim); }

/* dashboard "read the manual" link */
.man-link { font-size: 12.5px; color: var(--text-dim); border: 1px solid var(--border);
    border-radius: 3px; padding: 4px 12px; text-decoration: none; transition: all .15s ease; }
.man-link:hover { color: var(--accent); border-color: var(--accent); background: rgba(245,166,35,.07); }

/* themed admin toggle switch (matches the amber terminal theme, not BS default).
   The knob is drawn via background-image — it MUST be set on the resting state too,
   or the switch collapses to a plain square that looks like a checkbox/radio. */
.admin-switch { padding-left: 3.2rem; min-height: 1.5rem; display: flex; align-items: center; }
.admin-switch .form-check-input { width: 2.4rem; height: 1.3rem; margin-left: -3.2rem; margin-top: 0;
    border-radius: 1.3rem; background-color: #3a4252; border: 1.5px solid #8f9aad;
    cursor: pointer; box-shadow: inset 0 1px 2px rgba(0,0,0,.35);
    transition: background-color .15s ease, border-color .15s ease, background-position .15s ease;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23eef1f6'/%3e%3c/svg%3e");
    background-position: left center; background-repeat: no-repeat; }
.admin-switch .form-check-input:hover { border-color: #aab4c4; }
.admin-switch .form-check-input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(245,166,35,.2);
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23eef1f6'/%3e%3c/svg%3e"); }
.admin-switch .form-check-input:checked { background-color: var(--accent); border-color: var(--accent);
    background-position: right center;
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2314100a'/%3e%3c/svg%3e"); }
.admin-switch .form-check-label { font-size: 13px; color: var(--text); cursor: pointer; display: flex;
    align-items: center; gap: 8px; }
.admin-switch-state { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .06em;
    text-transform: uppercase; padding: 1px 6px; border-radius: 2px; border: 1px solid; }
.admin-switch-state.on  { color: var(--accent); border-color: rgba(245,166,35,.5); background: rgba(245,166,35,.1); }
.admin-switch-state.off { color: var(--text-dim); border-color: rgba(141,151,168,.35); background: rgba(141,151,168,.08); }
.admin-switch-help { font-size: 11.5px; margin-top: 5px; margin-left: 3rem; max-width: 520px; line-height: 1.45; }

/* shadow calibrated-confidence hint next to the live value (review #10-12) */
.conf-cal { font-family: var(--mono); font-size: 10px; font-weight: 600; color: var(--text-dim);
    border: 1px solid rgba(141,151,168,.35); border-radius: 2px; padding: 0 3px; cursor: help; white-space: nowrap; }

/* confidence meter */
.conf-wrap { display: flex; align-items: center; gap: 8px; min-width: 110px; }
.conf-bar  { flex: 1; height: 5px; background: #1a2130; border-radius: 2px; overflow: hidden; }
.conf-fill { height: 100%; border-radius: 2px; background: linear-gradient(90deg, #f5a623, #18c47c); }
.conf-val  { font-family: var(--mono); font-size: 12px; width: 30px; text-align: right; }
/* SELL rows. Confidence measures how sure the AI is of its DIRECTION, and on a
   short that direction is down — a bare "94" next to a green bar reads as
   "strong buy" at a glance, which is exactly how a user came to buy a
   94-confidence SHORT on 2026-07-29. So the bar turns red, the number carries
   a SHORT tag, and the row gets a red edge. */
.conf-wrap.is-short .conf-fill { background: linear-gradient(90deg, #f5a623, #f6465d); }
.conf-dir { font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .06em;
            color: var(--down); border: 1px solid rgba(246,70,93,.45); border-radius: 2px;
            padding: 1px 4px; white-space: nowrap; }
tr.row-short > td:first-child { box-shadow: inset 3px 0 0 var(--down); }

/* rank chip */
.rank-chip {
    font-family: var(--mono); display: inline-block; min-width: 26px; text-align: center;
    background: var(--bg-panel-2); border: 1px solid var(--border); color: var(--accent);
    font-size: 12px; font-weight: 600; padding: 2px 5px; border-radius: 2px;
}

/* ── Forms ────────────────────────────────────────────────────────────── */
.form-control, .form-select {
    background: var(--bg-panel-2); border: 1px solid var(--border); color: var(--text);
    font-size: 13.5px; border-radius: 2px;
}
.form-control:focus, .form-select:focus {
    background: var(--bg-panel-2); color: var(--text);
    border-color: var(--accent); box-shadow: 0 0 0 2px rgba(245,166,35,.15);
}
.form-label { font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); }
.btn { border-radius: 2px; font-size: 13px; }
.btn-outline-light { border-color: var(--border); color: var(--text-dim); }
.btn-outline-light:hover { background: var(--bg-panel-2); color: var(--text); border-color: var(--text-dim); }

/* ── Auth / landing ───────────────────────────────────────────────────── */
.auth-wrap { max-width: 420px; margin: 7vh auto; }
.hero {
    padding: 9vh 0 6vh; text-align: center;
}
.hero h1 { font-weight: 700; font-size: clamp(2rem, 5vw, 3.4rem); letter-spacing: -.02em; }
.hero h1 span { color: var(--accent); }
.hero p.lead { color: var(--text-dim); max-width: 640px; margin: 1rem auto; }
.feature-line { border-top: 1px solid var(--border); padding: 22px 0; }
.feature-line h5 { font-size: 15px; font-weight: 600; }
.feature-line p  { font-size: 13px; color: var(--text-dim); margin: 0; }
.mono-tag { font-family: var(--mono); color: var(--accent); font-size: 12px; letter-spacing: .15em; }

/* ── Stock page quote header ──────────────────────────────────────────── */
.quote-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 14px; }
.quote-head .q-sym  { font-family: var(--mono); font-size: 1.6rem; font-weight: 600; }
.quote-head .q-ltp  { font-family: var(--mono); font-size: 1.6rem; }
.quote-head .q-name { color: var(--text-dim); font-size: 13px; }
.ind-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 1px; background: var(--border); }
.ind-cell { background: var(--bg-panel); padding: 10px 12px; }
.ind-cell .k { font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-dim); }
.ind-cell .v { font-family: var(--mono); font-size: 14px; margin-top: 2px; }

/* ── Plans ────────────────────────────────────────────────────────────── */
.plan-col { background: var(--bg-panel); border: 1px solid var(--border); border-radius: 3px; padding: 24px; height: 100%; }
.plan-col.highlight { border-color: var(--accent); }
.plan-col .p-name  { font-size: 12px; letter-spacing: .18em; text-transform: uppercase; color: var(--text-dim); }
.plan-col .p-price { font-family: var(--mono); font-size: 2rem; font-weight: 600; margin: 6px 0 14px; }
.plan-col .p-price small { font-size: .45em; color: var(--text-dim); }
.plan-col ul { list-style: none; padding: 0; margin: 0 0 18px; font-size: 13px; }
.plan-col ul li { padding: 5px 0; border-bottom: 1px dashed #1a2130; color: var(--text-dim); }
.plan-col ul li.yes { color: var(--text); }
.plan-col ul li.yes::before { content: "✓ "; color: var(--up); }
.plan-col ul li.no::before  { content: "× "; color: var(--down); }

/* gated content blur for free plan */
.gated { position: relative; }
.gated .gated-blur { filter: blur(5px); pointer-events: none; user-select: none; }
.gated .gated-overlay {
    position: absolute; inset: 0; display: flex; flex-direction: column; gap: 8px;
    align-items: center; justify-content: center; text-align: center;
    background: rgba(10,14,20,.55); z-index: 5;
}

/* ── Footer ───────────────────────────────────────────────────────────── */
.app-footer { border-top: 1px solid var(--border); background: var(--bg-panel); padding: 14px 0; font-size: 12px; }
.footer-brand { font-family: var(--mono); color: var(--accent); letter-spacing: .08em; }
.footer-disclaimer { color: var(--text-dim); font-size: 11px; }

/* ── Misc ─────────────────────────────────────────────────────────────── */
.text-dim { color: var(--text-dim) !important; }
.last-updated { font-family: var(--mono); font-size: 11px; color: var(--text-dim); }

/* ── Feed health indicator (dashboard header) ─────────────────────────── */
.feed-health { font-family: var(--mono); font-size: 11px; color: var(--text-dim); white-space: nowrap; cursor: default; }
.feed-health .fh-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 5px; vertical-align: middle; background: var(--text-dim); }
.feed-health.fh-ok      .fh-dot   { background: var(--up);   box-shadow: 0 0 6px var(--up); }
.feed-health.fh-ok      .fh-label { color: var(--up); }
.feed-health.fh-failed  .fh-dot   { background: var(--down); box-shadow: 0 0 6px var(--down); animation: fh-pulse 1.4s ease-in-out infinite; }
.feed-health.fh-failed  .fh-label { color: var(--down); font-weight: 600; }
.feed-health.fh-running .fh-dot   { background: #e0a93b; }
.feed-health.fh-running .fh-label { color: #e0a93b; }
.feed-health .fh-source { font-weight: 600; letter-spacing: .04em; }
/* upstox = primary (calm); yahoo = fallback (amber, stands out) */
.feed-health .fh-source.src-upstox { color: var(--text-dim); }
.feed-health .fh-source.src-yahoo  { color: #e0a93b; }
.feed-health-reason { font-family: var(--mono); font-size: 11px; color: var(--down); margin: -2px 0 10px; }
@keyframes fh-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.chart-box { position: relative; height: 320px; }
.chart-box-sm { position: relative; height: 220px; }

/* Themed confirm dialog (window.appConfirm) — replaces native confirm() */
.app-confirm-overlay {
    position: fixed; inset: 0; z-index: 1090;
    background: rgba(4, 7, 12, .6); backdrop-filter: blur(2px);
    display: flex; align-items: center; justify-content: center; padding: 20px;
    animation: ac-fade .12s ease;
}
@keyframes ac-fade { from { opacity: 0; } to { opacity: 1; } }
.app-confirm {
    background: var(--bg-panel); border: 1px solid var(--border); border-radius: 8px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, .55); max-width: 380px; width: 100%;
    padding: 20px;
}
.app-confirm-msg {
    color: var(--text); font-size: 14px; line-height: 1.5; margin-bottom: 18px;
}
.app-confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }
/* Trade P&L doughnuts */
.pnl-pie { position: relative; height: 190px; }
.pnl-pie-title {
    font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
    color: var(--text-dim); text-align: center; margin-bottom: 6px;
}
.pnl-cap {
    color: var(--text-dim); font-size: 11.5px; text-align: center; margin-top: 4px;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: #222b3d; border-radius: 5px; }
::-webkit-scrollbar-track { background: var(--bg); }

/* ── Sortable tables ──────────────────────────────────────────────────── */
table.sortable thead th:not(.nosort) {
    cursor: pointer; user-select: none; position: relative;
    padding-right: 16px;            /* room for the sort arrow */
    transition: color .12s;
}
table.sortable thead th:not(.nosort):hover { color: var(--text); }
/* neutral hint arrow on hover; solid arrow when actively sorted */
table.sortable thead th:not(.nosort)::after {
    content: "⇅"; position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
    font-size: 9px; opacity: 0; transition: opacity .12s; color: var(--text-dim);
}
table.sortable thead th:not(.nosort):hover::after { opacity: .5; }
table.sortable thead th.sort-asc::after  { content: "▲"; opacity: 1; color: var(--accent); }
table.sortable thead th.sort-desc::after { content: "▼"; opacity: 1; color: var(--accent); }
/* keep the tooltip "i" icon clickable without triggering a sort feels wrong —
   the whole header sorts; the tooltip still opens on hovering the icon. */

@media (max-width: 768px) {
    html, body { font-size: 13px; }
    .kpi .kpi-value { font-size: 1.25rem; }
    .chart-box { height: 240px; }
    .pnl-pie { height: 170px; }
    .quote-head .q-sym, .quote-head .q-ltp { font-size: 1.25rem; }
}

/* ── Mobile: stacked-card tables (no horizontal scroll) ─────────────────────
   On phones a wide data table either overflows the viewport (the whole page
   drifts sideways) or needs an awkward horizontal scroller. Instead we turn
   every .table-terminal row into a compact card: the symbol heads the card and
   each remaining cell becomes a "Label  value" line, read from the cell's
   data-label. This keeps all data on-screen with no horizontal scroll. Cells
   with .stack-hide are dropped on mobile (secondary columns); .stack-full spans
   the whole card (e.g. the action button). Applies to My Positions, picks,
   movers, scanner, pre-open and the trades/scanner pages — every table-terminal. */
@media (max-width: 768px) {
    /* Applied to WIDE tables (.table-stack): My Positions, ranked picks, etc. The
       narrow 3-column tables (gainers/losers/scanner feed) stay as normal compact
       rows — they already fit. 768px (Bootstrap md) so small tablets get cards too
       — otherwise a 640–768px viewport showed the thead running off-screen while
       body-level overflow-x:clip cropped the rest. Neutralise scrollers around them. */
    .table-responsive { overflow-x: visible; }

    .table-stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
    .table-stack tbody tr {
        display: block; padding: 9px 12px;
        border-bottom: 1px solid var(--border);
    }
    .table-stack tbody tr:hover td { background: transparent; }
    .table-stack tbody td {
        display: flex; justify-content: space-between; align-items: baseline;
        gap: 12px; padding: 3px 0; border: 0; text-align: right;
        /* The value side must wrap / break instead of pushing the card wider than
           the screen (which the page-level overflow-x:clip would then crop). */
        min-width: 0; word-break: break-word; overflow-wrap: anywhere;
    }
    /* Left-side label from data-label. */
    .table-stack tbody td::before {
        content: attr(data-label); text-align: left;
        color: var(--text-dim); font-size: 10.5px; letter-spacing: .1em;
        text-transform: uppercase; font-weight: 600; white-space: nowrap;
        flex: 0 0 auto; max-width: 45%;
    }
    /* Card heading = the symbol cell. It's the FIRST cell in My Positions, but in
       the picks table the rank is first (.stack-hide'd) and the symbol carries
       .stack-head — so style both as the heading. Heading is a wrapping flex row
       (symbol + any chips) — NOT a flex that squeezes the symbol to one char wide. */
    .table-stack tbody td:first-child,
    .table-stack tbody td.stack-head {
        display: block; text-align: left;
        font-size: 15px; padding-bottom: 6px; margin-bottom: 2px;
        border-bottom: 1px dashed #1b2433;
        word-break: normal; overflow-wrap: anywhere;
    }
    .table-stack tbody td:first-child::before,
    .table-stack tbody td.stack-head::before { content: none; }
    /* The symbol link itself must never break mid-word (VEDL, LAURUSLABS …). */
    .table-stack tbody td:first-child .sym,
    .table-stack tbody td.stack-head .sym { white-space: nowrap; }
    /* Cells whose content is nowrap on desktop must be allowed to wrap in a card. */
    .table-stack .risk-cell { white-space: normal; text-align: right; }
    .table-stack tbody td.text-nowrap { white-space: normal; }
    .table-stack tbody td.stack-full { justify-content: flex-end; }
    .table-stack tbody td.stack-full::before { content: none; }
    .table-stack tbody td.stack-hide { display: none; }
    .table-stack tbody td:empty { display: none; }
    /* A full-width colspan cell (an inline edit/close form) is NOT a label/value
       line — render it as a plain block so the form lays out normally. */
    .table-stack tbody td.stack-row {
        display: block; text-align: left; padding: 6px 0;
    }
    .table-stack tbody td.stack-row::before { content: none; }
    .table-stack tfoot td { display: flex; justify-content: space-between; text-align: right; }
    .table-stack .pos-read, .table-stack .sym-meta { width: 100%; }
    .table-stack .conf-wrap { min-width: 0; width: 100%; }

    /* Narrow tables: just stop them ever forcing a horizontal scroll. */
    .table-terminal { width: 100%; }

    /* Keep panels within the viewport width (but NOT overflow:hidden — that would
       clip the chip tooltips that pop out of table cells). Wrapping long values
       below is what actually prevents the overflow. */
    .panel, .kpi { max-width: 100%; }
    .panel-head { flex-wrap: wrap; }
}

/* ── Combo: app-styled searchable dropdown (replaces native <select>) ──── */
.combo { position: relative; display: inline-block; vertical-align: middle; min-width: 130px; }
.combo-native { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
.combo-toggle {
    display: block; width: 100%; text-align: left; cursor: pointer;
    background: var(--bg-panel-2); border: 1px solid var(--border); border-radius: 2px;
    color: var(--text); font-size: 13.5px; padding: .375rem 2rem .375rem .75rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.combo-sm .combo-toggle { padding: .25rem 1.8rem .25rem .5rem; font-size: 12.5px; }
.combo-toggle.is-placeholder { color: var(--text-dim); }
.combo-toggle::after {
    content: "▾"; position: absolute; right: 9px; top: 50%; transform: translateY(-50%);
    color: var(--text-dim); font-size: 11px;
}
.combo.open .combo-toggle,
.combo-toggle:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 2px rgba(245,166,35,.15); }
.combo-menu {
    display: none; position: absolute; z-index: 1055; top: calc(100% + 4px); left: 0;
    min-width: 100%; width: max-content; max-width: min(320px, 90vw);
    background: var(--bg-panel); border: 1px solid var(--border); border-radius: 3px;
    box-shadow: 0 10px 28px rgba(0,0,0,.55);
}
.combo.open .combo-menu { display: block; }
.combo-search {
    display: block; width: 100%; border: none; border-bottom: 1px solid var(--border);
    background: var(--bg-panel-2); color: var(--text); outline: none;
    font-family: var(--mono); font-size: 13px; padding: 8px 11px; border-radius: 3px 3px 0 0;
}
.combo-search::placeholder { color: var(--text-dim); }
.combo-list { max-height: 264px; overflow-y: auto; padding: 4px 0; }
.combo-item {
    padding: 6px 12px; font-size: 13px; cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.combo-item:hover, .combo-item.hover { background: #161d2b; }
.combo-item.active { color: var(--accent); }
.combo-item .combo-sym { font-family: var(--mono); font-weight: 600; }
.combo-item .combo-name { color: var(--text-dim); font-size: 12px; margin-left: 6px; }
.combo-empty { padding: 9px 12px; color: var(--text-dim); font-size: 12.5px; }

/* ── Tooltips (CSS-only hover/focus help bubbles) ─────────────────────────────
   Usage (PHP): <?= tip('Label', 'Helpful explanation shown on hover/tap') ?>
   For outsiders/new users: explain KPIs, statuses, columns, jargon. */
.tt-wrap { position: relative; display: inline-flex; align-items: center; gap: 5px; overflow: visible; }
.tt-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 15px; height: 15px; flex: 0 0 15px; border-radius: 50%;
    border: 1px solid var(--border); background: var(--bg-panel-2);
    color: var(--text-dim); font-family: var(--sans); font-size: 10px;
    font-weight: 700; line-height: 1; cursor: help; padding: 0;
    transition: border-color .15s, color .15s;
}
.tt-icon:hover, .tt-icon:focus { outline: none; border-color: var(--accent); color: var(--accent); }
.tt-bubble {
    position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%) translateY(4px);
    z-index: 1080; width: max-content; max-width: 260px;
    background: #0d1219; border: 1px solid var(--border); border-radius: 8px;
    box-shadow: 0 12px 32px rgba(0,0,0,.5); padding: 9px 11px;
    color: var(--text); font-family: var(--sans); font-size: 12px; font-weight: 400;
    line-height: 1.45; text-align: left; white-space: normal;
    opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .14s, transform .14s;
}
.tt-bubble::after {
    content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
    border: 6px solid transparent; border-top-color: var(--border);
}
.tt-wrap:hover .tt-bubble, .tt-wrap:focus-within .tt-bubble, .tt-wrap.open .tt-bubble {
    opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); pointer-events: auto;
}
/* keep edge bubbles on-screen */
.tt-wrap.tt-left .tt-bubble  { left: 0; transform: translateY(4px); }
.tt-wrap.tt-left .tt-bubble::after { left: 10px; }
.tt-wrap.tt-left:hover .tt-bubble, .tt-wrap.tt-left:focus-within .tt-bubble { transform: translateY(0); }

/* open downward — for tooltips near the top of the page (e.g. KPI cards under
   the sticky header) so the bubble never opens up behind the header. */
.tt-wrap.tt-down .tt-bubble {
    bottom: auto; top: calc(100% + 8px);
    transform: translateX(-50%) translateY(-4px);
}
.tt-wrap.tt-down .tt-bubble::after {
    top: auto; bottom: 100%;
    border-top-color: transparent; border-bottom-color: var(--border);
}
.tt-wrap.tt-down:hover .tt-bubble,
.tt-wrap.tt-down:focus-within .tt-bubble,
.tt-wrap.tt-down.open .tt-bubble { transform: translateX(-50%) translateY(0); }
/* combined with left alignment (the dashboard KPIs use both) */
.tt-wrap.tt-down.tt-left .tt-bubble { left: 0; transform: translateY(-4px); }
.tt-wrap.tt-down.tt-left:hover .tt-bubble,
.tt-wrap.tt-down.tt-left:focus-within .tt-bubble { transform: translateY(0); }
.tt-wrap.tt-down.tt-left .tt-bubble::after { left: 10px; }

/* Tooltips inside a table header open DOWNWARD into the table body. Opening
   upward would slide them behind the sticky header and they'd also be clipped
   by the .table-responsive scroll container. This rule makes every thead tip()
   behave like .tt-down without touching each call site. Bubbles also align to
   the cell's left edge so they never overflow the left of the viewport. */
thead .tt-wrap .tt-bubble {
    bottom: auto; top: calc(100% + 8px); left: 0;
    transform: translateY(-4px);
}
thead .tt-wrap .tt-bubble::after {
    top: auto; bottom: 100%; left: 10px;
    border-top-color: transparent; border-bottom-color: var(--border);
}
thead .tt-wrap:hover .tt-bubble,
thead .tt-wrap:focus-within .tt-bubble { transform: translateY(0); }
/* right-aligned numeric columns: anchor the bubble to the right edge instead so
   it doesn't run off the right of the screen. */
thead th.text-end .tt-wrap .tt-bubble { left: auto; right: 0; }
thead th.text-end .tt-wrap .tt-bubble::after { left: auto; right: 10px; }

/* When the JS positioner pins a bubble with position:fixed, the CSS arrow no
   longer lines up with the icon, so hide it. */
.tt-bubble.tt-pinned::after { display: none; }

/* AJAX nav: brief dim while the next page is fetched */
main.app-main.ajax-loading { opacity: .55; transition: opacity .12s; pointer-events: none; }

/* AJAX nav: instant feedback the moment a link is clicked, so a slow remote
   page render doesn't read as a dead/frozen click. Busy cursor + a thin
   indeterminate progress bar pinned to the top of the viewport. */
html.nav-busy, html.nav-busy a { cursor: progress; }
html.nav-busy::before {
    content: "";
    position: fixed;
    top: 0; left: 0;
    height: 2px;
    width: 100%;
    z-index: 2000;
    background: linear-gradient(90deg, transparent 0%, var(--accent, #18c47c) 50%, transparent 100%);
    background-size: 40% 100%;
    background-repeat: no-repeat;
    animation: nav-progress 1.1s ease-in-out infinite;
    pointer-events: none;
}
@keyframes nav-progress {
    0%   { background-position: -40% 0; }
    100% { background-position: 140% 0; }
}

/* ── Place-order modal (dashboard / watchlist / predictions "⚡ Order") ───── */
/* Same overlay treatment as .rsr-overlay below — one visual language for every
   modal in the app. Narrower shell: this is a short form, not a report. */
/* Centred on both axes. align-items:center does the vertical centring, and the
   modal's own max-height keeps a tall form scrollable inside the viewport
   rather than pushing itself off-centre. */
.ais-order-overlay {
    position: fixed; inset: 0; z-index: 1085;
    background: rgba(4, 7, 12, .72); backdrop-filter: blur(2px);
    display: none; align-items: center; justify-content: center;
    padding: 16px;
}
.ais-order-overlay.show { display: flex; }
.ais-order-modal {
    width: 100%; max-width: 460px; max-height: 90vh; overflow-y: auto;
    border-radius: 10px; box-shadow: 0 24px 60px rgba(0,0,0,.55);
}
.ais-order-modal .form-label { font-size: 11px; margin-bottom: 2px; }
/* Rupee risk/reward under the stop-loss and take-profit dropdowns. */
.ais-order-amt { font-size: 11px; margin-top: 3px; font-weight: 600; line-height: 1.2; }

/* Cost summary — also used by the Trades page panel (.ais-order-cost). */
.ais-order-cost {
    font-size: 12px; color: var(--text-dim);
    border-top: 1px solid var(--border); margin-top: 6px; padding-top: 8px;
}
.ais-order-cost > div { margin-bottom: 2px; }
.ais-order-cost-total {
    color: var(--text); font-weight: 600;
    border-top: 1px dashed var(--border); margin-top: 4px; padding-top: 4px;
}
/* Result line + risk-limit confirmation, both shown INSIDE the modal so the
   order stays on screen instead of jumping into a browser alert()/confirm(). */
.ais-order-msg {
    font-size: 12.5px; font-weight: 600; line-height: 1.35;
    border-radius: 8px; padding: 8px 10px; border: 1px solid transparent;
}
.ais-order-msg.is-ok  { color: var(--up);   background: rgba(24, 196, 124, .12); border-color: rgba(24, 196, 124, .35); }
.ais-order-msg.is-err { color: var(--down); background: rgba(246, 70, 93, .12);  border-color: rgba(246, 70, 93, .35); }
.ais-order-risk {
    font-size: 12.5px; border-radius: 8px; padding: 10px;
    color: var(--text); background: rgba(246, 70, 93, .10);
    border: 1px solid rgba(246, 70, 93, .35);
}
.ais-order-risk ul { font-size: 12px; color: var(--text-dim); }

/* The combo menu is absolutely positioned inside .combo; the modal scrolls, so
   let the menu escape the row it sits in rather than clipping at the field. */
.ais-order-modal .combo-menu { z-index: 10; }
.btn-order { font-weight: 600; letter-spacing: .02em; white-space: nowrap; }

/* ── Instant Research (Feature 2) — header button + modal ─────────────────── */
.research-btn { font-weight: 600; letter-spacing: .02em; }
.research-btn .research-ico { font-size: 14px; line-height: 1; }

.rsr-overlay {
    position: fixed; inset: 0; z-index: 1080;
    background: rgba(4, 7, 12, .72); backdrop-filter: blur(2px);
    display: none; align-items: flex-start; justify-content: center;
    padding: 6vh 16px 16px;
}
.rsr-overlay.show { display: flex; }
.rsr-modal {
    width: 100%; max-width: 620px; max-height: 86vh; overflow-y: auto;
    background: var(--bg-panel); border: 1px solid var(--border);
    border-radius: 10px; box-shadow: 0 24px 60px rgba(0,0,0,.55);
}
.rsr-head { display: flex; align-items: center; justify-content: space-between;
    padding: 14px 16px; border-bottom: 1px solid var(--border); }
.rsr-kicker { font-family: var(--mono, monospace); font-size: 11px; letter-spacing: .14em;
    text-transform: uppercase; color: var(--accent); }
.rsr-quota { display: block; font-size: 11px; color: var(--text-dim); margin-top: 2px; }
.rsr-close { background: none; border: 0; color: var(--text-dim); font-size: 26px;
    line-height: 1; cursor: pointer; padding: 0 4px; }
.rsr-close:hover { color: var(--text); }

.rsr-search { display: flex; gap: 8px; padding: 14px 16px; border-bottom: 1px solid var(--border); }
.rsr-input { flex: 1; background: var(--bg); border: 1px solid var(--border);
    border-radius: 6px; color: var(--text); padding: 9px 12px; font-size: 14px;
    text-transform: uppercase; letter-spacing: .04em; }
.rsr-input:focus { outline: none; border-color: var(--accent); }

/* ── Autocomplete (symbol/name hinter) ─────────────────────────────────── */
.rsr-ac { position: relative; flex: 1; }
.rsr-ac .rsr-input { width: 100%; }
.rsr-auto {
    list-style: none; margin: 6px 0 0; padding: 4px;
    position: absolute; top: 100%; left: 0; right: 0; z-index: 20;
    background: var(--bg-panel-2); border: 1px solid var(--border);
    border-radius: 8px; box-shadow: 0 16px 38px rgba(0,0,0,.55);
    max-height: 268px; overflow-y: auto; display: none;
    -webkit-overflow-scrolling: touch;
}
.rsr-auto.show { display: block; }
.rsr-ac-item {
    display: flex; align-items: baseline; gap: 10px;
    padding: 8px 10px; border-radius: 6px; cursor: pointer;
    border: 1px solid transparent;
}
.rsr-ac-item:hover,
.rsr-ac-item.active {
    background: rgba(245, 166, 35, .10);
    border-color: rgba(245, 166, 35, .35);
}
.rsr-ac-sym {
    font-family: var(--mono, monospace); font-weight: 600; font-size: 13px;
    color: var(--text); letter-spacing: .03em; flex: 0 0 auto;
}
.rsr-ac-sym mark,
.rsr-ac-name mark { background: none; color: var(--accent); padding: 0; }
.rsr-ac-name {
    font-size: 12px; color: var(--text-dim); flex: 1 1 auto;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    text-align: right;
}
.rsr-ac-empty { padding: 10px; font-size: 12px; color: var(--text-dim); text-align: center; }

@media (max-width: 560px) {
    .rsr-auto { max-height: 240px; }
    .rsr-ac-item { padding: 10px; }
    .rsr-ac-name { font-size: 11px; }
}

.rsr-body { padding: 16px; min-height: 120px; }
.rsr-hint { color: var(--text-dim); font-size: 13px; text-align: center; padding: 24px 8px; }

.rsr-loading { text-align: center; padding: 28px 8px; color: var(--text-dim); }
.rsr-loading p { margin: 6px 0 0; font-size: 13px; }
.rsr-loading .rsr-sub { font-size: 11px; opacity: .7; }
.rsr-spin { width: 30px; height: 30px; margin: 0 auto 12px; border-radius: 50%;
    border: 3px solid var(--border); border-top-color: var(--accent);
    animation: rsr-spin .8s linear infinite; }
@keyframes rsr-spin { to { transform: rotate(360deg); } }
.rsr-fail { text-align: center; padding: 24px 8px; color: var(--text-dim); font-size: 13px; }
.rsr-fail .btn { margin-top: 12px; }

.rsr-quote { margin-bottom: 12px; }
.rsr-sym { font-size: 18px; font-weight: 700; letter-spacing: .02em; }
.rsr-co { font-size: 11px; font-weight: 400; color: var(--text-dim); text-transform: none; letter-spacing: 0; }
.rsr-price { margin-top: 2px; font-size: 14px; }
.rsr-ltp { font-size: 22px; font-weight: 700; }
.rsr-lohc { font-size: 11.5px; color: var(--text-dim); margin-top: 3px; }

/* chart-first: a tall chart right under the price */
.rsr-chart-box { height: 220px; margin: 4px 0 14px; }

.rsr-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 560px) {
    .rsr-grid { grid-template-columns: 1fr; }
    /* 3-col indicator grid is too tight on phones → 2 cols, and let values wrap. */
    .rsr-inds { grid-template-columns: 1fr 1fr; }
    .rsr-ind-v { overflow-wrap: anywhere; }
    /* Keep all research content inside the modal (no sideways crop). */
    .rsr-body { padding: 12px; }
    .rsr-body * { max-width: 100%; }
    .rsr-plan-row { flex-wrap: wrap; gap: 2px 10px; }

    /* Tighter marquee on phones — smaller type, less padding. Keep the dot's
       margin equal to the track gap so the "·" stays centred between indices. */
    .ticker-strip { padding: 5px 10px; gap: 8px; font-size: 11px; }
    .ticker-track { gap: 11px; }
    .ticker-item:not(:first-child)::before { margin-right: 11px; }
    .ticker-status { padding-left: 8px; }
}
.rsr-sec { background: var(--bg-panel-2); border: 1px solid var(--border);
    border-radius: 7px; padding: 10px 12px; margin-bottom: 10px; }
.rsr-sec-h { font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
    color: var(--text-dim); margin-bottom: 6px; }
.rsr-conf { font-family: var(--mono, monospace); font-size: 13px; }
.rsr-plan { margin-top: 8px; border-top: 1px solid var(--border); padding-top: 8px; }
.rsr-plan-row { display: flex; justify-content: space-between; font-size: 12.5px; padding: 2px 0; }
.rsr-plan-row span { color: var(--text-dim); }
.rsr-plan-row b { font-family: var(--mono, monospace); }
.rsr-reason { font-size: 12px; color: var(--text-dim); margin-top: 6px; }
.rsr-inds { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px 10px; }
.rsr-ind { display: flex; flex-direction: column; }
.rsr-ind-k { font-size: 9.5px; letter-spacing: .08em; color: var(--text-dim); }
.rsr-ind-v { font-family: var(--mono, monospace); font-size: 12.5px; }
.rsr-ai-note { font-size: 12.5px; }
.rsr-disc { font-size: 10.5px; color: var(--text-dim); font-style: italic; margin: 10px 0 0; }
.rsr-asof { font-size: 10px; color: var(--text-dim); margin: 4px 0 0; text-align: right; }

/* ── /indicator — AI Buy/Sell Indicator page ─────────────────────────── */
.ind-up { color: var(--up); }
.ind-down { color: var(--down); }
.ind-panel { border: 1px solid var(--border); border-radius: 12px;
             background: var(--bg-panel); padding: 2rem 1.25rem; text-align: center; }
.ind-countdown-label { color: var(--text-dim); font-size: 12px;
                       letter-spacing: .08em; text-transform: uppercase; }
.ind-countdown { font-family: var(--mono, monospace); font-size: 2.25rem;
                 font-weight: 700; letter-spacing: .05em; }
.ind-status { font-size: 11px; letter-spacing: .06em; }
.ind-status.ind-live { background: var(--up); color: #06110c; }
.ind-status.ind-closed { background: var(--flat); color: #10151f; }
.ind-card { border: 1px solid var(--border); border-radius: 12px;
            background: var(--bg-panel); margin-bottom: .75rem; overflow: hidden; }
.ind-card-head { display: flex; align-items: center; gap: .6rem; width: 100%;
                 padding: .8rem 1rem; background: none; border: 0;
                 color: var(--text); text-align: left; cursor: pointer; flex-wrap: wrap; }
.ind-card-head:hover { background: var(--bg-panel-2); }
/* AI holds a live open position on this stock right now — visible at a
   glance without opening the (collapsed) card. */
.ind-card-live .ind-card-head { background: rgba(74,158,255,.14);
                                 box-shadow: inset 3px 0 0 #4a9eff; }
.ind-card-live .ind-card-head:hover { background: rgba(74,158,255,.22); }
.ind-rank { font-weight: 700; color: var(--text-dim); }
.ind-symbol { font-weight: 700; font-size: 1.05rem; }
.ind-conf { font-family: var(--mono, monospace); font-weight: 700;
            padding: .1rem .5rem; border-radius: 999px;
            background: rgba(245,166,35,.14); color: var(--accent); }
.ind-ltp { margin-left: auto; font-family: var(--mono, monospace);
           font-variant-numeric: tabular-nums; }
.ind-chip { font-size: .72rem; padding: .15rem .5rem; border-radius: 999px; }
.ind-chip-clear { background: rgba(24,196,124,.14); color: var(--up); }
.ind-chip-caution { background: rgba(245,166,35,.14); color: var(--accent); }
.ind-chip-avoid { background: rgba(246,70,93,.14); color: var(--down); }
.ind-chip-vol { background: rgba(123,133,150,.15); color: var(--text-dim); }
.ind-chip-pos { background: rgba(24,196,124,.2); color: var(--up); font-weight: 600; }
.ind-card-body { padding: .75rem 1rem 1rem; border-top: 1px solid var(--border); }
/* Definite box, not just a min-height: the chart runs with autoSize and sizes
   itself FROM this container, so the container's own height must not depend on
   the chart's content. */
.ind-chart { width: 100%; height: 320px; min-height: 320px; margin: .6rem 0; }
.ind-trade-row { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.ind-qty { max-width: 90px; }
.ind-btn-buy { background: var(--up); border: 0; color: #06110c; font-weight: 700; }
.ind-btn-sell { background: var(--down); border: 0; color: #fff; font-weight: 700; }
.ind-btn-buy:disabled, .ind-btn-sell:disabled { opacity: .4; }
.ind-pnl { font-family: var(--mono, monospace); font-variant-numeric: tabular-nums; }
.ind-act-form summary { cursor: pointer; margin-top: .6rem; font-weight: 600;
                        color: var(--accent); }
.ind-act-fields { display: flex; flex-direction: column; gap: .5rem;
                  max-width: 420px; margin-top: .5rem; }
.ind-accept { display: flex; gap: .4rem; align-items: flex-start;
              color: var(--text-dim); }
.ind-btn-activate { background: var(--accent); border: 0; color: #10151f;
                    font-weight: 700; align-self: flex-start; }
.ind-act-state { margin-top: .6rem; font-size: .85rem; }
.ind-msg { min-height: 1.2em; margin-top: .4rem; }
@media (max-width: 576px) {
    .ind-ltp { width: 100%; margin-left: 0; }
    .ind-trade-row .ind-qty { max-width: 70px; }
}
.ind-btn-stop { background: var(--down); border: 0; color: #fff; font-weight: 700;
                padding: .1rem .6rem; margin-left: .4rem; }
.ind-btn-restart { background: var(--up); border: 0; color: #06110c; font-weight: 700;
                    padding: .1rem .6rem; margin-left: .4rem; }
.ind-act-state { margin-top: .6rem; font-size: .85rem; display: flex;
                 flex-wrap: wrap; gap: .4rem; align-items: center; }
.ind-act-state > div { flex-basis: 100%; }
.ind-row-label { font-size: 11px; color: var(--text-dim); letter-spacing: .04em;
                 margin: .7rem 0 .25rem; text-transform: uppercase; }
/* "the AI will not open here" — replaces an Activate button that could only
   ever be a no-op. Amber, not red: nothing is broken, it's a deliberate gate. */
.ind-gated { color: var(--accent); text-transform: none; letter-spacing: .01em;
             font-size: 12px; font-weight: 600; }
.ind-runs { overflow-x: auto; }
.ind-runs-table { width: 100%; border-collapse: collapse; font-size: .78rem;
                   font-family: var(--mono, monospace); font-variant-numeric: tabular-nums; }
.ind-runs-table th { text-align: left; color: var(--text-dim); font-weight: 600;
                      font-size: .7rem; text-transform: uppercase; letter-spacing: .04em;
                      padding: .2rem .4rem; border-bottom: 1px solid var(--border); }
.ind-runs-table td { padding: .2rem .4rem; border-bottom: 1px solid var(--border); }
.ind-runs-table tfoot td { border-bottom: 0; border-top: 1px solid var(--border);
                            font-weight: 700; padding-top: .3rem; }

/* ── Device notifications panel (Alerts page, rendered by push.js) ────── */
.push-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .25rem; }
.btn-outline-accent {
    background: none; border: 1px solid var(--border); color: var(--text-dim);
    font-weight: 500;
}
.btn-outline-accent:hover { border-color: var(--accent); color: var(--accent); }
.push-steps { color: var(--text-dim); font-size: 12.5px; padding-left: 1.1rem; margin-bottom: .6rem; }
.push-steps li { margin-bottom: .3rem; }
.push-steps strong { color: var(--text); }
.push-msg:empty { display: none; }
.push-msg {
    margin-top: .7rem; font-size: 12px; line-height: 1.45; border-radius: 2px;
    padding: 7px 9px; border: 1px solid var(--border); color: var(--text-dim);
}
.push-msg-ok    { color: var(--up);     border-color: rgba(24,196,124,.35);  background: rgba(24,196,124,.07); }
.push-msg-warn  { color: var(--accent); border-color: rgba(245,166,35,.35);  background: rgba(245,166,35,.07); }
.push-msg-error { color: var(--down);   border-color: rgba(246,70,93,.35);   background: rgba(246,70,93,.07); }
.push-devices { margin-top: 1rem; border-top: 1px solid var(--border); padding-top: .7rem; }
.push-devices-head {
    font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
    color: var(--text-dim); margin-bottom: .45rem;
}
.push-device {
    display: flex; align-items: center; gap: .5rem;
    padding: .4rem 0; border-bottom: 1px solid var(--border);
}
.push-device:last-child { border-bottom: 0; }
.push-device.is-off .push-device-name { color: var(--text-dim); text-decoration: line-through; }
.push-device-main { min-width: 0; flex: 1; }
.push-device-name { display: block; font-size: 12.5px; color: var(--text); }
.push-device-meta { display: block; font-size: 11px; color: var(--text-dim); }
.push-device-x {
    background: none; border: 0; color: var(--text-dim); font-size: 20px;
    line-height: 1; padding: 0 4px; cursor: pointer; flex: 0 0 auto;
}
.push-device-x:hover { color: var(--down); }
.push-device-x:disabled { opacity: .4; cursor: default; }
