@import url('mia.css');
@import url('extras.css');
@import url('cinematic.css');
@import url('debug-panel.css');
@import url('about.css');
@import url('currency.css');
@import url('markets.css');
@import url('pl-toggle.css');
@import url('spikers.css');
@import url('penny-mia-phase8.css');
@import url('portfolio.css');
@import url('notify.css');
@import url('agentic-stage.css');
@import url('signal-extras.css');
@import url('surfaces.css');

:root {
    /* Dark mode: page stays true black, but cards/secondary surfaces
       lift a few notches so they're visibly raised slabs against the
       black backdrop. Pure-black-on-black shadows were invisible —
       we now use white-tinted outer shadows (low alpha) PLUS a
       brighter inset top hairline so each card looks like a piece of
       dark glass with light catching the upper edge. */
    --bg-primary: #000000;
    --bg-secondary: #161616;
    --bg-card: #121212;
    --bg-hover: #1e1e1e;
    --border: #262626;
    --border-strong: #383838;
    --text-primary: #e8eef5;
    --text-secondary: #9fb0c4;
    --text-muted: #6c7a8c;
    --accent: #4a9eff;
    --accent-rgb: 74, 158, 255;
    --green: #2dd28b;
    --green-bg: rgba(45, 210, 139, 0.1);
    --red: #ef4444;
    --red-bg: rgba(239, 68, 68, 0.1);
    --yellow: #fbbf24;
    --yellow-bg: rgba(251, 191, 36, 0.1);
    --num-font: 'JetBrains Mono', 'Fira Code', ui-monospace, SFMono-Regular, Menlo, monospace;
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 16px;
    --brand-grad: linear-gradient(135deg, #4a9eff 0%, #2dd28b 100%);
    --brand-grad-2: linear-gradient(135deg, #4a9eff, #a371f7);
    --brand-grad-shadow: rgba(74, 158, 255, 0.32);
    --scroll-track: #000000;
    --scroll-thumb: #383838;
    --scroll-thumb-hover: #4a9eff;
    /* Depth tokens — white-tinted outer shadows so the lifted edge of
       each card glows softly off the pure-black backdrop instead of
       disappearing. Inset top hairline (4-5% white) catches the
       light source. The pairing — lighter card surface + white
       outer halo + white inset top + thin black inset bottom — is
       what reads as "raised dark glass" instead of flat slab.
       Combined cards: outer halo + inset top + inset bottom in one
       declaration so callers don't have to stack multiple shadow
       tokens on each surface. */
    --shadow-card:
        inset 0 1px 0 rgba(255, 255, 255, 0.08),
        inset 0 -1px 0 rgba(0, 0, 0, 0.5),
        0 1px 0 rgba(255, 255, 255, 0.04),
        0 6px 16px rgba(255, 255, 255, 0.04),
        0 14px 32px rgba(255, 255, 255, 0.05);
    --shadow-card-hover:
        inset 0 1px 0 rgba(255, 255, 255, 0.10),
        inset 0 -1px 0 rgba(0, 0, 0, 0.5),
        0 1px 0 rgba(255, 255, 255, 0.05),
        0 8px 22px rgba(255, 255, 255, 0.06),
        0 20px 44px rgba(var(--accent-rgb), 0.18);
    --shadow-control:
        inset 0 1px 0 rgba(255, 255, 255, 0.07),
        0 1px 0 rgba(255, 255, 255, 0.03),
        0 2px 8px rgba(255, 255, 255, 0.04);
    --shadow-control-hover:
        inset 0 1px 0 rgba(255, 255, 255, 0.12),
        0 1px 0 rgba(255, 255, 255, 0.05),
        0 4px 14px rgba(var(--accent-rgb), 0.22);
    --shadow-inset-top: inset 0 1px 0 rgba(255, 255, 255, 0.08);
    --shadow-inset-bottom: inset 0 -1px 0 rgba(0, 0, 0, 0.5);
}

[data-theme="light"] {
    /* CRED-inspired: pale cool-grey page that's clearly NOT pure white,
       elevated white cards lifting off it via layered shadows, deeper
       border-strong for inset hairlines. The page background sits a
       step darker than cards so the cards read as raised surfaces. */
    --bg-primary: #ecf0f6;
    --bg-secondary: #f4f7fb;
    --bg-card: #ffffff;
    --bg-hover: #e6ecf3;
    --border: #dde4ee;
    --border-strong: #c5d0de;
    --text-primary: #0f172a;
    --text-secondary: #475569;
    --text-muted: #8492a6;
    --accent: #2563eb;
    --accent-rgb: 37, 99, 235;
    --green: #059669;
    --green-bg: rgba(5, 150, 105, 0.08);
    --red: #dc2626;
    --red-bg: rgba(220, 38, 38, 0.08);
    --yellow: #d97706;
    --yellow-bg: rgba(217, 119, 6, 0.08);
    --brand-grad: linear-gradient(135deg, #2563eb 0%, #059669 100%);
    --brand-grad-2: linear-gradient(135deg, #2563eb, #7c3aed);
    --brand-grad-shadow: rgba(37, 99, 235, 0.3);
    --scroll-track: #e6ecf3;
    --scroll-thumb: #c5d0de;
    --scroll-thumb-hover: #2563eb;
    /* Light-theme-only depth tokens. Cards/buttons read these to
       layer shadows; dark+aurora override them to no-op so the same
       selectors don't paint shadows on dark backgrounds where they'd
       just look muddy. */
    --shadow-card: 0 1px 2px rgba(15, 23, 42, 0.04), 0 4px 12px rgba(15, 23, 42, 0.06), 0 12px 28px rgba(15, 23, 42, 0.05);
    --shadow-card-hover: 0 2px 4px rgba(15, 23, 42, 0.06), 0 8px 18px rgba(15, 23, 42, 0.08), 0 18px 36px rgba(15, 23, 42, 0.07);
    --shadow-control: 0 1px 2px rgba(15, 23, 42, 0.05), 0 2px 6px rgba(15, 23, 42, 0.06);
    --shadow-control-hover: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.10);
    --shadow-inset-top: inset 0 1px 0 rgba(255, 255, 255, 0.9);
    --shadow-inset-bottom: inset 0 -1px 0 rgba(15, 23, 42, 0.04);
    /* Light-theme frosted glass: a translucent near-white plate. */
    --bg-glass: rgba(255, 255, 255, 0.78);
}

[data-theme="aurora"] {
    --bg-primary: #0a0420;
    --bg-secondary: #14082b;
    --bg-card: #100628;
    --bg-hover: #1d0e3d;
    --border: #2a1652;
    --border-strong: #3d2270;
    --text-primary: #f0e6ff;
    --text-secondary: #c2a8e6;
    --text-muted: #8c75b8;
    --accent: #c084fc;
    --accent-rgb: 192, 132, 252;
    --green: #14e8a8;
    --green-bg: rgba(20, 232, 168, 0.12);
    --red: #ff5c8a;
    --red-bg: rgba(255, 92, 138, 0.12);
    --yellow: #ffc857;
    --yellow-bg: rgba(255, 200, 87, 0.12);
    --brand-grad: linear-gradient(135deg, #c084fc 0%, #14e8a8 50%, #38bdf8 100%);
    --brand-grad-2: linear-gradient(135deg, #c084fc, #ec4899);
    --brand-grad-shadow: rgba(192, 132, 252, 0.4);
    --scroll-track: #100628;
    --scroll-thumb: #3d2270;
    --scroll-thumb-hover: #c084fc;
    /* Aurora depth tokens — same approach as dark, but the accent
       glow on hover uses the violet accent so cards lift with a
       subtle purple wash, matching the rest of the theme. */
    --shadow-card: 0 1px 0 rgba(0, 0, 0, 0.55), 0 6px 16px rgba(0, 0, 0, 0.50), 0 20px 44px rgba(58, 18, 110, 0.55);
    --shadow-card-hover: 0 1px 0 rgba(0, 0, 0, 0.55), 0 8px 22px rgba(0, 0, 0, 0.60), 0 26px 56px rgba(192, 132, 252, 0.18);
    --shadow-control: 0 1px 0 rgba(0, 0, 0, 0.45), 0 2px 8px rgba(58, 18, 110, 0.45);
    --shadow-control-hover: 0 1px 0 rgba(0, 0, 0, 0.45), 0 4px 16px rgba(192, 132, 252, 0.25);
    --shadow-inset-top: inset 0 1px 0 rgba(255, 255, 255, 0.06);
    --shadow-inset-bottom: inset 0 -1px 0 rgba(0, 0, 0, 0.40);
    /* Aurora frosted glass: translucent deep-violet plate. */
    --bg-glass: rgba(22, 10, 45, 0.72);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
    height: 100%;
    /* Lock horizontal overflow at the document root. The TradingView
       embed iframe self-sizes to a desktop width on phones, which used
       to force the body wider than the viewport. That made the
       browser silently disable the mobile media queries (since body
       was now > 540px) and rendered the desktop layout while the user
       could only see the leftmost 402px — looking like "the screen
       split, with the right half empty waiting for Mia." Clamping
       overflow-x to hidden at html+body level means no child can
       expand the document, and our @media rules fire reliably. */
    overflow-x: hidden;
    max-width: 100vw;
}
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: var(--bg-primary);
    color: var(--text-primary);
    line-height: 1.5;
    transition: background 0.3s, color 0.3s;
}

/* ────────────────────────────────────────────────────────────────────
   Depth pass — applied across all themes.

   Roshan's brief: cards / buttons / pills should have soft elevation
   so the page doesn't look flat. Each theme defines its own
   --shadow-card / --shadow-control tokens up top:
     dark   = deep-black outer + faint white inset top hairline
     aurora = deep-black outer + violet hover glow
     light  = layered slate shadows + bright white inset hairline
   The painting selectors below are theme-agnostic; the visual changes
   per theme via the tokens.

   Light-theme-only embellishments (top hairline ::before, white→pale
   gradient on cards) live in a separate block lower down.
   ──────────────────────────────────────────────────────────────────── */

.signal-box,
.chart-container,
.hot-pick-card,
.scanner-details,
.price-target-card,
.pp-calc,
.portfolio-stat,
.accordion-item,
.empty-state,
.acc-cell,
.resources-body {
    box-shadow: var(--shadow-card);
}
.hot-pick-card:hover,
.accordion-item:hover {
    box-shadow: var(--shadow-card-hover);
    transform: translateY(-2px);
}

/* Buttons + tab pills + filters lift slightly off the page so they
   don't sit flat against the surface they're on. Active/hover get a
   stronger elevation. .portfolio-launcher sits in this group so it
   matches the .tab-group pills it lives next to (Stock Analysis /
   Crypto Analysis / Today / Tomorrow / Portfolio all read as the
   same elevated control row). */
.tab-group,
.resources-toggle,
.header-btn,
.scanner-filter,
.scanner-select,
.search-input,
.portfolio-action-btn,
.pp-calc input[type="number"],
.portfolio-cta,
.portfolio-launcher,
.refresh-btn,
#spikers-btn {
    box-shadow: var(--shadow-control);
}
.header-btn:hover,
.resources-toggle:hover,
.tab-group:hover,
.portfolio-launcher:hover,
.portfolio-action-btn:hover,
.portfolio-cta:hover,
.refresh-btn:hover,
#spikers-btn:hover {
    box-shadow: var(--shadow-control-hover);
}
/* The active tab inside .tab-group (e.g. "Stock Analysis", "Today")
   used to be flush against the group's surface. Lift it with a small
   own-shadow so the on-state reads as a pressed pill that's now
   raised above the off pills next to it. Each theme tints the glow
   with its own --accent-rgb. */
.tab-btn.active {
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.4), 0 4px 12px rgba(var(--accent-rgb), 0.30);
}
[data-theme="light"] .tab-btn.active {
    box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06), 0 4px 10px rgba(var(--accent-rgb), 0.18);
}
/* Portfolio launcher when its panel is open — accent glow so it
   reads as the active control like .tab-btn.active. */
body.side-panel-portfolio-open .portfolio-launcher {
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.4), 0 4px 14px rgba(var(--accent-rgb), 0.32);
}
[data-theme="light"] body.side-panel-portfolio-open .portfolio-launcher {
    box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06), 0 4px 12px rgba(var(--accent-rgb), 0.20);
}

/* Inset highlight on top + soft inset bottom shadow on cards gives
   the polished CRED card edge — a thin white line on top and a thin
   shadow on bottom, like light catching a raised surface. */
[data-theme="light"] .signal-box,
[data-theme="light"] .hot-pick-card,
[data-theme="light"] .chart-container,
[data-theme="light"] .price-target-card,
[data-theme="light"] .portfolio-stat,
[data-theme="light"] .accordion-item {
    border-color: var(--border);
}
[data-theme="light"] .signal-box::before,
[data-theme="light"] .hot-pick-card::before {
    /* Top hairline highlight — purely decorative, sits inside the
       border so the corners stay clean. */
    content: '';
    position: absolute;
    top: 0; left: 1px; right: 1px;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 1), transparent);
    border-radius: inherit;
    pointer-events: none;
}
[data-theme="light"] .signal-box,
[data-theme="light"] .hot-pick-card { position: relative; }

/* Subtle gradient on cards so they're not a flat slab of white.
   Top a touch warmer than the bottom — light source from above. */
[data-theme="light"] .hot-pick-card,
[data-theme="light"] .signal-box,
[data-theme="light"] .price-target-card,
[data-theme="light"] .portfolio-stat {
    background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%);
}

/* Page-level surfaces step down from cards: secondary panels sit
   slightly grey so cards on top read as raised. */
[data-theme="light"] .signal-section,
[data-theme="light"] .chart-section,
[data-theme="light"] .hot-picks-section,
[data-theme="light"] .scanner-section {
    /* No background here; the parent --bg-primary is already the
       cool-grey. Cards above will carry the depth visually. */
}

.app-header {
    /* sticky already counts as a positioned value, so the absolute
       .header-actions inside it anchors here (not to <body>). The
       gear cluster sits centred against the header height via
       top: 50% / translateY(-50%) — see .header-actions below.

       safe-area-inset-top covers the iPhone notch when the page runs
       as a PWA from the home screen. apple-mobile-web-app-status-bar-
       style: black-translucent makes iOS overlay the status bar on
       top of the page, so without this padding the title + gear sit
       UNDER the notch / status bar. The max() guards desktop where
       safe-area-inset-top is 0. */
    position: sticky; top: 0; z-index: 100;
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border);
    padding: max(14px, env(safe-area-inset-top, 14px)) max(24px, env(safe-area-inset-right, 24px)) 14px max(24px, env(safe-area-inset-left, 24px));
}
[data-theme="light"] .app-header {
    /* Match the new pale cool-grey page bg + a subtle bottom shadow
       so the header reads as raised on top of the content below. */
    background: rgba(236, 240, 246, 0.86);
    box-shadow: 0 1px 0 rgba(15, 23, 42, 0.04), 0 4px 14px rgba(15, 23, 42, 0.04);
}
[data-theme="aurora"] .app-header { background: rgba(10, 4, 32, 0.85); }
.header-content {
    max-width: 1400px; margin: 0 auto;
    display: flex; align-items: center; justify-content: center;
    position: relative;
}
.app-title-wrap { display: flex; align-items: center; gap: 18px; }
.app-title {
    font-size: 1.4rem; font-weight: 900;
    background: var(--brand-grad);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent;
    letter-spacing: 0.5px;
}
.header-ecg { width: 80px; height: 24px; }
.header-ecg-trace { stroke: var(--text-muted); opacity: 0.35; }
.header-ecg-blip {
    stroke: var(--accent);
    stroke-dasharray: 200;
    stroke-dashoffset: 200;
    filter: drop-shadow(0 0 4px rgba(var(--accent-rgb), 0.7));
    animation: header-ecg-sweep 2.4s ease-in-out infinite;
}
@keyframes header-ecg-sweep {
    0%   { stroke-dashoffset: 200; }
    50%  { stroke-dashoffset: 0; }
    100% { stroke-dashoffset: -200; }
}

.header-actions {
    /* Anchor BELOW the safe-area inset so the gear clears the iPhone
       notch / dynamic island. Earlier `top: 50%` centered the gear
       against the header's full height — but with safe-area-inset-top
       padding added, half of that height is consumed by the notch,
       so 50% landed the gear partially behind the dynamic island.
       Using calc(safe-area-inset-top + 14px) puts the gear directly
       below the notch on iPhone and at top: 14px on desktop (env
       resolves to 0). transform: none so we anchor by the gear's
       OWN top edge, not its center. */
    position: absolute;
    /* Vertically center the gear on the TITLE's baseline rather than top-
       anchoring it (which left it sitting above the title's center). The
       header's safe-area padding-top is already on .app-header, so within
       .header-content the title is vertically centered; matching that with
       top:50% + translateY(-50%) aligns the gear to the title. On iPhone the
       safe-area padding lives on the header, so the content (and thus this
       50%) is already below the notch — no dynamic-island overlap. */
    top: 50%;
    right: max(24px, env(safe-area-inset-right, 24px));
    transform: translateY(-50%);
    display: flex; gap: 8px; align-items: center;
    z-index: 200;
}
.header-btn {
    width: 36px; height: 36px;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-primary);
    border-radius: 50%;
    cursor: pointer;
    font-weight: 800;
    transition: all 0.15s;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 0.92rem;
}
.header-btn:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-1px); }
.header-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }

/* Settings gear — exactly ONE forward rotation on open, ONE backward
   on close. No hover rotation, no continuous spin. Earlier the hover
   rule rotated to 60deg, which made the open animation jump 60→360
   (looked like a fast forward+back wobble). Now the gear holds at 0
   when closed, transitions cleanly to 360 on open, and back to 0 on
   close. The 0.6s transition is the spin duration. */
.settings-gear {
    transform: rotate(0deg);
    transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}
.header-btn[aria-expanded="true"] .settings-gear {
    transform: rotate(180deg);
}

/* Dropdown menu that slides down from under the gear button. */
.header-settings-menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 200px;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: 12px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45);
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    opacity: 0;
    transform: translateY(-6px) scale(0.96);
    transform-origin: top right;
    pointer-events: none;
    transition: opacity 0.18s ease, transform 0.18s ease;
    z-index: 210;
}
.header-settings-menu.open {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
.header-menu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    /* Bumped vertical padding from 6px → 10px so each menu row hits
       ~44pt — Apple HIG floor for touch targets. The gear menu was
       hard to tap accurately on iPhone before. Desktop is unaffected
       (still feels compact). */
    padding: 10px 12px;
    min-height: 40px;
    background: transparent;
    border: none;
    border-radius: 6px;
    color: var(--text-primary);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    text-align: left;
    transition: background 0.15s ease, color 0.15s ease, transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1);
    transform-origin: left center;
    width: 100%;
}
.header-menu-item:hover {
    background: var(--bg-hover);
    transform: scale(1.04);   /* gentle zoom-in on hover */
}
.header-menu-item:hover .header-menu-icon {
    color: var(--accent);
    transform: scale(1.12);
}
.header-menu-icon { transition: color 0.15s ease, transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1); }
.header-menu-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    transition: color 0.15s ease;
}
.header-menu-icon svg { width: 14px; height: 14px; }
.header-menu-label {
    flex: 1;
    font-weight: 600;
    color: var(--text-primary);
}
.header-menu-meta {
    font-size: 0.68rem;
    font-weight: 500;
    color: var(--text-muted);
    letter-spacing: 0.2px;
    margin-left: 6px;
}

/* Currency picker popover — opens to the LEFT of the settings menu
   when the Currency Converter item is clicked. Lists every supported
   currency with symbol, code, and friendly name. */
.currency-picker {
    position: fixed;
    z-index: 220;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: 12px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
    padding: 6px;
    min-width: 240px;
    max-height: 70vh;
    overflow-y: auto;
}
.currency-picker-item {
    display: grid;
    grid-template-columns: 28px 50px 1fr;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: none;
    background: transparent;
    color: var(--text-primary);
    cursor: pointer;
    border-radius: 6px;
    text-align: left;
    transition: background 0.12s;
}
.currency-picker-item:hover {
    background: var(--bg-hover);
}
.currency-picker-item.active {
    background: rgba(var(--accent-rgb), 0.12);
    color: var(--accent);
}
.currency-picker-symbol {
    font-family: var(--num-font);
    font-weight: 800;
    font-size: 0.95rem;
    text-align: center;
}
.currency-picker-code {
    font-family: var(--num-font);
    font-size: 0.78rem;
    color: var(--text-secondary);
    font-weight: 700;
}
.currency-picker-item.active .currency-picker-code { color: var(--accent); }
.currency-picker-name {
    font-size: 0.78rem;
    color: var(--text-secondary);
}
.currency-picker-item.active .currency-picker-name { color: var(--accent); }
/* Brief feedback pulse when a menu item is activated. The user clicks
   → row pulses with the accent → menu closes. Tells the user "yes,
   the click landed" before the menu animates away. */
.header-menu-item.header-menu-fired {
    animation: header-menu-fired 0.45s cubic-bezier(0.45, 0, 0.55, 1);
}
.header-menu-item.header-menu-fired .header-menu-icon {
    color: var(--accent);
}
@keyframes header-menu-fired {
    0%   { background: transparent; transform: scale(1); }
    35%  { background: rgba(var(--accent-rgb), 0.22); transform: scale(1.02); }
    100% { background: transparent; transform: scale(1); }
}
.theme-toggle {
    width: 36px; height: 36px;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-primary);
    border-radius: 50%;
    cursor: pointer; transition: all 0.15s;
    display: inline-flex; align-items: center; justify-content: center;
}
.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }

.app-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    /* Tighter centered column so the chart, search, and tabs read as
       a clean centered block on wide displays instead of stretching
       edge-to-edge. Resources / P&L slide in as overlays without
       resizing this column (see css/pl-toggle.css). */
    max-width: 960px;
    margin: 0 auto;
    padding: 24px;
    gap: 24px;
}
/* Resources panel — slides in from the left as a fixed full-height
   overlay (covers the sticky header too) so opening / closing it
   never reflows the main content and the panel reads as a complete
   side-sheet, not a clipped strip. Z-index sits above .app-header
   (100) and the toggle pill so the pill is hidden while the panel
   is open. */
.glossary-rail {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(300px, 92vw);
    /* 100dvh (dynamic viewport height) instead of 100vh — on iOS
       Safari the URL bar collapses on scroll, and 100vh is sticky
       to the LARGER viewport state, which means content overflows
       the visible area when the bar is open. dvh tracks the actual
       visible height. inner padding clamps to safe-area-inset-top
       so the headline isn't trapped under the Dynamic Island, and
       inset-bottom so the home indicator doesn't sit on the last
       glossary row. */
    height: 100dvh;
    max-height: 100dvh;
    background: var(--bg-card);
    border-right: 1px solid var(--border-strong);
    box-shadow: 16px 0 48px rgba(0, 0, 0, 0.35);
    z-index: 600;
    transform: translateX(-110%);
    transition: transform 0.36s cubic-bezier(0.22, 1, 0.36, 1);
    overflow-y: auto;
    padding:
        max(16px, env(safe-area-inset-top, 16px))
        16px
        max(16px, env(safe-area-inset-bottom, 16px))
        16px;
}
body.resources-open .glossary-rail { transform: translateX(0); }
/* In-rail header: "Resources" title on the left + close × on the
   right. Title is the shimmer target after the panel slides in. */
.glossary-rail .resources-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
    padding: 0 4px;
}
.glossary-rail .resources-title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: 0.4px;
    color: var(--text-primary);
}
.glossary-rail .resources-close {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 999px;
    width: 28px; height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.glossary-rail .resources-close:hover {
    background: var(--bg-hover);
    color: var(--accent);
    border-color: var(--accent);
}
.glossary-rail .resources-body {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
}
/* Backdrop: invisible click-target on desktop so clicking outside the
   panel closes it (no visual dim — the chart stays clearly readable).
   Mobile gets a dim + blur so the sheet pattern reads. Sits just below
   the panel (600) and above the header (100) so the header is also
   click-to-dismiss. */
.resources-backdrop {
    position: fixed;
    inset: 0;
    background: transparent;
    z-index: 590;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s ease, background 0.3s ease;
}
body.resources-open .resources-backdrop {
    pointer-events: auto;
    opacity: 1;
}
@media (max-width: 1023px) {
    .glossary-rail {
        width: min(320px, 88vw);
    }
    body.resources-open .resources-backdrop {
        background: rgba(0, 0, 0, 0.36);
        backdrop-filter: blur(2px);
    }
}

/* Toggle handle lives inline in the .tabs-row (mounted by glossary.js)
   so it sits on the same horizontal baseline as the .tab-group pills
   (Stock Analysis / Crypto Analysis / Today / Tomorrow / Portfolio).
   Shape and metrics mirror .tab-group exactly: 4px outer + 8px inner
   vertical padding, 0.85rem font, 999px radius. */
.resources-toggle {
    /* Only enter the elevated stacking context while Resources is
       open (so the pill stays clickable above the overlay+backdrop).
       When closed, leave it in normal flow so it scrolls under the
       sticky .app-header instead of punching through it. */
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text-primary);
    padding: 4px 14px 4px 10px;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s;
}
.resources-toggle:hover {
    background: var(--bg-hover);
    color: var(--accent);
    border-color: var(--accent);
    transform: translateY(-1px);
}
.resources-toggle-icon { font-size: 1rem; line-height: 1; }
.resources-toggle-label {
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.4px;
    padding: 6px 0;
    line-height: 1;
}
/* Hide the toggle pill while Resources is open — the panel itself
   has its own × close button and the header strip the pill lives in
   should not show through the overlay. Earlier we lifted the pill
   above the panel (z-index 460 > overlay 450), but Roshan's correct
   read is that the pill shouldn't be visible at all once the panel
   takes the screen. */
body.resources-open .resources-toggle {
    visibility: hidden;
}

.main-container { min-width: 0; }

/* Theme-aware scrollbars across the whole app. CSS variables already
   carry per-theme colors; we just point the scrollbar pseudo-elements
   at them so dark / light / aurora each get a matching look.
   Webkit (Chrome/Edge/Safari) + Firefox both supported. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--scroll-thumb, var(--border-strong)) var(--scroll-track, transparent);
}
*::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}
*::-webkit-scrollbar-track {
    background: var(--scroll-track, transparent);
}
*::-webkit-scrollbar-thumb {
    background: var(--scroll-thumb, var(--border-strong));
    border-radius: 6px;
    border: 2px solid var(--bg-primary);
}
*::-webkit-scrollbar-thumb:hover {
    background: var(--scroll-thumb-hover, var(--accent));
}
*::-webkit-scrollbar-corner {
    background: var(--scroll-track, transparent);
}

.controls-section { margin-bottom: 16px; }
.tabs-row { display: flex; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.tab-group { display: inline-flex; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 999px; padding: 4px; }
.tab-btn {
    padding: 8px 16px;
    font-size: 0.85rem;
    font-weight: 600;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    border-radius: 999px;
    cursor: pointer;
    transition: all 0.15s;
}
.tab-btn.active {
    background: var(--brand-grad-2);
    color: #fff;
    box-shadow: 0 4px 14px var(--brand-grad-shadow);
}
.tab-btn:hover:not(.active) { color: var(--text-primary); }

.search-container {
    position: relative;
    display: flex; align-items: center;
}
.search-icon { position: absolute; left: 14px; pointer-events: none; }
.search-input {
    width: 100%;
    padding: 12px 14px 12px 38px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    font-size: 0.95rem;
    outline: none;
    transition: all 0.15s;
}
.search-input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.12);
}
.search-results {
    position: absolute; top: calc(100% + 4px); left: 0; right: 0;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    max-height: 320px; overflow-y: auto;
    z-index: 50;
    box-shadow: 0 8px 24px rgba(0,0,0,0.3);
    display: none;
}
.search-results.visible { display: block; }
.search-result-item {
    /* Symbol+name on the left, exchange code on the right, single row. */
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 14px;
    cursor: pointer;
    border-bottom: 1px solid var(--border);
    transition: background 0.15s;
}
.search-result-item:hover, .search-result-item.active { background: var(--bg-hover); }
.search-result-item:last-child { border-bottom: none; }
.search-result-item > div {
    /* Inner wrapper: symbol + name flow inline, name truncates if too long. */
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: baseline;
    gap: 8px;
    overflow: hidden;
}
.search-result-item .result-symbol {
    font-weight: 700;
    font-family: var(--num-font);
    flex-shrink: 0;
    color: var(--text-primary);
}
.search-result-item .result-name {
    font-size: 0.78rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.search-result-item > .result-name {
    /* The right-side exchange code chip */
    flex-shrink: 0;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.4px;
    color: var(--text-muted);
    padding: 2px 7px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: 4px;
    text-transform: uppercase;
}

.chart-section { margin-bottom: 16px; }
.chart-header { padding: 8px 0 12px; display: flex; align-items: center; gap: 12px; }
.chart-header.hidden { display: none; }
.chart-symbol { font-weight: 800; font-size: 1.1rem; font-family: var(--num-font); }
.chart-price {
    font-family: var(--num-font);
    font-size: 1rem;
    position: relative;
    padding: 4px 12px;
    border-radius: 999px;
    transition: color 0.4s ease;
    --price-pulse-period: 3s;
}
/* The ring lives in ::after so we can animate scale + opacity without
   touching layout. Fades when no signal is set (placeholder state). */
.chart-price::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 999px;
    border: 2px solid currentColor;
    opacity: 0;
    pointer-events: none;
}
.chart-price-buy {
    color: var(--green);
    background: rgba(45, 210, 139, 0.10);
}
.chart-price-sell {
    color: var(--red);
    background: rgba(239, 68, 68, 0.10);
}
.chart-price-neutral {
    color: var(--yellow);
    background: rgba(234, 179, 8, 0.10);
}
.chart-price-no_trade {
    color: var(--text-muted);
    background: rgba(148, 163, 184, 0.08);
}
.chart-price-buy::after,
.chart-price-sell::after,
.chart-price-neutral::after {
    animation: chart-price-pulse var(--price-pulse-period) ease-out infinite;
}
@keyframes chart-price-pulse {
    0%   { opacity: 0.55; transform: scale(1); }
    70%  { opacity: 0;    transform: scale(1.18); }
    100% { opacity: 0;    transform: scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
    .chart-price::after { animation: none !important; }
}
.chart-container {
    /* Use the page background so the empty-chart placeholder reads as
       seamless true black on dark mode, with a thin border to keep it
       visually distinct. Light + aurora themes still get their own
       tokens via the same variable. */
    background: var(--bg-primary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
    height: 360px;
}
#tradingview-widget { width: 100%; height: 100%; }
/* Aurora: keep the CHART background dark (near-black) rather than the deep
   purple page colour — the TradingView widget + candle placeholder read far
   better on a neutral dark canvas, and it matches the dark theme's chart. */
[data-theme="aurora"] .chart-container { background: #07060d; }

.signal-section { margin-bottom: 24px; }
.signal-box {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 18px;
}
.signal-box.buy { border-color: var(--green); box-shadow: 0 8px 24px rgba(45, 210, 139, 0.12); }
.signal-box.sell { border-color: var(--red); box-shadow: 0 8px 24px rgba(239, 68, 68, 0.12); }
.signal-box.neutral { border-color: var(--yellow); }
.signal-box.no_trade {
    border-color: var(--text-muted);
    border-style: dashed;
    background: linear-gradient(180deg, var(--bg-secondary), var(--bg-card));
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
    opacity: 0.92;
}
.signal-box.no_trade .confidence-fill { background: var(--text-muted); }
.signal-header { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.signal-arrow { font-size: 1.4rem; }
.signal-arrow.up { color: var(--green); }
.signal-arrow.down { color: var(--red); }
.signal-arrow.neutral { color: var(--yellow); }
.signal-arrow.abstain { color: var(--text-muted); }
.signal-label { font-size: 1.15rem; font-weight: 900; letter-spacing: 0.5px; }
.signal-label.buy { color: var(--green); }
.signal-label.sell { color: var(--red); }
.signal-label.neutral { color: var(--yellow); }
.signal-label.no_trade { color: var(--text-muted); }

.time-travel-wrap { position: relative; margin-left: 8px; }
.time-travel-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 0.78rem;
    font-weight: 700;
    transition: all 0.15s ease;
    -webkit-tap-highlight-color: transparent;
}
.time-travel-btn:hover { color: var(--accent); border-color: var(--accent); }
.time-travel-btn.active {
    color: #fff;
    background: var(--brand-grad-2);
    border-color: transparent;
    box-shadow: 0 4px 14px var(--brand-grad-shadow);
}
.time-travel-label { font-family: var(--num-font); }
.time-travel-popover {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 280px;
    padding: 14px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 32px rgba(0,0,0,0.25);
    z-index: 30;
    animation: tt-pop 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes tt-pop {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.time-travel-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 10px;
}
.time-travel-row label {
    font-size: 0.78rem;
    color: var(--text-secondary);
    font-weight: 700;
}
.time-travel-row input[type="date"] {
    padding: 8px 10px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 0.86rem;
    outline: none;
    color-scheme: dark light;
}
.time-travel-row input[type="date"]:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.15);
}
.time-travel-actions { display: flex; gap: 8px; margin-bottom: 10px; }
.tt-apply {
    flex: 1;
    padding: 8px;
    border: none;
    border-radius: var(--radius-sm);
    background: var(--brand-grad-2);
    color: #fff;
    font-weight: 800;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.tt-apply:hover { transform: translateY(-1px); box-shadow: 0 6px 18px var(--brand-grad-shadow); }
.tt-back-live {
    padding: 8px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 0.82rem;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.tt-back-live:hover { color: var(--accent); border-color: var(--accent); }
.time-travel-hint {
    font-size: 0.72rem;
    color: var(--text-muted);
    line-height: 1.45;
}

.watch-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; height: 32px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text-muted);
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
    -webkit-tap-highlight-color: transparent;
    margin-left: auto;
}
.watch-toggle:hover { color: var(--yellow); border-color: var(--yellow); transform: scale(1.06); }
.watch-toggle.watching {
    color: var(--yellow);
    border-color: var(--yellow);
    background: rgba(234, 179, 8, 0.08);
}
.watch-toggle:active { transform: scale(0.94); }

.watchlist-section { margin: 24px 0; }
.watchlist-details {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.watchlist-summary {
    padding: 14px 18px;
    cursor: pointer;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    user-select: none;
}
.watchlist-summary::-webkit-details-marker { display: none; }
.watchlist-summary::before {
    content: '▸';
    color: var(--text-muted);
    transition: transform 0.18s ease;
    margin-right: 6px;
}
.watchlist-details[open] .watchlist-summary::before { transform: rotate(90deg); }
.watchlist-title { font-weight: 800; color: var(--text-primary); }
.watchlist-hint { font-size: 0.78rem; color: var(--text-muted); margin-left: 12px; }
.watchlist-controls {
    display: flex; gap: 12px; align-items: center;
    padding: 12px 18px;
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
}
.watchlist-perm-btn {
    padding: 8px 14px;
    background: var(--brand-grad-2);
    color: #fff;
    border: none;
    border-radius: var(--radius-sm);
    font-weight: 700;
    font-size: 0.84rem;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.watchlist-perm-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 18px var(--brand-grad-shadow); }
.watchlist-perm-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; box-shadow: none; }
.watchlist-perm-state { font-size: 0.78rem; color: var(--text-muted); }
.watchlist-perm-state.on { color: var(--green); }

/* ── Notification toggle choreography ─────────────────────────────────────
   The Enable button lives in .watchlist-notif-row when OFF. When toggled ON it
   becomes "Turn off…" and is re-parented into .watchlist-notif-dock in the
   summary header, rendered as a glass pill. The closed-app checkbox sits beside
   Enable and fades out while docked. */
.watchlist-notif-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.watchlist-notif-dock { margin-left: auto; display: inline-flex; align-items: center; }

/* Glass treatment for the docked "Turn off browser notifications" button. */
.watchlist-perm-btn.is-on {
    background: var(--bg-glass);
    -webkit-backdrop-filter: blur(12px) saturate(140%);
    backdrop-filter: blur(12px) saturate(140%);
    border: 1px solid var(--border-strong);
    color: var(--text-primary);
    box-shadow: var(--shadow-control);
}
@media (prefers-reduced-motion: no-preference) {
    /* Swoosh: when the button lands in the dock (.is-on), it slides in from the
       left with a fade — reads as travelling rightward into the header. */
    .watchlist-perm-btn.is-on { animation: notif-swoosh-in 0.42s var(--ease-premium, cubic-bezier(0.22,1,0.36,1)) both; }
}
@keyframes notif-swoosh-in {
    from { opacity: 0; transform: translateX(-28px) scale(0.92); }
    to   { opacity: 1; transform: translateX(0) scale(1); }
}

/* Closed-app checkbox — fades in/out with the toggle state. */
.watchlist-closed-check {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 0.8rem; color: var(--text-secondary); cursor: pointer;
    transition: opacity 0.26s ease, transform 0.26s ease;
}
.watchlist-closed-check.fading-out { opacity: 0; transform: translateX(8px); pointer-events: none; }
.watchlist-closed-check input { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }
.watchlist-list {
    padding: 6px 18px 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.watchlist-empty { padding: 14px; color: var(--text-muted); font-style: italic; }
.watchlist-item {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color 0.15s ease, transform 0.15s ease;
}
.watchlist-item:hover { border-color: var(--accent); transform: translateY(-1px); }
.watchlist-row-main {
    display: grid;
    grid-template-columns: 1fr auto auto auto;
    align-items: center;
    gap: 10px;
}
.watchlist-alert-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0 2px;
    border-top: 1px dashed var(--border);
    font-size: 0.78rem;
    color: var(--text-muted);
    cursor: default;
    flex-wrap: wrap;
}
.watchlist-alert-row.stocks-disabled {
    border-top: none;
    padding: 4px 0 0;
    font-style: italic;
    opacity: 0.75;
}
.watchlist-alert-note { line-height: 1.4; }
.watchlist-live-price {
    font-family: var(--num-font);
    font-weight: 800;
    color: var(--text-primary);
    font-size: 0.92rem;
    min-width: 84px;
}
.watchlist-live-price.waiting {
    color: var(--text-muted);
    font-style: italic;
    font-weight: 500;
}
.watchlist-alert-field {
    display: flex;
    align-items: center;
    gap: 6px;
}
.watchlist-alert-field span {
    font-size: 0.74rem;
    color: var(--text-muted);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
}
.watchlist-alert-input {
    width: 84px;
    padding: 4px 6px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-xs, 4px);
    color: var(--text-primary);
    font-family: var(--num-font);
    font-size: 0.84rem;
    transition: border-color 0.15s ease;
}
.watchlist-alert-input:focus {
    outline: none;
    border-color: var(--accent);
}
.watchlist-symbol { font-weight: 800; color: var(--text-primary); }
.watchlist-meta { font-size: 0.76rem; color: var(--text-muted); font-style: italic; }
.watchlist-sig {
    font-size: 0.74rem;
    font-weight: 800;
    padding: 2px 10px;
    border-radius: 999px;
}
.watchlist-sig.sig-buy      { background: rgba(45, 210, 139, 0.14); color: var(--green); }
.watchlist-sig.sig-sell     { background: rgba(239, 68, 68, 0.14); color: var(--red); }
.watchlist-sig.sig-neutral  { background: rgba(234, 179, 8, 0.14); color: var(--yellow); }
.watchlist-sig.sig-no_trade { background: rgba(148, 163, 184, 0.14); color: var(--text-muted); }
.watchlist-conf {
    font-family: var(--num-font);
    font-weight: 700;
    color: var(--text-primary);
    font-size: 0.86rem;
}
.watchlist-remove {
    width: 22px; height: 22px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
    font-size: 0.7rem;
    line-height: 1;
}
.watchlist-remove:hover { color: var(--red); border-color: var(--red); background: rgba(239, 68, 68, 0.08); }

.scanner-section { margin: 28px 0; }
.scanner-details {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
}
.scanner-summary {
    padding: 14px 18px;
    cursor: pointer;
    display: flex;
    /* Left-align so the title sits next to the chevron, with the hint
       trailing it. space-between was pushing the hint to the far right
       on wide displays, dragging the title with it on narrow ones. */
    justify-content: flex-start;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    user-select: none;
}
.scanner-summary::-webkit-details-marker { display: none; }
.scanner-summary::before {
    content: '▸';
    font-size: 0.9rem;
    color: var(--text-muted);
    transition: transform 0.18s ease;
    margin-right: 6px;
}
.scanner-details[open] .scanner-summary::before { transform: rotate(90deg); }
.scanner-title { font-weight: 800; font-size: 1.0rem; color: var(--text-primary); }
.scanner-hint { font-size: 0.78rem; color: var(--text-muted); margin-left: 12px; }
.scanner-controls {
    display: flex;
    gap: 10px;
    padding: 12px 18px;
    border-top: 1px solid var(--border);
    align-items: center;
    flex-wrap: wrap;
}
.scanner-filter, .scanner-select {
    padding: 8px 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 0.86rem;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.scanner-filter:focus, .scanner-select:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.12);
}
.scanner-filter { flex: 1; min-width: 200px; }
.scanner-meta { font-size: 0.78rem; color: var(--text-muted); margin-left: auto; }
/* Accuracy time-window control — small label + number + unit
   dropdown, sized so the row stays compact. */
.scanner-window {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px 8px;
}
.scanner-window-label { font-size: 0.78rem; color: var(--text-secondary); }
.scanner-window-n {
    width: 56px;
    padding: 5px 8px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 0.84rem;
    text-align: right;
    outline: none;
    /* hide native number-input arrows so the field stays clean */
    -moz-appearance: textfield;
}
.scanner-window-n::-webkit-outer-spin-button,
.scanner-window-n::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.scanner-window-n:disabled { opacity: 0.5; }
.scanner-window-n:focus { border-color: var(--accent); }
.scanner-window-unit { padding: 5px 8px; font-size: 0.84rem; }
.scanner-tablewrap {
    max-height: 600px;
    overflow: auto;
    border-top: 1px solid var(--border);
}
.scanner-table {
    width: 100%;
    /* separate + vertical border-spacing turns each row into a free-standing
       card with a gap between rows (cards, not a dense grid). */
    border-collapse: separate;
    border-spacing: 0 6px;
    font-size: 0.84rem;
}
.scanner-table thead {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-card);
}
.scanner-table th {
    padding: 10px 12px;
    text-align: left;
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-secondary);
    cursor: pointer;
    border-bottom: 1px solid var(--border);
    user-select: none;
    white-space: nowrap;
}
.scanner-table th.sortable-num { text-align: right; }
.scanner-table th:hover { color: var(--accent); }
.scanner-table th.sorted { color: var(--accent); }
.scanner-table th.sort-asc::after  { content: ' ▲'; font-size: 0.7em; }
.scanner-table th.sort-desc::after { content: ' ▼'; font-size: 0.7em; }

/* Per-row "Load chart ↗" button — loads the symbol's chart + analysis above. */
.scanner-loadchart-btn {
    margin-left: 8px;
    padding: 2px 8px;
    font-size: 0.66rem;
    font-weight: 700;
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    background: var(--bg-card);
    color: var(--text-secondary);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.scanner-row:hover .scanner-loadchart-btn { opacity: 1; }
.scanner-loadchart-btn:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-1px); }

/* Full-Ledger focus overlay — row click zooms the analysis into a big card
   over a blurred backdrop; click the backdrop (or ×/Esc) to return. */
.ledger-focus-overlay {
    position: fixed; inset: 0; z-index: 1300;
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
    background: rgba(0, 0, 0, 0.45);
    -webkit-backdrop-filter: blur(8px) saturate(120%);
    backdrop-filter: blur(8px) saturate(120%);
    opacity: 0;
    transition: opacity 0.24s ease;
}
.ledger-focus-overlay.open { opacity: 1; }
.ledger-focus-card {
    position: relative;
    width: min(680px, 94vw);
    max-height: 86vh;
    overflow-y: auto;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card-hover);
    padding: 18px 20px;
    transform: scale(0.92) translateY(10px);
    transition: transform 0.26s var(--ease-spring, cubic-bezier(0.34,1.56,0.64,1));
}
.ledger-focus-overlay.open .ledger-focus-card { transform: scale(1) translateY(0); }
.ledger-focus-head { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.ledger-focus-sym { font-family: var(--num-font); font-weight: 900; font-size: 1.3rem; color: var(--text-primary); }
.ledger-focus-close {
    position: absolute; top: 14px; right: 16px;
    width: 30px; height: 30px; border-radius: 50%;
    border: 1px solid var(--border); background: var(--bg-secondary);
    color: var(--text-secondary); font-size: 1.1rem; cursor: pointer; line-height: 1;
}
.ledger-focus-close:hover { color: var(--accent); border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
    .ledger-focus-overlay, .ledger-focus-card { transition: none; }
}
.scanner-table td {
    padding: 10px 12px;
    white-space: nowrap;
    /* Each cell is a slice of the row-card: shared top/bottom border, card
       surface. First/last cells round the card's left/right edges. */
    background: var(--bg-card);
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
}
.scanner-row td:first-child {
    border-left: 1px solid var(--border);
    border-top-left-radius: var(--radius-sm);
    border-bottom-left-radius: var(--radius-sm);
}
.scanner-row td:last-child {
    border-right: 1px solid var(--border);
    border-top-right-radius: var(--radius-sm);
    border-bottom-right-radius: var(--radius-sm);
}
/* Row-as-card: zoom in on hover. transform on a <tr> needs a transform-box +
   the table to be border-collapse:separate (set above). We scale slightly and
   lift with a shadow + accent border, and raise z-index so the zoom sits above
   neighbouring cards. */
.scanner-row {
    cursor: pointer;
    transition: transform 0.16s var(--ease-spring, cubic-bezier(0.34,1.56,0.64,1)),
                box-shadow 0.16s ease, background 0.12s ease;
    position: relative;
}
.scanner-row:hover { z-index: 1; }
.scanner-row:hover td {
    background: var(--bg-hover);
    border-color: var(--accent);
}
@media (prefers-reduced-motion: no-preference) {
    .scanner-row:hover {
        transform: scale(1.015);
        box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.16);
    }
}
/* The expanded drawer row is NOT a card — neutralise the card cell styling so
   it reads as an attached panel under its row (no rounding/zoom/gap weirdness). */
.scanner-drawer-row td {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
    padding: 0;
}
.scanner-drawer-row:hover { transform: none; box-shadow: none; }
.scanner-symbol { font-weight: 700; color: var(--text-primary); }
.scanner-region { font-size: 0.76rem; color: var(--text-muted); }
.scanner-num { text-align: right; font-family: var(--num-font); }
.scanner-empty { text-align: center; padding: 30px; color: var(--text-muted); font-style: italic; }
.scanner-sig {
    font-weight: 700;
    font-size: 0.78rem;
    padding: 2px 8px;
    border-radius: 999px;
    display: inline-block;
}
.scanner-sig.sig-buy { background: rgba(45, 210, 139, 0.14); color: var(--green); }
.scanner-sig.sig-sell { background: rgba(239, 68, 68, 0.14); color: var(--red); }
.scanner-sig.sig-neutral { background: rgba(234, 179, 8, 0.14); color: var(--yellow); }
.scanner-sig.sig-no_trade { background: rgba(148, 163, 184, 0.14); color: var(--text-muted); }
.scanner-conf-bar {
    display: inline-block;
    width: 60px;
    height: 4px;
    background: var(--bg-card);
    border-radius: 999px;
    overflow: hidden;
    vertical-align: middle;
    margin-right: 8px;
}
.scanner-conf-fill {
    display: block;
    height: 100%;
    background: var(--accent);
    border-radius: 999px;
}
.scanner-conf-num { color: var(--text-primary); font-weight: 700; }
.hit-yes     { color: var(--green);  font-weight: 700; }
.hit-no      { color: var(--red);    font-weight: 700; }
.hit-pending { color: var(--text-muted); font-style: italic; }

/* Full Ledger summary icon — small SVG sitting between the chevron
   and the title. Replaces the old 📊 emoji which was misaligned and
   theme-ignorant. */
.scanner-icon {
    display: inline-flex;
    align-items: center;
    color: var(--accent);
    margin-right: 8px;
}

/* Symbol cell: clickable link styling so the user knows it loads
   into the main chart. The rest of the row still toggles the inline
   drawer; the link just stops propagation in the click handler. */
.scanner-symbol-link {
    color: var(--text-primary);
    text-decoration: none;
    border-bottom: 1px dashed var(--border-strong);
    transition: color 0.15s ease, border-color 0.15s ease;
}
.scanner-symbol-link:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

/* Prediction Accuracy cell — three stacked rows (frac, pct + label,
   gradient bar). Color flows through the gradient computed in JS so
   the cell tints smoothly red→amber→green with the percentage. */
.acc-cell {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 3px;
    min-width: 130px;
}
.acc-frac {
    font-family: var(--num-font);
    font-weight: 700;
    font-size: 0.86rem;
}
/* Per-number tint inside the hits/misses/total/days cell. Hits +
   misses use a tone-class set by the JS (.acc-tone-good / -mid /
   -bad / -mute) so the colors reflect actual engine performance,
   not just the static label. See fmtAccuracy() in scanner.js for
   the rules. total + days are neutral (they're counts, not verdicts).
   Slashes stay muted so they read as separators. */
.acc-tone-good { color: var(--green); }
.acc-tone-bad  { color: var(--red); }
.acc-tone-mid  { color: var(--yellow); }     /* coin-flip: amber */
.acc-tone-mute { color: var(--text-muted); }
.acc-total     { color: var(--accent); opacity: 0.85; }
.acc-days      { color: var(--text-muted); font-weight: 600; }
.acc-sep       { color: var(--text-muted); margin: 0 1px; opacity: 0.6; font-weight: 500; }
.acc-pct {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.3px;
}
.acc-bar {
    width: 100%;
    height: 4px;
    background: var(--bg-hover);
    border-radius: 999px;
    overflow: hidden;
}
.acc-bar-fill {
    height: 100%;
    border-radius: 999px;
    transition: width 0.4s ease;
}
.acc-empty {
    font-size: 0.74rem;
    color: var(--text-muted);
    font-style: italic;
}

/* Inline drawer that expands beneath a clicked row. Recreates the
   key fields from the detail-card analysis (verdict, sources,
   targets, drivers) inside the table, so the user doesn't have to
   leave Full Ledger to see the engine's reasoning. */
.scanner-drawer-row { background: var(--bg-secondary); }
.scanner-drawer-row > td { padding: 0 !important; }
.scanner-drawer {
    padding: 16px 20px;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border-strong);
    animation: drawer-slide-down 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes drawer-slide-down {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 14px;
}
.drawer-verdict {
    display: inline-flex;
    align-items: baseline;
    gap: 10px;
}
.drawer-verdict-arrow { font-size: 1.4rem; }
.drawer-verdict.buy .drawer-verdict-arrow { color: var(--green); }
.drawer-verdict.sell .drawer-verdict-arrow { color: var(--red); }
.drawer-verdict.no_trade .drawer-verdict-arrow,
.drawer-verdict.neutral .drawer-verdict-arrow { color: var(--text-muted); }
.drawer-verdict-label { font-weight: 800; letter-spacing: 0.6px; font-size: 1.05rem; }
.drawer-verdict-conf {
    font-family: var(--num-font);
    color: var(--text-secondary);
    font-size: 0.86rem;
    font-weight: 700;
}
.drawer-close {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 999px;
    width: 28px; height: 28px;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.drawer-close:hover { background: var(--bg-hover); color: var(--accent); border-color: var(--accent); }

.drawer-section-title {
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-secondary);
    margin: 14px 0 8px;
    font-weight: 700;
}
.drawer-sources { display: flex; flex-direction: column; gap: 6px; }
.drawer-source {
    display: grid;
    grid-template-columns: 160px 1fr 36px;
    gap: 10px;
    align-items: center;
    font-size: 0.84rem;
}
.drawer-source-label { color: var(--text-secondary); font-weight: 600; }
.drawer-source-weight { color: var(--text-muted); font-weight: 500; }
.drawer-source-bar {
    height: 5px;
    background: var(--bg-hover);
    border-radius: 999px;
    overflow: hidden;
}
.drawer-source-fill {
    display: block;
    height: 100%;
    background: var(--accent);
    border-radius: 999px;
    transition: width 0.5s ease;
}
.drawer-source-score { font-family: var(--num-font); text-align: right; color: var(--text-primary); font-weight: 700; }

.drawer-targets {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 12px;
    margin-top: 10px;
}
.drawer-target {
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px 12px;
}
.drawer-target-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
.drawer-target-value { font-family: var(--num-font); font-weight: 700; color: var(--text-primary); }
.drawer-target-value.high { color: var(--green); }
.drawer-target-value.low  { color: var(--red); }

.drawer-reasons { margin: 0; padding-left: 18px; color: var(--text-secondary); font-size: 0.86rem; line-height: 1.6; }
.drawer-reasons li { margin-bottom: 3px; }
.drawer-empty-reasons { color: var(--text-muted); font-style: italic; font-size: 0.84rem; }

.drawer-foot { margin-top: 14px; display: flex; justify-content: flex-end; }
.drawer-load-chart {
    background: var(--accent);
    color: #fff;
    border: 0;
    padding: 8px 14px;
    border-radius: 999px;
    font-size: 0.82rem;
    font-weight: 700;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.drawer-load-chart:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(var(--accent-rgb), 0.32);
}

.horizon-bands {
    margin-top: 10px;
    padding: 10px 12px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.horizon-bands-title {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 8px;
}
.horizon-bands-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(60px, 1fr));
    gap: 8px;
}
.horizon-band {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding: 6px 8px;
    background: var(--bg-secondary);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    cursor: help;
}
.horizon-band-label {
    font-size: 0.7rem;
    color: var(--text-muted);
    text-align: center;
    font-weight: 600;
    margin-bottom: 2px;
}
.horizon-band-rate {
    font-family: var(--num-font);
    font-size: 0.95rem;
    font-weight: 800;
    text-align: center;
    margin-bottom: 4px;
}
.horizon-band.high .horizon-band-rate { color: var(--green); }
.horizon-band.mid  .horizon-band-rate { color: var(--yellow); }
.horizon-band.low  .horizon-band-rate { color: var(--red); }
.horizon-band-bar {
    height: 3px;
    background: var(--bg-card);
    border-radius: 999px;
    overflow: hidden;
}
.horizon-band-fill.high { background: var(--green); }
.horizon-band-fill.mid  { background: var(--yellow); }
.horizon-band-fill.low  { background: var(--red); }
.horizon-band-fill {
    height: 100%;
    transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.attribution-section {
    margin: 14px 0;
    padding: 12px 14px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.attribution-title {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 10px;
}
.attribution-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 6px 0;
    border-bottom: 1px solid var(--border);
}
.attribution-row:last-child { border-bottom: none; }
.attribution-arrow {
    flex-shrink: 0;
    font-size: 0.8rem;
    width: 16px;
    text-align: center;
    margin-top: 2px;
}
.attribution-arrow.positive { color: var(--green); }
.attribution-arrow.negative { color: var(--red); }
.attribution-arrow.neutral  { color: var(--yellow); }
.attribution-body { flex: 1; min-width: 0; }
.attribution-label {
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 4px;
}
.attribution-bar {
    height: 5px;
    background: var(--bg-secondary);
    border-radius: 999px;
    overflow: hidden;
    margin-bottom: 4px;
}
.attribution-fill {
    height: 100%;
    border-radius: 999px;
    /* Sequential reveal: each row's bar fills with a stagger so the user
       feels the engine "thinking through" each indicator. CSS-only,
       triggered fresh on every signal-box render via key-frame replay. */
    transform-origin: left center;
    animation: attribution-grow 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.attribution-row:nth-child(1) .attribution-fill { animation-delay: 0.05s; }
.attribution-row:nth-child(2) .attribution-fill { animation-delay: 0.20s; }
.attribution-row:nth-child(3) .attribution-fill { animation-delay: 0.35s; }
.attribution-row:nth-child(4) .attribution-fill { animation-delay: 0.50s; }
@keyframes attribution-grow {
    from { transform: scaleX(0); opacity: 0.4; }
    to   { transform: scaleX(1); opacity: 1; }
}
/* The arrow + label fade in alongside the bar so the row feels coherent. */
.attribution-row {
    animation: attribution-row-in 0.45s ease both;
}
.attribution-row:nth-child(1) { animation-delay: 0.00s; }
.attribution-row:nth-child(2) { animation-delay: 0.15s; }
.attribution-row:nth-child(3) { animation-delay: 0.30s; }
.attribution-row:nth-child(4) { animation-delay: 0.45s; }
@keyframes attribution-row-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.attribution-fill.positive { background: var(--green); }
.attribution-fill.negative { background: var(--red); }
.attribution-fill.neutral  { background: var(--yellow); }
.attribution-evidence {
    font-size: 0.74rem;
    color: var(--text-muted);
    line-height: 1.35;
}
.signal-confidence { font-family: var(--num-font); font-size: 1.4rem; font-weight: 900; margin-left: auto; }
.conf-range { font-family: var(--num-font); font-size: 0.78rem; color: var(--text-muted); }
.trend-chip {
    font-size: 0.66rem; padding: 3px 8px;
    background: var(--bg-card); border: 1px solid var(--border);
    border-radius: 999px; color: var(--text-secondary);
    text-transform: uppercase; letter-spacing: 0.4px; font-weight: 800;
}
.cal-badge {
    font-size: 0.62rem; padding: 2px 6px; border-radius: 999px;
    text-transform: uppercase; letter-spacing: 0.5px; font-weight: 800;
}
.cal-badge.calibrated { background: var(--green-bg); color: var(--green); border: 1px solid var(--green); }
.cal-badge.raw { background: var(--yellow-bg); color: var(--yellow); border: 1px solid var(--yellow); }
.cal-badge.live {
    background: color-mix(in srgb, var(--accent) 15%, transparent);
    color: var(--accent);
    border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
    animation: cal-badge-live-pulse 2.5s ease-in-out infinite;
}
@keyframes cal-badge-live-pulse {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 25%, transparent); }
    50%      { box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    .cal-badge.live { animation: none; }
}
.cal-delta-row { font-size: 0.74rem; color: var(--text-muted); margin-top: 4px; }
.cal-delta { font-family: var(--num-font); }
.refresh-btn {
    padding: 6px 14px; border: 1px solid var(--border); background: var(--bg-card);
    color: var(--text-primary); border-radius: 999px; cursor: pointer; font-weight: 700; font-size: 0.78rem;
}
.refresh-btn.small { padding: 4px 10px; font-size: 0.74rem; }
.refresh-btn:hover { border-color: var(--accent); color: var(--accent); }
.refresh-btn.spinning { animation: spin 1s linear infinite; }
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

.confidence-bar {
    height: 8px; background: var(--bg-hover); border-radius: 999px;
    overflow: hidden; margin: 12px 0;
}
.confidence-fill {
    height: 100%;
    transition: width 0.4s ease;
    border-radius: 999px;
}
.confidence-fill.high { background: linear-gradient(90deg, #2dd28b, #4a9eff); }
.confidence-fill.medium { background: linear-gradient(90deg, #fbbf24, #4a9eff); }
.confidence-fill.low { background: linear-gradient(90deg, #ef4444, #fbbf24); }

.source-breakdown { margin: 14px 0; }
.breakdown-title { font-size: 0.7rem; color: var(--text-muted); margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.6px; font-weight: 800; }
.breakdown-bars { display: flex; flex-direction: column; gap: 6px; }
.breakdown-item { display: grid; grid-template-columns: 140px 1fr 38px; align-items: center; gap: 12px; font-size: 0.84rem; }
.breakdown-label { color: var(--text-secondary); font-size: 0.78rem; }
.breakdown-bar { height: 6px; background: var(--bg-hover); border-radius: 999px; overflow: hidden; }
.breakdown-fill { height: 100%; transition: width 0.4s ease; border-radius: 999px; }
.breakdown-score { font-family: var(--num-font); font-weight: 700; text-align: right; }

.insight-summary { margin: 14px 0; line-height: 1.6; font-size: 0.92rem; }
.highlight-green { color: var(--green); font-weight: 700; }
.highlight-red { color: var(--red); font-weight: 700; }
.highlight-yellow { color: var(--yellow); font-weight: 700; }

.price-targets { margin: 14px 0; padding: 14px; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-md); }
.price-targets-title { font-size: 0.74rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px; font-weight: 800; margin-bottom: 10px; }
.price-targets-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.price-target-card { padding: 10px 12px; background: var(--bg-secondary); border-radius: var(--radius-sm); border: 1px solid var(--border); }
.price-target-label { font-size: 0.66rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; font-weight: 700; }
.price-target-value { font-family: var(--num-font); font-size: 1.05rem; font-weight: 800; margin-top: 4px; }
.price-target-value.high { color: var(--green); }
.price-target-value.low { color: var(--red); }
.price-target-pct { font-size: 0.78rem; font-family: var(--num-font); margin-top: 2px; }
.price-target-pct.up { color: var(--green); }
.price-target-pct.down { color: var(--red); }
.price-targets-meta { font-size: 0.74rem; color: var(--text-muted); margin-top: 10px; }
.probable-strip {
    display: flex; align-items: center; gap: 10px;
    margin: 0 0 12px;
    padding: 10px 14px;
    background: color-mix(in srgb, var(--accent) 12%, var(--bg-secondary));
    border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
    border-radius: var(--radius-sm);
    font-size: 0.92rem;
    cursor: help;
}
.probable-label {
    text-transform: uppercase; letter-spacing: 0.6px; font-size: 0.66rem; font-weight: 800;
    color: var(--accent);
    padding: 2px 8px;
    background: color-mix(in srgb, var(--accent) 18%, transparent);
    border-radius: 3px;
    flex-shrink: 0;
}
.probable-low, .probable-high { font-family: var(--num-font); font-weight: 700; color: var(--text-primary); }
.probable-arrow { color: var(--text-muted); }
.probable-pct { font-size: 0.78rem; color: var(--text-secondary); margin-left: auto; font-family: var(--num-font); }
@media (max-width: 540px) {
    .probable-strip { flex-wrap: wrap; gap: 6px 10px; }
    .probable-pct { margin-left: 0; width: 100%; }
}

.section-subtitle { font-size: 0.74rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px; font-weight: 800; margin: 14px 0 8px; }
.technical-section { margin-top: 12px; }
/* Live indicator snapshot chips — the actual computed numbers for the
   current symbol, tinted by bull/bear/neutral reading. */
.tech-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 10px; }
.tech-chip {
    display: inline-flex; align-items: baseline; gap: 5px;
    padding: 3px 9px; border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-card);
    font-size: 0.72rem; line-height: 1.2;
}
.tech-chip-k { color: var(--text-secondary); font-weight: 600; letter-spacing: 0.02em; }
.tech-chip-v { color: var(--text-primary); font-weight: 700; font-variant-numeric: tabular-nums; }
.tech-chip.positive { border-color: rgba(45, 210, 139, 0.45); background: rgba(45, 210, 139, 0.10); }
.tech-chip.positive .tech-chip-v { color: var(--green); }
.tech-chip.negative { border-color: rgba(239, 68, 68, 0.45); background: rgba(239, 68, 68, 0.10); }
.tech-chip.negative .tech-chip-v { color: var(--red); }
.tech-chip.neutral-strong { border-color: rgba(var(--accent-rgb), 0.45); background: rgba(var(--accent-rgb), 0.10); }
.tech-chip.neutral-strong .tech-chip-v { color: var(--accent); }
.accordion-list { display: flex; flex-direction: column; gap: 6px; }
.accordion-item { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.accordion-header { display: flex; align-items: center; gap: 10px; padding: 8px 12px; cursor: pointer; list-style: none; user-select: none; }
.accordion-header::-webkit-details-marker { display: none; }
.accordion-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.accordion-dot.positive { background: var(--green); }
.accordion-dot.negative { background: var(--red); }
.accordion-dot.neutral { background: var(--yellow); }
.accordion-header-content { flex: 1; min-width: 0; }
.accordion-title { font-size: 0.84rem; line-height: 1.45; }
.accordion-chevron { transition: transform 0.2s; color: var(--text-muted); }
.accordion-item[open] .accordion-chevron { transform: rotate(90deg); }
.accordion-body { padding: 0 12px 10px 28px; font-size: 0.82rem; color: var(--text-secondary); line-height: 1.5; }
.accordion-explanation { padding-top: 6px; border-top: 1px dashed var(--border); }
/* Flat (non-expandable) variant for technical-indicator rows that
   have no extra detail to surface beyond the title — saves the user
   from clicking only to find "this indicator provides context"
   placeholder text. Inherits the same row layout but without the
   pointer cursor / chevron. */
.tech-accordion-flat .accordion-header { cursor: default; padding: 6px 12px; }

.signal-meta { font-size: 0.74rem; color: var(--text-muted); }
.risk-disclaimer { margin-top: 14px; padding: 10px 12px; background: var(--bg-card); border-left: 2px solid var(--yellow); font-size: 0.74rem; color: var(--text-muted); border-radius: 4px; }
.risk-disclaimer strong { color: var(--text-primary); }

.hotpicks-section { margin-bottom: 24px; }
.section-header { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
.section-title { font-size: 1.05rem; font-weight: 800; }
.hotpicks-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.hot-pick-card {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 12px;
    cursor: pointer;
    transition: all 0.15s;
    display: flex; flex-direction: column; gap: 4px;
    min-height: 130px;
}
.hot-pick-card.buy { border-left: 3px solid var(--green); }
.hot-pick-card.sell { border-left: 3px solid var(--red); }
.hot-pick-card.neutral { border-left: 3px solid var(--yellow); }
.hot-pick-card:hover { transform: translateY(-2px); border-color: var(--accent); box-shadow: 0 8px 24px var(--brand-grad-shadow); }
.hot-pick-symbol { font-family: var(--num-font); font-weight: 800; font-size: 1rem; }
.hot-pick-name { font-size: 0.72rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hot-pick-spark { height: 30px; margin: 4px 0; }
.spark-placeholder { height: 30px; background: var(--bg-hover); border-radius: 4px; opacity: 0.4; }
.hot-pick-signal-badge { font-size: 0.62rem; font-weight: 800; padding: 2px 8px; border-radius: 999px; text-transform: uppercase; letter-spacing: 0.5px; align-self: flex-start; }
.hot-pick-signal-badge.buy { background: var(--green-bg); color: var(--green); border: 1px solid var(--green); }
.hot-pick-signal-badge.sell { background: var(--red-bg); color: var(--red); border: 1px solid var(--red); }
.hot-pick-signal-badge.neutral { background: var(--yellow-bg); color: var(--yellow); border: 1px solid var(--yellow); }
.hot-pick-confidence { font-family: var(--num-font); font-weight: 800; font-size: 0.92rem; }
.hot-pick-confidence.buy { color: var(--green); }
.hot-pick-confidence.sell { color: var(--red); }
.hot-pick-confidence.neutral { color: var(--yellow); }
.hot-pick-arrow { display: inline-block; }
/* Spike-expected line: shows magnitude of the predicted upside as a
   percent. Bright accent + ⚡ icon to telegraph "this is the
   forecast move size", distinct from confidence. */
.hot-pick-spike {
    font-family: var(--num-font);
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--accent);
    letter-spacing: 0.2px;
    margin-top: 2px;
}

/* High / Low / Current price target rows. Two-line layout per row:
   muted descriptor on top ("Expected Highest Reach"), the actual
   price below. Color-coded so green = upside target, red = downside,
   neutral = current price reference. */
.hot-pick-target {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin-top: 4px;
    line-height: 1.25;
}
.hot-pick-target-label {
    font-size: 0.66rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
}
.hot-pick-target-value {
    font-family: var(--num-font);
    font-size: 0.84rem;
    font-weight: 700;
}
.hot-pick-target-high .hot-pick-target-value { color: var(--green); }
.hot-pick-target-low  .hot-pick-target-value { color: var(--red); }
.hot-pick-current-price {
    /* Override the default flex layout from .hot-pick-price so the
       two-line stack works the same as the high/low rows. */
    display: flex !important;
    flex-direction: column;
    align-items: flex-start;
    margin-top: 4px;
}
.hot-pick-current-price .hot-pick-target-value { color: var(--text-primary); }
.hot-pick-price { font-family: var(--num-font); font-size: 0.82rem; color: var(--text-secondary); }
.hp-skel-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.hp-skel { height: 130px; background: var(--bg-hover); border-radius: var(--radius-md); animation: skel-pulse 1.6s ease-in-out infinite; }
@keyframes skel-pulse { 0%,100% { opacity: 0.6; } 50% { opacity: 0.3; } }

.loading { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 32px; color: var(--text-secondary); }
.loader { width: 28px; height: 28px; border: 3px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; }
.loading-text { font-size: 0.88rem; }
.loading-tip { font-size: 0.74rem; color: var(--text-muted); font-style: italic; }

/* Candlestick skeleton loader. Renders a row of OHLC bars whose body
   heights, wick lengths, and colors animate in a staggered loop —
   visually says "we are computing a market chart" instead of generic
   spinner. Used on the multi-second analysis screen where the user
   stares at the loader long enough to notice. */
/* Premium "live-market" loader — bars breathe as a smooth travelling wave
   (scaleY from a shared baseline, GPU transform not top/bottom thrash), each
   capped with a soft glow, and a faint scan-sheen drifts across the whole row.
   Reads as the engine actively pulsing through the data rather than a choppy
   grow. Same markup hooks (.cl-bar/.cl-wick/.cl-body) so JS is untouched. */
.candle-loader {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 64px;
    margin: 6px 0 4px;
    position: relative;
    overflow: hidden;
}
.candle-loader .cl-bar {
    position: relative;
    width: 8px;
    height: 60%;
    display: flex;
    align-items: center;
    justify-content: center;
}
.candle-loader .cl-wick {
    position: absolute;
    top: -18%;
    bottom: -18%;
    left: 50%;
    width: 1.5px;
    transform: translateX(-50%);
    border-radius: 1px;
    background: currentColor;
    opacity: 0.35;
}
.candle-loader .cl-body {
    position: absolute;
    inset: 0;
    border-radius: 3px;
    background: linear-gradient(180deg, currentColor, color-mix(in srgb, currentColor 55%, transparent));
    box-shadow: 0 0 8px color-mix(in srgb, currentColor 45%, transparent);
    transform-origin: center;
    animation: cl-wave 1.25s cubic-bezier(0.45, 0, 0.55, 1) infinite;
    will-change: transform, opacity;
}
.candle-loader .cl-bar.up   { color: var(--green); }
.candle-loader .cl-bar.down { color: var(--red); }
.candle-loader .cl-bar:nth-child(1) .cl-body { animation-delay: 0.00s; }
.candle-loader .cl-bar:nth-child(2) .cl-body { animation-delay: 0.09s; }
.candle-loader .cl-bar:nth-child(3) .cl-body { animation-delay: 0.18s; }
.candle-loader .cl-bar:nth-child(4) .cl-body { animation-delay: 0.27s; }
.candle-loader .cl-bar:nth-child(5) .cl-body { animation-delay: 0.36s; }
.candle-loader .cl-bar:nth-child(6) .cl-body { animation-delay: 0.45s; }
.candle-loader .cl-bar:nth-child(7) .cl-body { animation-delay: 0.54s; }
@keyframes cl-wave {
    0%, 100% { transform: scaleY(0.35); opacity: 0.45; }
    50%      { transform: scaleY(1);    opacity: 1; }
}
/* Scan-sheen sweeping across the loader. */
.candle-loader::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, transparent 40%, rgba(var(--accent-rgb), 0.18) 50%, transparent 60%);
    transform: translateX(-100%);
    animation: cl-sheen 1.8s ease-in-out infinite;
    pointer-events: none;
}
@keyframes cl-sheen { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) {
    .candle-loader .cl-body { animation: none; transform: scaleY(0.6); }
    .candle-loader::after { display: none; }
}

.error-message { padding: 16px; background: var(--red-bg); color: var(--red); border: 1px solid var(--red); border-radius: var(--radius-md); }
.empty-state { text-align: center; padding: 48px 16px; color: var(--text-muted); }
.empty-state-icon { font-size: 2.4rem; margin-bottom: 8px; }

.fade-in { animation: fade-in 0.3s ease-out; }
@keyframes fade-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }

.accuracy-strip { font-size: 0.78rem; color: var(--text-muted); padding: 4px 0 12px; }

@media (max-width: 768px) {
    .app-layout { padding: 12px; gap: 12px; }
    .header-actions { right: 12px; gap: 6px; }
    .header-btn, .theme-toggle { width: 32px; height: 32px; font-size: 0.85rem; }
    .signal-box { padding: 14px; }
    .signal-confidence { font-size: 1.2rem; }
    .price-targets-grid { grid-template-columns: 1fr; }
    .breakdown-item { grid-template-columns: 100px 1fr 30px; gap: 8px; }
}

/* ────────────────────────────────────────────────────────────────────
   Phone breakpoint (≤540px) — iPhone 17 Pro logical width is 402pt.
   Roshan's brief: "looks so squeezed in and looks like the web version
   when added as a Safari home-screen shortcut". Address each squeeze
   point: tabs row wrapping cleanly, Portfolio button visible (icon-
   only on mobile is fine), search input full width, cards roomier,
   Full Ledger table horizontally scrollable but readable, side panels
   take full width with safe-area inset for the iPhone home-bar.
   ──────────────────────────────────────────────────────────────────── */
@media (max-width: 540px) {
    /* Page surfaces — respect iPhone safe areas (notch + home bar) */
    body { padding-bottom: env(safe-area-inset-bottom, 0); }
    .app-layout {
        padding: 10px max(10px, env(safe-area-inset-left, 10px))
                 14px max(10px, env(safe-area-inset-right, 10px));
        gap: 10px;
    }
    .app-header {
        padding: max(10px, env(safe-area-inset-top, 10px))
                 max(14px, env(safe-area-inset-right, 14px))
                 10px
                 max(14px, env(safe-area-inset-left, 14px));
    }
    .app-title { font-size: 1.05rem; letter-spacing: 0.3px; }
    .app-title-portfolio-svg { width: 18px; height: 18px; }
    .header-ecg { display: none; }    /* save horizontal space */
    .header-actions { right: max(10px, env(safe-area-inset-right, 10px)); gap: 4px; }
    /* Tap-target floor: 36×36 minimum on phones. Apple HIG says 44pt;
       we cheat slightly because the gear/theme/portfolio icons are
       reachable in a tight cluster and 44 each would crowd the row. */
    .header-btn, .theme-toggle { width: 36px; height: 36px; }

    /* Tabs row — wrap onto multiple lines without squishing */
    .tabs-row { gap: 6px; margin-bottom: 8px; row-gap: 8px; }
    .tab-group { padding: 3px; }
    .tab-btn { padding: 6px 12px; font-size: 0.78rem; }
    .resources-toggle { padding: 3px 10px 3px 8px; }
    .resources-toggle-label { font-size: 0.78rem; padding: 5px 0; }

    /* Portfolio launcher — show as compact pill with icon visible.
       The pre-existing rule at portfolio.css:731 hid the LABEL on
       phones, but the icon span was nested inside the label so the
       whole button became invisible. The HTML is fixed (icon is now
       a sibling of the label) and we keep the label visible too at
       this size since there's room. */
    .portfolio-launcher { padding: 6px 12px; font-size: 0.78rem; margin-left: 0; }
    .portfolio-launcher-icon { width: 12px; height: 12px; }

    /* Search row — input takes the full row, results dropdown is
       100% wide so suggestions don't truncate awkwardly. */
    .controls-section { margin-bottom: 12px; }
    .search-container { width: 100%; }
    .search-input { font-size: 0.9rem; padding: 10px 12px 10px 36px; }
    .search-results { max-height: 60vh; }

    /* Chart + signal cards — roomier interior so text doesn't crowd */
    .chart-container { height: 280px; }
    .chart-header { padding: 6px 0 10px; flex-wrap: wrap; gap: 8px; }
    .signal-section { margin-bottom: 16px; }
    .signal-box { padding: 16px; }
    .signal-confidence { font-size: 1.1rem; }
    .source-breakdown .breakdown-item {
        grid-template-columns: 92px 1fr 28px;
        gap: 6px;
        font-size: 0.78rem;
    }

    /* Hot Picks grid — stay 2-up on phones (was auto-fill 160px which
       would only fit one column on a 402pt screen). 2 columns reads
       as a proper grid, not a stack. */
    .hotpicks-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px;
    }
    .hot-pick-card { padding: 10px; min-height: 120px; }
    .hot-pick-symbol { font-size: 0.92rem; }
    .hot-pick-confidence { font-size: 0.86rem; }
    .penny-tabs { flex-wrap: wrap; gap: 4px; }

    /* Full Ledger — let the table scroll horizontally inside its
       wrapper so cells stay readable instead of getting crushed. */
    .scanner-summary { padding: 10px 12px; }
    .scanner-title { font-size: 0.92rem; }
    .scanner-hint { display: none; }
    .scanner-controls { padding: 10px 12px; gap: 6px; }
    .scanner-filter { min-width: 140px; }
    .scanner-window { flex-wrap: wrap; padding: 4px 6px; }
    .scanner-window-n { width: 44px; }
    .scanner-tablewrap { max-height: 70vh; -webkit-overflow-scrolling: touch; }
    .scanner-table { font-size: 0.78rem; min-width: 640px; }
    .scanner-table th, .scanner-table td { padding: 6px 8px; }
    .acc-cell { min-width: 110px; }
    .acc-frac { font-size: 0.78rem; }

    /* Side panels (Mia + Portfolio) — full width on phones. The panel
       itself starts at top: 0 (covers the notch area) but the FIRST
       child is the header which now carries safe-area-inset-top
       padding, so the close button + title sit below the dynamic
       island. Bottom padding clears the iPhone home indicator. */
    .mia-panel, .portfolio-panel {
        width: 100vw !important;
        max-width: 100vw !important;
        padding-bottom: env(safe-area-inset-bottom, 0);
    }
    /* Side-panel headers — push below the iPhone notch so the close
       buttons aren't trapped under the dynamic island. The class on
       Mia is .mia-head (single 'head'), not .mia-header — earlier rule
       targeted the wrong class so Mia's notch fix never took effect. */
    .portfolio-panel-head,
    .mia-head { padding-top: max(14px, env(safe-area-inset-top, 14px)); }

    /* Mia launcher — slightly smaller + nudged inward so it doesn't
       crash the right edge or the home indicator. */
    .mia-launcher { width: 48px; height: 48px; bottom: max(16px, env(safe-area-inset-bottom, 16px)); right: 16px; }
    .mia-launcher-logo { width: 36px; height: 26px; }

    /* Resources panel as a left sheet — full width, safe-area top */
    .glossary-rail { width: min(320px, 96vw); padding-top: max(16px, env(safe-area-inset-top, 16px)); }

    /* Notification stack — narrow + safe-area top */
    .ma-notify-container {
        top: max(12px, env(safe-area-inset-top, 12px));
        left: 12px;
        width: calc(100vw - 24px);
    }
}
