/* ============================================================
   Atkin Research — Design System
   Dark theme, clean financial aesthetic
   ============================================================ */

:root {
    --bg-primary: #0a0e17;
    --bg-secondary: #111827;
    --bg-card: #1a2236;
    --bg-input: #0f1629;
    --border: #1e293b;
    --border-focus: #3b82f6;
    --text-primary: #f1f5f9;
    --text-secondary: #94a3b8;
    --text-muted: #64748b;
    --accent: #3b82f6;
    --accent-hover: #2563eb;
    --accent-glow: rgba(59, 130, 246, 0.15);
    --success: #10b981;
    --error: #ef4444;
    --warning: #f59e0b;
    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', monospace;
    --radius: 8px;
    --radius-lg: 12px;
    /* Tokens for colors that used to be written out in the rules below - dark values are those exact colors, so the
       dark theme is unchanged; the light theme redefines them. */
    --border-strong: #334155;
    --surface-deep: #0f172a;
    --surface-deep-2: #0d1220;
    --text-body: #cbd5e1;
    --text-strong: #e2e8f0;
    --link: #60a5fa;
    --good-text: #10b981;
    --good-soft: #34d399;
    --bad-text: #ef4444;
    --bad-soft: #f87171;
    --watch-text: #fbbf24;
    --cyan-text: #22d3ee;
    --warning-text: #f59e0b;
    --orange-text: #f97316;
    --brand-text: #d9d5cf;
    color-scheme: dark;
}

/* Light theme (mobile mockup's light view): chosen with the sun/moon button, remembered per device. Same accent and
   status hues; darker text tones so green/red/amber text stays readable on white. */
:root[data-theme="light"] {
    --bg-primary: #f1f5f9;
    --bg-secondary: #ffffff;
    --bg-card: #ffffff;
    --bg-input: #ffffff;
    --border: #e2e8f0;
    --border-focus: #3b82f6;
    --text-primary: #0f172a;
    --text-secondary: #475569;
    --text-muted: #64748b;
    --accent-glow: rgba(59, 130, 246, 0.12);
    --border-strong: #cbd5e1;
    --surface-deep: #ffffff;
    --surface-deep-2: #f8fafc;
    --text-body: #334155;
    --text-strong: #1e293b;
    --link: #1d4ed8;
    --good-text: #047857;
    --good-soft: #047857;
    --bad-text: #b91c1c;
    --bad-soft: #b91c1c;
    --watch-text: #b45309;
    --cyan-text: #0e7490;
    --warning-text: #b45309;
    --orange-text: #c2410c;
    --brand-text: #1e293b;
    color-scheme: light;
}

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

/* The UA stylesheet's [hidden]{display:none} loses to ANY same-specificity
   author rule that sets display on the same element (e.g. .auth-form,
   .macro-panel, .form-group all set their own `display`) since author
   rules always beat the UA origin regardless of selector - so an element
   with both a class setting display and a `hidden` attribute silently
   stays visible (confirmed live: login.html's reset-password form,
   `<form class="auth-form" hidden>`, rendered stacked below the sign-in
   form instead of staying hidden). Toggle visibility via el.hidden, not
   inline style.display, and this reset makes that actually work. */
[hidden] {
    display: none !important;
}

body {
    font-family: var(--font-sans);
    background: var(--bg-primary);
    color: var(--text-primary);
    line-height: 1.6;
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    /* Defensive hardening against accidental horizontal overflow (e.g. a
       negative-margin full-bleed trick like the mobile world-clock
       ticker's own edge-to-edge fix, elsewhere in this file, coming out
       a pixel or two wider than intended on some device) - the page
       itself should never be side-scrollable/pannable regardless of a
       stray few px anywhere in the layout. */
    overflow-x: hidden;
}

/* ---- Modern hover tooltip (replaces native browser title bubbles site-wide;
   any element with a data-tooltip="..." attribute gets one automatically -
   see the delegated listener in base.html) ---- */
.app-tooltip {
    position: fixed;
    z-index: 9999;
    /* min(300px, 85vw) instead of a bare 300px - on a narrow phone a fixed
       300px tooltip could span nearly the whole screen width, sitting
       flush against both edges; capping it relative to the viewport keeps
       it comfortably inset regardless of screen size. */
    max-width: min(300px, 85vw);
    padding: 7px 11px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
    color: var(--text-primary);
    font-size: 0.78rem;
    font-weight: 400;
    line-height: 1.45;
    white-space: pre-line;
    pointer-events: none;
    opacity: 0;
    transform: translateY(3px) scale(0.98);
    transition: opacity 0.1s ease, transform 0.1s ease;
    left: 0;
    top: 0;
}

.app-tooltip.visible {
    opacity: 1;
    transform: translateY(0) scale(1);
}

/* A finger-tap tooltip is read at arm's length: a touch more size and width */
@media (pointer: coarse) {
    .app-tooltip {
        max-width: calc(100vw - 16px);
        width: max-content;
        padding: 10px 13px;
        font-size: 0.88rem;
    }
}

/* ---- Navbar ---- */
.navbar {
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 100;
    backdrop-filter: blur(12px);
}

.nav-container-full {
    display: flex;
    height: 56px;
    align-items: center;
    width: 100%;
}

.nav-brand-area {
    width: 260px;
    min-width: 260px;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    transition: width 0.25s ease, min-width 0.25s ease;
}

.nav-main-area {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 24px;
    min-width: 0;
}

.nav-brand {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    text-decoration: none;
    color: var(--text-primary);
}

.brand-logo {
    height: 42px;
    width: auto;
}

.brand-name {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: 2px;
    color: var(--brand-text);
    margin-bottom: -4px;
}

.brand-text {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -0.3px;
}

/* Mobile-only user row sharing the logo's own line (see the <=800px
   override below that actually shows this) - hidden on desktop by
   default, where .nav-user/Login/Sign Up stay in .nav-right instead. */
.nav-brand-mobile-actions {
    display: none;
}
/* Circular initials avatar - opens the same hamburger drawer as the
   desktop hamburger button (see base.html's shared hamburger IIFE).
   Real per-user customization (a chosen color/photo) isn't built yet;
   this covers "put their initials in there" with the site's own accent
   color for everyone for now. */
.nav-avatar-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    border: none;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
}
.nav-avatar-initials {
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.nav-right {
    display: flex;
    align-items: center;
    gap: 16px;
}

/* Site-wide scrolling world-clock ticker, sitting in the top nav between
   the per-page center content (e.g. the ticker-analysis search box) and
   the login/account controls - a compact inline strip rather than the
   full-width block this used to be on the Macro Dashboard page alone.
   Track content is duplicated (see base.html's JS) and animated -50% so
   the loop is seamless; pausing on hover lets you actually read one
   before it moves. */
.world-clock-ticker {
    /* Grows to fill all space between .nav-analyze and .nav-right - no
       max-width cap (that used to exist here, back when .nav-analyze itself
       grew and needed the room) - see the .nav-analyze comment above. */
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg-card);
    padding: 4px 0;
    margin: 0 16px;
}
.world-clock-ticker-track { display: inline-block; white-space: nowrap; animation: world-clock-scroll 120s linear infinite; }
.world-clock-ticker:hover .world-clock-ticker-track { animation-play-state: paused; }
.world-clock-ticker-item { display: inline-block; padding: 0 14px; font-size: 0.72rem; color: var(--text-secondary); font-family: var(--font-mono); }
.world-clock-ticker-item strong { color: var(--text-primary); font-family: inherit; margin-right: 4px; }
.world-clock-ticker-item.is-night { opacity: 0.7; }
.world-clock-ticker-item.is-night strong { color: #90a4ae; }
@keyframes world-clock-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* Second scrolling strip, sitting directly under the world-clock ticker as
   its own full-width row (not squeezed into the same nav line - that row
   is already tight with brand/search/user controls). Same duplicated-
   content -50% loop technique as world-clock-ticker, own <-- shorter -->
   animation duration so a handful of symbols doesn't crawl as slowly as
   the 31-city clock strip does. */
.market-ticker-wrap {
    overflow: hidden;
    white-space: nowrap;
    border-top: 1px solid var(--border);
    background: var(--bg-secondary);
    padding: 3px 0;
}
.market-ticker-track { display: inline-block; white-space: nowrap; animation: market-ticker-scroll 40s linear infinite; }
.market-ticker-wrap:hover .market-ticker-track { animation-play-state: paused; }
.market-ticker-item { display: inline-block; padding: 0 16px; font-size: 0.72rem; font-family: var(--font-mono); color: var(--text-secondary); }
.market-ticker-item strong { color: var(--text-primary); font-family: inherit; margin-right: 5px; }
/* Dedicated names (not the .v-green/.v-red used elsewhere) since this
   ticker lives in base.html, rendered on every page - several of which
   (dashboard.html, admin.html, terms/privacy) never define those classes
   at all, only macro_dashboard.html/thirteenf.html/politician_trades.html
   do, locally, in their own <style> blocks. */
.market-ticker-up { color: var(--success); }
.market-ticker-down { color: var(--error); }
.market-ticker-amber { color: var(--warning); }
.market-ticker-flat { color: var(--text-muted); }
@keyframes market-ticker-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.nav-user {
    color: var(--text-secondary);
    font-size: 14px;
    white-space: nowrap;
}

.nav-pro-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--accent-glow);
    color: var(--accent);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    vertical-align: middle;
}

.nav-link {
    color: var(--text-muted);
    text-decoration: none;
    font-size: 14px;
    transition: color 0.15s;
}

.nav-link:hover {
    color: var(--text-primary);
}

/* ---- Hamburger Menu ---- */
.hamburger-wrap {
    position: relative;
}

.hamburger-btn {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 32px;
    height: 32px;
    padding: 6px;
    background: none;
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    transition: background 0.15s;
}

.hamburger-btn:hover {
    background: rgba(148,163,184,0.1);
}

.hamburger-btn span {
    display: block;
    width: 100%;
    height: 2px;
    background: var(--text-secondary);
    border-radius: 1px;
    transition: transform 0.2s, opacity 0.2s;
}

.hamburger-btn.open span:nth-child(1) {
    transform: translateY(6px) rotate(45deg);
}
.hamburger-btn.open span:nth-child(2) {
    opacity: 0;
}
.hamburger-btn.open span:nth-child(3) {
    transform: translateY(-6px) rotate(-45deg);
}

.hamburger-menu {
    /* fixed, not absolute: it's rendered as a sibling of .navbar (see the
       markup comment in base.html), not nested inside .hamburger-wrap, so
       there's no positioned ancestor to anchor an absolute box to. top/right
       are computed from the button's actual screen position by
       positionDesktopMenu() in base.html's hamburger IIFE and set inline;
       these are just pre-JS fallback values. */
    position: fixed;
    top: 64px;
    right: 16px;
    min-width: 180px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.3);
    padding: 6px 0;
    z-index: 1000;
    /* Closed state (desktop dropdown): faded + nudged up, not display:none -
       display can't be transitioned, and the mobile drawer below needs this
       same open/closed toggle to actually animate. visibility flips at the
       end of the close transition so it's unreachable by tab/click while
       hidden, without needing a display swap. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
}

.hamburger-menu.open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 0.18s ease, transform 0.18s ease;
}

/* Hidden/inert everywhere except the <=800px drawer below, mirroring
   .sidebar-backdrop's own base-rule-plus-media-override pattern. */
.hamburger-backdrop {
    display: none;
}

.hamburger-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px;
    color: var(--text-primary);
    text-decoration: none;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.3;
    transition: background 0.15s;
}

.hl-icon {
    width: 16px;
    height: 16px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.8;
}

.hamburger-link:hover {
    background: rgba(148,163,184,0.08);
}

.hamburger-link-danger {
    color: var(--red, #ef4444);
    border-top: 1px solid var(--border);
    margin-top: 4px;
    padding-top: 12px;
}

.hamburger-link-danger:hover {
    background: rgba(239,68,68,0.08);
}

.hamburger-divider {
    height: 1px;
    background: var(--border);
    margin: 6px 0;
}

/* A <button> version of .hamburger-link (a page-specific ACTION, not
   navigation - e.g. the Macro Dashboard's own "Reset card order") -
   strips the native button chrome a plain .hamburger-link <a> doesn't
   carry, so the two read as one consistent list. */
.hamburger-link-btn {
    background: none;
    border: none;
    width: 100%;
    text-align: left;
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.3;
    cursor: pointer;
}

/* ---- Navbar Analyze Input ----
   Deliberately shrink-to-fit (not flex:1/centered) and pulled in close to
   the logo, so the freed horizontal space goes to the world-clock ticker
   next to it, which DOES want to grow (see .world-clock-ticker below). */
.nav-analyze {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 0 0 auto;
    margin: 0 20px 0 4px;
}

.nav-tagline {
    font-size: 13px;
    color: var(--text-secondary);
    white-space: nowrap;
    font-weight: 500;
    letter-spacing: -0.2px;
}

.nav-macro-link {
    font-size: 13px;
    color: var(--accent);
    white-space: nowrap;
    font-weight: 500;
    text-decoration: none;
    padding-left: 12px;
    border-left: 1px solid var(--border);
}

.nav-macro-link:hover {
    color: var(--accent-hover);
    text-decoration: underline;
}

.nav-input-row {
    display: flex;
    gap: 8px;
    flex: 0 0 auto;
}

/* Fixed width, not flex:1 - .nav-analyze is shrink-to-fit now (see above),
   so a flex:1 child here would collapse toward its 0% basis instead of
   growing, since there's no extra space in a content-sized parent to
   grow into. */
.nav-ticker-input {
    flex: 0 0 auto;
    width: 150px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 7px 12px;
    font-size: 14px;
    font-family: var(--font-mono);
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: 1px;
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
    min-width: 0;
}

.nav-ticker-input:focus {
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--accent-glow);
}

.nav-ticker-input::placeholder {
    text-transform: none;
    letter-spacing: normal;
    font-family: var(--font-sans);
    color: var(--text-muted);
    font-size: 13px;
}

.nav-ticker-input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn-nav {
    padding: 7px 16px;
    font-size: 13px;
    white-space: nowrap;
}

.nav-usage-note {
    font-size: 11px;
    color: var(--text-muted);
    white-space: nowrap;
}

.nav-paywall {
    margin-top: 0;
    padding: 4px 10px;
    font-size: 12px;
}

/* ---- App Layout (Sidebar + Main) ---- */
.app-layout {
    display: flex;
    min-height: calc(100vh - 56px);
}

.sidebar {
    width: 260px;
    min-width: 260px;
    background: var(--bg-secondary);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    transition: margin-left 0.25s ease, opacity 0.25s ease;
    overflow: hidden;
    position: relative;
    z-index: 50;
}

.sidebar.collapsed {
    margin-left: -260px;
    opacity: 0;
    pointer-events: none;
}

.sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 16px 12px;
    border-bottom: 1px solid var(--border);
}

.sidebar-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.sidebar-toggle {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 4px;
    border-radius: 4px;
    display: flex;
    align-items: center;
    transition: color 0.15s, background 0.15s;
}

.sidebar-toggle:hover {
    color: var(--text-primary);
    background: var(--bg-card);
}

.sidebar-expand {
    position: fixed;
    left: 0;
    top: 72px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-left: none;
    border-radius: 0 6px 6px 0;
    color: var(--text-secondary);
    cursor: pointer;
    padding: 8px 6px;
    display: none;
    align-items: center;
    z-index: 51;
    transition: color 0.15s, background 0.15s;
}

.sidebar-expand:hover {
    color: var(--text-primary);
    background: var(--bg-card);
}

.sidebar-expand.visible {
    display: flex;
}

/* Re-armed by JS every time the sidebar is FRESHLY collapsed (including
   on page load if it was already collapsed last visit) - not a one-time-
   ever "discovered" flag, which used to permanently silence this the
   first time it was ever clicked, leaving a returning user with nothing
   but a small muted pill to notice on their own. 3 pulses is enough to
   catch the eye without pulsing forever while the drawer just sits
   collapsed. */
.sidebar-expand.visible.pulse-hint {
    animation: sidebar-expand-pulse 2s ease-out 3;
}

@keyframes sidebar-expand-pulse {
    0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.55); }
    70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
    100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}

/* Sidebar filters */
.sidebar-filters {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
}

.sidebar-filter-input,
.sidebar-filter-select {
    width: 100%;
    padding: 5px 8px;
    font-size: 11px;
    font-family: var(--font-sans);
    background: var(--bg-primary);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 4px;
    outline: none;
    transition: border-color 0.15s;
    box-sizing: border-box;
}

.sidebar-filter-input:focus,
.sidebar-filter-select:focus {
    border-color: var(--accent);
}

.sidebar-filter-date {
    color-scheme: dark;
}

.sidebar-filter-input:disabled,
.sidebar-filter-select:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    background: var(--bg-secondary, var(--bg-primary));
}

/* Framework tags on report cards */
.sidebar-report-frameworks {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    margin-bottom: 5px;
}

.sidebar-fw-tag {
    font-size: 9px;
    font-weight: 500;
    padding: 1px 6px;
    border-radius: 3px;
    background: rgba(99, 179, 237, 0.12);
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.sidebar-content {
    flex: 1;
    overflow-y: auto;
    padding: 8px 0;
}

.sidebar-report-list {
    display: flex;
    flex-direction: column;
}

.sidebar-report {
    padding: 10px 16px;
    border-bottom: 1px solid var(--border);
    transition: background 0.15s;
}

.sidebar-report.filter-hidden {
    display: none;
}

.sidebar-report:last-child {
    border-bottom: none;
}

.sidebar-report:hover {
    background: var(--bg-card);
}

.sidebar-report-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 2px;
}

.sidebar-report-ticker {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 14px;
    letter-spacing: 0.5px;
    color: var(--text-primary);
}

.sidebar-report-status {
    font-size: 10px;
    font-weight: 500;
    padding: 2px 8px;
    border-radius: 20px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.sidebar-report-date {
    font-size: 11px;
    color: var(--text-muted);
    margin-bottom: 6px;
}

.sidebar-report-actions {
    display: flex;
    gap: 6px;
}

.sidebar-btn {
    padding: 3px 10px;
    font-size: 11px;
    font-weight: 500;
    border: 1px solid var(--accent);
    background: transparent;
    color: var(--accent);
    border-radius: 4px;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s;
    font-family: var(--font-sans);
}

.sidebar-btn:hover {
    background: var(--accent-glow);
}

.sidebar-btn-dl {
    border-color: var(--border);
    color: var(--text-secondary);
}

.sidebar-btn-dl:hover {
    border-color: var(--text-muted);
    background: var(--bg-input);
}

.sidebar-btn-delete {
    border-color: var(--border);
    color: var(--text-muted);
}

.sidebar-btn-delete:hover {
    border-color: var(--error);
    color: var(--error);
    background: rgba(239, 68, 68, 0.1);
}

.sidebar-btn-delete:disabled {
    opacity: 0.5;
    cursor: default;
}

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

.sidebar-footer {
    padding: 12px 16px;
    border-top: 1px solid var(--border);
    text-align: center;
}

.sidebar-legal-links {
    display: flex;
    justify-content: center;
    gap: 4px;
    margin-bottom: 6px;
}

.sidebar-legal-links a {
    font-size: 11px;
    color: var(--text-muted);
    text-decoration: none;
    transition: color 0.15s;
}

.sidebar-legal-links a:hover {
    color: var(--accent);
    text-decoration: underline;
}

.sidebar-legal-sep {
    color: var(--border);
    font-size: 11px;
}

.sidebar-copyright {
    font-size: 10px;
    color: var(--text-muted);
    margin-bottom: 4px;
}

.sidebar-disclaimer {
    font-size: 9px;
    color: var(--text-muted);
    opacity: 0.7;
    line-height: 1.3;
}

/* ---- Main Content ---- */
.main-content {
    flex: 1;
    min-width: 0;
    max-width: 1100px;
    padding: 0 24px;
}

/* ---- Auth Pages ---- */
/* .main-content is `flex:1; max-width:1100px` with no auto margins, so it
   sits flush against wherever the sidebar would be rather than centering
   itself in the viewport - invisible on pages with a sidebar eating the
   extra width, but on the login page (no sidebar block) it left-anchors
   the whole 1100px box on any screen wider than that, dragging this
   already-self-centered card off to the left of the real page center.
   `position: fixed` sidesteps that parent entirely - percentages/viewport
   units for a fixed element resolve against the true viewport, not
   whatever width-constrained ancestor it happens to sit inside, so this
   centers correctly regardless of .main-content's own layout (no change
   needed there, so every other page is unaffected). 56px matches the
   navbar's own fixed height used elsewhere in this file (e.g. the old
   min-height calc this replaces).*/
.auth-container {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    top: 56px;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 40px 24px;
    overflow-y: auto;
    box-sizing: border-box;
}

.auth-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 40px;
    width: 100%;
    max-width: 400px;
}

.auth-header {
    text-align: center;
    margin-bottom: 32px;
}

.auth-header h1 {
    font-size: 22px;
    font-weight: 600;
    margin-bottom: 6px;
}

.auth-subtitle {
    color: var(--text-muted);
    font-size: 14px;
}

.auth-form {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.form-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.form-group label {
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
}

.form-group input {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 14px;
    font-size: 15px;
    color: var(--text-primary);
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
    font-family: var(--font-sans);
}

.form-group input:focus {
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--accent-glow);
}

.form-group input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.form-hint {
    font-size: 12px;
    color: var(--text-muted);
}

/* Google sign-in button */
.btn-google {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 10px 16px;
    font-size: 14px;
    font-weight: 500;
    font-family: var(--font-sans);
    color: var(--text-primary);
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s, border-color 0.15s;
}

.btn-google:hover {
    background: var(--bg-card);
    border-color: var(--text-muted);
}

.btn-google svg {
    flex-shrink: 0;
}

/* Auth divider */
.auth-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 20px 0;
    color: var(--text-muted);
    font-size: 12px;
}

.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--border);
}

.auth-footer {
    text-align: center;
    margin-top: 24px;
    font-size: 14px;
    color: var(--text-muted);
}

.auth-footer a {
    color: var(--accent);
    text-decoration: none;
    font-weight: 500;
}

.auth-footer a:hover {
    text-decoration: underline;
}

/* Auth legal footer */
.auth-legal {
    text-align: center;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
    font-size: 11px;
    color: var(--text-muted);
    line-height: 1.6;
}

.auth-legal a {
    color: var(--text-secondary);
    text-decoration: none;
}

.auth-legal a:hover {
    color: var(--accent);
    text-decoration: underline;
}

.auth-legal-sep {
    margin: 0 4px;
}

/* ---- Alerts ---- */
.alert {
    padding: 10px 14px;
    border-radius: var(--radius);
    font-size: 14px;
    margin-bottom: 16px;
}

.alert-error {
    background: rgba(239, 68, 68, 0.1);
    border: 1px solid rgba(239, 68, 68, 0.3);
    color: #fca5a5;
}

.alert-info {
    background: rgba(99, 179, 237, 0.1);
    border: 1px solid rgba(99, 179, 237, 0.3);
    color: #90cdf4;
}

/* Verification code input */
.input-code {
    text-align: center;
    font-size: 24px !important;
    font-family: var(--font-mono) !important;
    letter-spacing: 8px;
    padding: 12px 16px !important;
}

/* Resend code link */
.auth-resend {
    text-align: center;
    margin-top: 12px;
}

.btn-link {
    background: none;
    border: none;
    color: var(--accent);
    font-size: 13px;
    font-family: var(--font-sans);
    cursor: pointer;
    text-decoration: underline;
    padding: 0;
}

.btn-link:hover {
    color: var(--text-primary);
}

/* Forgot password link */
.form-link {
    color: var(--accent);
    text-decoration: none;
    display: inline-block;
    margin-top: 2px;
}

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

/* ---- Buttons ---- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 20px;
    border: none;
    border-radius: var(--radius);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    transition: all 0.15s;
    font-family: var(--font-sans);
}

.btn-primary {
    background: var(--accent);
    color: #fff;
}

.btn-primary:hover:not(:disabled) {
    background: var(--accent-hover);
}

.btn-primary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn-secondary {
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
}

.btn-secondary:hover {
    background: var(--bg-card);
    border-color: var(--text-muted);
}

/* ---- Support/Sales contact modal (base.html, site-wide) - replaces
   plain mailto: links, which do nothing visible without a configured
   mail client. Posts to /api/contact. ---- */
@keyframes contactModalIn {
    from { opacity: 0; transform: translateY(8px) scale(0.97); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}
.contact-modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(6, 9, 16, 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.contact-modal {
    width: 100%;
    max-width: 440px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(59, 130, 246, 0.06);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: contactModalIn 0.18s ease-out;
}
@media (prefers-reduced-motion: reduce) {
    .contact-modal { animation: none; }
}
.contact-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 18px 20px;
    background: linear-gradient(180deg, var(--bg-secondary), var(--bg-card));
    border-bottom: 1px solid var(--border);
}
.contact-modal-header span {
    font-weight: 600;
    font-size: 1rem;
    letter-spacing: -0.01em;
    color: var(--text-primary);
}
.contact-modal-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    background: transparent;
    border: none;
    border-radius: 50%;
    color: var(--text-muted);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.contact-modal-close:hover { color: var(--text-primary); background: var(--bg-input); }
.contact-modal-body { padding: 20px; display: flex; flex-direction: column; gap: 8px; }
.contact-modal-label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}
.contact-modal-textarea {
    width: 100%;
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px;
    font-family: var(--font-sans);
    font-size: 0.9rem;
    line-height: 1.5;
    resize: vertical;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.contact-modal-textarea::placeholder { color: var(--text-muted); }
.contact-modal-textarea:focus {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--accent-glow);
}
.contact-modal-status {
    font-size: 0.82rem;
    min-height: 1.2em;
    transition: all 0.15s;
}
.contact-modal-status.error,
.contact-modal-status.success {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 10px;
    border-radius: var(--radius);
    font-weight: 500;
}
.contact-modal-status.error { color: var(--bad-soft); background: rgba(239, 68, 68, 0.12); }
.contact-modal-status.success { color: var(--good-soft); background: rgba(16, 185, 129, 0.12); }
.contact-modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 14px 20px;
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
}

.btn-outline {
    background: transparent;
    color: var(--accent);
    border: 1px solid var(--accent);
}

.btn-outline:hover {
    background: var(--accent-glow);
}

.btn-full {
    width: 100%;
}

.btn-lg {
    padding: 12px 28px;
    font-size: 15px;
}

.btn-sm {
    padding: 6px 12px;
    font-size: 12px;
}

/* ---- Framework Selector Bar ---- */
.tagline-quote {
    text-align: center;
    font-style: italic;
    color: var(--text-secondary);
    font-size: 13px;
    padding: 8px 0 4px;
    opacity: 0.7;
}
.tagline-quote .quote-credit {
    font-style: normal;
    font-size: 11px;
    opacity: 0.8;
}

.framework-bar {
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border);
    padding: 10px 0;
    margin-bottom: 24px;
    border-radius: var(--radius);
}

.fw-bar-inner {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 0 4px;
}

.fw-bar-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    white-space: nowrap;
}

.fw-chips {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.fw-chip {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 20px;
    cursor: pointer;
    transition: all 0.15s;
    user-select: none;
    position: relative;
}

.fw-chip:hover {
    border-color: var(--text-muted);
}

.fw-chip input {
    display: none;
}

.fw-chip input:checked + .fw-chip-label {
    color: var(--accent);
}

.fw-chip input:checked ~ .fw-chip-label {
    color: var(--accent);
}

.fw-chip:has(input:checked) {
    border-color: var(--accent);
    background: var(--accent-glow);
}

.fw-chip-label {
    font-size: 12px;
    font-weight: 500;
    color: var(--text-muted);
    white-space: nowrap;
    transition: color 0.15s;
}

.fw-tooltip {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    width: 340px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 18px;
    z-index: 200;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    pointer-events: none;
}

.fw-tooltip::after {
    content: "";
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--border);
}

.fw-chip:hover .fw-tooltip {
    display: block;
}

.fw-tooltip strong {
    display: block;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
}

.fw-tip-section {
    display: block;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-secondary);
    margin-bottom: 8px;
}

.fw-tip-section:last-child {
    margin-bottom: 0;
}

.fw-tip-heading {
    display: block;
    font-size: 11px;
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.3px;
    margin-bottom: 2px;
}

.fw-suggestion {
    font-size: 11px;
    color: var(--text-muted);
    font-style: italic;
    margin-left: auto;
    white-space: nowrap;
}

/* ---- Dashboard ---- */
.dashboard {
    padding: 24px 0 80px;
}

.section-hero {
    text-align: center;
    margin-bottom: 48px;
}

.hero-title {
    font-size: 32px;
    font-weight: 700;
    letter-spacing: -0.5px;
    margin-bottom: 8px;
}

.hero-subtitle {
    color: var(--text-muted);
    font-size: 16px;
    margin-bottom: 32px;
}

.analyze-box {
    max-width: 520px;
    margin: 0 auto;
}

.input-row {
    display: flex;
    gap: 12px;
}

.ticker-input-wrapper {
    flex: 1;
}

.ticker-input-wrapper input {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 16px;
    font-size: 16px;
    font-family: var(--font-mono);
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: 1px;
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.ticker-input-wrapper input:focus {
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--accent-glow);
}

.ticker-input-wrapper input::placeholder {
    text-transform: none;
    letter-spacing: normal;
    font-family: var(--font-sans);
    color: var(--text-muted);
}

.paywall-notice {
    margin-top: 16px;
    padding: 12px 16px;
    background: rgba(245, 158, 11, 0.08);
    border: 1px solid rgba(245, 158, 11, 0.25);
    border-radius: var(--radius);
    font-size: 14px;
    color: var(--warning);
}

.paywall-notice a {
    color: var(--warning);
    font-weight: 600;
}

.usage-note {
    margin-top: 12px;
    font-size: 13px;
    color: var(--text-muted);
}

.upgrade-buttons {
    display: flex;
    gap: 8px;
    margin-top: 8px;
}

.btn-paypal {
    background: #0070ba;
    color: #fff;
    border: none;
    border-radius: var(--radius);
    padding: 6px 14px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
}
.btn-paypal:hover { background: #005ea6; }

.pro-badge {
    background: linear-gradient(135deg, #f59e0b, #d97706);
    color: #000;
    font-weight: 700;
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 10px;
    letter-spacing: 0.5px;
}

/* ---- Job Section ---- */
.section-job {
    margin-bottom: 48px;
}

.job-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 24px;
    max-width: 1700px;
}

.job-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
}
.job-header .job-status {
    flex: 1;
}
.job-header .section-minimize-btn {
    margin-left: auto;
}

.job-ticker-badge {
    font-family: var(--font-mono);
    font-size: 18px;
    font-weight: 700;
    background: var(--accent-glow);
    color: var(--accent);
    padding: 4px 14px;
    border-radius: 6px;
    letter-spacing: 1px;
}

.job-status {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    color: var(--text-secondary);
}

.spinner {
    width: 18px;
    height: 18px;
    border: 2px solid var(--border);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

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

.job-progress {
    margin-bottom: 16px;
}

.progress-bar {
    height: 4px;
    background: var(--bg-input);
    border-radius: 2px;
    overflow: hidden;
}

.progress-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--accent), #6366f1);
    border-radius: 2px;
    width: 0%;
    transition: width 0.5s ease;
}

.progress-fill.indeterminate {
    width: 30%;
    animation: indeterminate 1.5s ease-in-out infinite;
}

@keyframes indeterminate {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(400%); }
}

.job-log {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px;
    max-height: 280px;
    overflow-y: auto;
    margin-bottom: 16px;
}

@media (max-width: 800px) {
    /* the raw progress log is diagnostics - a short scrolling strip on a phone, not a screen of "=====" lines */
    .job-log { max-height: 110px; padding: 10px; }
    .job-log pre { font-size: 10.5px !important; white-space: pre-wrap; word-break: break-word; }
}

.job-log pre {
    font-family: var(--font-mono);
    font-size: 12px;
    line-height: 1.6;
    color: var(--text-secondary);
    white-space: pre-wrap;
    word-break: break-word;
}

.job-actions {
    display: flex;
    gap: 12px;
    justify-content: center;
}

.job-error {
    text-align: center;
}

.job-error p {
    color: var(--error);
    font-size: 14px;
    margin-bottom: 12px;
}

/* ---- PDF Viewer ---- */
/* Interactive Chart Viewer */
.section-chart {
    margin-bottom: 24px;
}

.chart-viewer-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    max-width: 1700px;
}

.chart-viewer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px;
    border-bottom: 1px solid var(--border);
}

.chart-viewer-header h2 {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
}
.chart-viewer-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}
.crosshair-lock-btn {
    font-size: 11px;
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.15s;
}
.crosshair-lock-btn.active {
    background: rgba(59,130,246,0.15);
    border-color: #3b82f6;
    color: var(--link);
}
.crosshair-lock-btn:not(.active) {
    background: rgba(148,163,184,0.1);
    border-color: #475569;
    color: var(--text-secondary);
}
#pattern-toggle-btn.active {
    background: rgba(59,130,246,0.15);
    border-color: #3b82f6;
    color: var(--link);
}

/* Pro-only candlestick pattern customization panel (see dashboard.html's
   pattern-settings-panel, gated server-side by user.is_pro) */
.pattern-settings-panel {
    padding: 12px 20px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-input);
}
.pattern-settings-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 8px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.pattern-settings-pro-badge {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--accent-glow);
    color: var(--accent);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}
.pattern-settings-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
    margin-bottom: 8px;
    font-size: 12px;
    color: var(--text-secondary);
}
.pattern-settings-row label {
    display: flex;
    align-items: center;
    gap: 5px;
    cursor: pointer;
    white-space: nowrap;
}
.pattern-category-label input[type="color"] {
    width: 20px;
    height: 20px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: none;
    cursor: pointer;
}
.pattern-search-input {
    width: 100%;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text-primary);
    padding: 6px 10px;
    font-size: 12px;
    margin-bottom: 8px;
}
.pattern-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 4px 12px;
    max-height: 140px;
    overflow-y: auto;
}
.pattern-list label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--text-secondary);
    cursor: pointer;
}

/* Section minimize button (used in job header & chart header) */
.section-minimize-btn {
    background: none;
    border: 1px solid var(--border);
    color: var(--text-muted);
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 4px;
    display: flex;
    align-items: center;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.section-minimize-btn:hover {
    color: var(--text-primary);
    background: var(--bg-card);
    border-color: var(--text-muted);
}

/* Section expand tab (appears when section is minimized) */
.section-expand-tab {
    display: none;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    color: var(--text-muted);
    cursor: pointer;
    font-size: 12px;
    font-weight: 500;
    margin-bottom: 8px;
    max-width: 1000px;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.section-expand-tab:not(.hidden) {
    display: flex;
}
.section-expand-tab:hover {
    color: var(--text-primary);
    background: var(--bg-secondary);
    border-color: var(--text-muted);
}

/* Minimized state for sections */
.section-job.minimized .job-card,
.section-chart.minimized .chart-viewer-card {
    display: none;
}

.chart-summary {
    background: var(--surface-deep);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 16px 20px;
    margin-bottom: 12px;
    font-family: 'JetBrains Mono', 'Fira Code', monospace;
    font-size: 12px;
    line-height: 1.7;
    color: var(--text-body);
}
.chart-summary .summary-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 8px 24px;
}
.chart-summary .summary-section {
    border-left: 2px solid var(--border-strong);
    padding-left: 10px;
}
.chart-summary .summary-section-title {
    color: var(--link);
    font-weight: 600;
    margin-bottom: 2px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
/* Finviz-style stat grid (stat_grid.py): label/value rows per group, value
   colored by its rating; the reason is in each row's hover title. */
.chart-summary .stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 10px 22px;
}
.chart-summary .stat-grid-group { min-width: 0; }
.chart-summary .stat-grid-row {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 1px 0;
    border-bottom: 1px solid var(--border);
    cursor: help;
}
.chart-summary .stat-grid-row:hover { background: var(--border); }
/* each row is a button (tap/keyboard reach the reason) - reset to look like the row it was */
.chart-summary button.stat-grid-row {
    width: 100%; background: none; border: none; border-bottom: 1px solid var(--border); border-radius: 0;
    font: inherit; color: inherit; text-align: left; margin: 0;
}
.chart-summary button.stat-grid-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.chart-summary .sg-src { display: none; }
.chart-summary .sg-why { font-family: var(--font-sans); font-size: 12px; color: var(--text-secondary); line-height: 1.5; padding: 4px 0 8px; }

/* Phone: the stat grid as tiles (mobile mockup) - label, value, source stamp; tap for the reason. Colored edge =
   the same good/bad rating the desktop colors the value with. Desktop is unchanged. */
@media (max-width: 800px) {
    .chart-summary { padding: 14px; font-family: var(--font-sans); }
    .chart-summary .stat-grid { display: flex; flex-direction: column; gap: 18px; }
    .chart-summary .summary-section-title {
        font-size: 12px; letter-spacing: 0.8px; color: var(--text-secondary); margin-bottom: 8px;
        padding-bottom: 6px; border-bottom: 1px solid var(--border);
    }
    .chart-summary .sg-items { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
    .chart-summary .sg-item {
        background: var(--bg-card); border: 1px solid var(--border); border-left: 3px solid var(--border);
        border-radius: 8px; min-width: 0; display: flex; flex-direction: column;
    }
    .chart-summary .sg-item[data-rating="good"] { border-left-color: var(--success); }
    .chart-summary .sg-item[data-rating="bad"] { border-left-color: var(--error); }
    .chart-summary button.stat-grid-row {
        display: flex; flex-direction: column; align-items: flex-start; gap: 4px; border: none;
        padding: 10px 12px; min-height: 76px; cursor: pointer;
    }
    .chart-summary button.stat-grid-row:hover { background: none; }
    .chart-summary .sg-label { font-size: 12px; font-weight: 600; white-space: normal; line-height: 1.3; }
    .chart-summary .sg-value { font-family: var(--font-mono); font-size: 18px; font-weight: 700; }
    .chart-summary .sg-src {
        display: block; font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.3px; color: var(--text-muted);
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
    }
    .chart-summary .sg-why { padding: 0 12px 10px; border-top: 1px solid var(--border); padding-top: 8px; }
    .chart-summary .stat-grid-check { font-family: var(--font-sans); font-size: 12px; padding: 8px 10px; margin-top: 8px;
        border-radius: 8px; background: var(--bg-card); border: 1px dashed var(--border); }
}
.chart-summary .sg-label { color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chart-summary .sg-value { color: var(--text-primary); font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.chart-summary .sg-good { color: var(--good-text); }
.chart-summary .sg-bad { color: var(--bad-text); }
.chart-summary .stat-grid-legend { margin-top: 10px; font-size: 11px; color: var(--text-muted); line-height: 1.5; }
.chart-summary .stat-grid-check { margin-top: 4px; font-size: 11px; line-height: 1.5; }
.chart-summary .sg-warn { color: var(--watch-text); }
.chart-summary .val-green { color: var(--good-text); }
.chart-summary .val-red { color: var(--bad-text); }
.chart-summary .val-yellow { color: var(--watch-text); }
.chart-summary .val-cyan { color: var(--cyan-text); }
.chart-summary .val-white { color: var(--text-primary); font-weight: 600; }
.chart-summary .summary-narrative {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
    color: var(--text-secondary);
    font-size: 12px;
    line-height: 1.6;
}

/* ===== Cheapness Q&A Card (Socratic) ===== */
.cheapness-card {
    background: var(--surface-deep);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 16px 20px;
    margin-bottom: 12px;
    font-family: -apple-system, 'Segoe UI', system-ui, sans-serif;
    font-size: 13px;
    color: var(--text-body);
    line-height: 1.5;
}
.qa-headline {
    border-bottom: 1px solid var(--border);
    padding-bottom: 12px;
    margin-bottom: 14px;
}
.qa-headline-question {
    color: var(--text-secondary);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    font-weight: 500;
    margin-bottom: 4px;
}
.qa-headline-answer {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: 0.2px;
}
.headline-yes_strong { color: var(--good-text); }
.headline-yes        { color: var(--cyan-text); }
.headline-mixed      { color: var(--watch-text); }
.headline-no         { color: #fb923c; }
.headline-no_strong  { color: var(--bad-text); }

.qa-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
}
.qa-row {
    border-left: 2px solid var(--border);
    padding-left: 12px;
}
.qa-question {
    color: var(--text-strong);
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 4px;
}
.qa-answer-line {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.qa-answer {
    font-size: 14px;
    font-weight: 700;
}
.qa-answer-yes_strong { color: var(--good-text); }
.qa-answer-yes        { color: var(--cyan-text); }
.qa-answer-mixed      { color: var(--watch-text); }
.qa-answer-no         { color: #fb923c; }
.qa-answer-no_strong  { color: var(--bad-text); }

.qa-steps {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--bg-primary);
    padding: 3px 8px;
    border-radius: 3px;
    border: 1px solid var(--border);
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
}
.qa-step {
    min-width: 16px;
    text-align: center;
    color: var(--border-strong);
    font-weight: 700;
}
.qa-step-dim    { color: var(--border-strong); }
.qa-step-active { transform: scale(1.15); }
.qa-step-yes_strong { color: var(--good-text); }
.qa-step-yes        { color: var(--cyan-text); }
.qa-step-mixed      { color: var(--watch-text); }
.qa-step-no         { color: #fb923c; }
.qa-step-no_strong  { color: var(--bad-text); }

.qa-explanation {
    color: var(--text-secondary);
    font-size: 12px;
    line-height: 1.5;
}
.qa-missing {
    margin-top: 12px;
    color: var(--text-muted);
    font-size: 11px;
    font-style: italic;
}
.qa-context-notes {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.qa-context-note {
    color: var(--text-secondary);
    font-size: 12px;
    line-height: 1.5;
    padding-left: 12px;
    border-left: 2px solid var(--border-strong);
}
.qa-score-footer {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
    color: var(--text-muted);
    font-size: 11px;
    text-align: right;
}
.qa-score-footer b { color: var(--text-body); }

/* ===== Moving Averages Panel ===== */
.ma-card {
    background: var(--surface-deep);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 14px 18px;
    margin-bottom: 12px;
    font-family: 'JetBrains Mono', 'Fira Code', monospace;
    font-size: 12px;
    color: var(--text-body);
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    overflow: hidden;
}
.ma-card * { box-sizing: border-box; }
.ma-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
    flex-wrap: wrap;
    gap: 10px;
}
.ma-panel-title {
    color: var(--link);
    font-weight: 600;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.ma-panel-price { color: var(--text-primary); font-size: 12px; }
.ma-panel-price b { color: var(--watch-text); font-size: 13px; }
.ma-tf-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
    min-width: 0; /* allow grid items to shrink below their content width */
}
.ma-tf-block {
    background: var(--bg-primary);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px 12px;
    min-width: 0;
    overflow-x: auto; /* horizontal scroll if table can't fit even when stacked */
}
.ma-tf-empty {
    background: var(--bg-primary);
    border: 1px dashed var(--border-strong);
    border-radius: 4px;
    padding: 10px 12px;
    color: var(--text-muted);
    font-style: italic;
}
.ma-tf-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 6px;
    flex-wrap: wrap;
    gap: 8px;
}
.ma-tf-name {
    color: var(--text-strong);
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
}
.ma-tf-meta { font-size: 11px; display: flex; gap: 10px; flex-wrap: wrap; }
.ma-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 11px;
    /* Fixed + shared per-column percentages (below) so the Daily/Weekly/
       Monthly tables - three separate <table> elements stacked in
       .ma-tf-grid - line up column-for-column instead of each one
       auto-sizing to its own content. min-width stops a narrow panel from
       squeezing the percentage columns (esp. Value) down to where numeric
       text effectively disappears - .ma-tf-block's overflow-x:auto kicks
       in and scrolls instead once the panel is narrower than this. */
    table-layout: fixed;
    min-width: 560px;
}
.ma-table th:nth-child(1), .ma-table td:nth-child(1) { width: 12%; }
.ma-table th:nth-child(2), .ma-table td:nth-child(2) { width: 14%; }
.ma-table th:nth-child(3), .ma-table td:nth-child(3) { width: 11%; }
.ma-table th:nth-child(4), .ma-table td:nth-child(4) { width: 13%; }
.ma-table th:nth-child(5), .ma-table td:nth-child(5) { width: 11%; }
.ma-table th:nth-child(6), .ma-table td:nth-child(6) { width: 15%; }
.ma-table th:nth-child(7), .ma-table td:nth-child(7) { width: 24%; }
.ma-table th {
    text-align: left;
    color: var(--text-muted);
    font-weight: 500;
    border-bottom: 1px solid var(--border);
    padding: 4px 6px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    font-size: 10px;
    white-space: nowrap;
}
.ma-table td {
    padding: 4px 6px;
    border-bottom: 1px solid var(--bg-secondary);
    white-space: nowrap;
}
.ma-table td:last-child, .ma-table th:last-child {
    white-space: normal; /* let the Signal column wrap if it's the only long one */
}
.ma-table tr:last-child td { border-bottom: none; }
.ma-num { font-variant-numeric: tabular-nums; }
.ma-bull { color: var(--good-text); }
.ma-bear { color: var(--bad-text); }
.ma-warn { color: var(--watch-text); }
.ma-cross-bull { color: var(--good-text); font-weight: 600; }
.ma-cross-bear { color: var(--bad-text); font-weight: 600; }
.ma-evidence { color: var(--text-muted); font-size: 10px; }
.ma-evidence-hot {
    color: var(--good-soft);
    font-weight: 600;
    background: rgba(16, 185, 129, 0.16);
    border-radius: 3px;
    padding: 2px 6px;
}
.conf-strong   { color: var(--good-text); font-weight: 600; }
.conf-moderate { color: var(--cyan-text); }
.conf-weak     { color: var(--text-muted); }
.ma-trans {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 10px;
    font-weight: 600;
}
.trans-bull { background: rgba(16,185,129,0.15); color: var(--good-text); border: 1px solid #10b981; }
.trans-bear { background: rgba(239,68,68,0.15);  color: var(--bad-text); border: 1px solid #ef4444; }
.trans-warn { background: rgba(251,191,36,0.13); color: var(--watch-text); border: 1px solid #fbbf24; }

/* Confluence zones */
.ma-confluence-section { margin-top: 14px; }
.ma-confluence-title {
    color: var(--link);
    font-weight: 600;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 8px;
}
.ma-confluence-empty {
    margin-top: 12px;
    color: var(--text-muted);
    font-style: italic;
    font-size: 11px;
}
.ma-confluence-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 8px;
}
.zone-card {
    background: var(--bg-primary);
    border-left: 3px solid var(--border-strong);
    border-radius: 4px;
    padding: 8px 12px;
    font-size: 11px;
}
.zone-vstrong  { border-left-color: #fbbf24; background: rgba(251,191,36,0.05); }
.zone-strong   { border-left-color: #22d3ee; background: rgba(34,211,238,0.04); }
.zone-moderate { border-left-color: #64748b; }
.zone-card-head {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.zone-strength {
    font-weight: 700;
    font-size: 10px;
    color: var(--watch-text);
    letter-spacing: 0.5px;
}
.zone-role { font-weight: 700; font-size: 11px; }
.zone-range { color: var(--text-primary); font-weight: 600; }
.zone-dist { color: var(--text-muted); font-size: 10px; margin-left: auto; }
.zone-why { color: var(--text-secondary); margin: 4px 0; line-height: 1.4; }
.zone-members {
    margin: 4px 0 0 0;
    padding-left: 16px;
    color: var(--text-body);
    font-size: 10px;
    line-height: 1.5;
}
.zone-members li b { color: var(--link); }

/* Tables stack vertically by default. The parent .chart-viewer-card is capped at
   1000px, so three side-by-side tables (~440px each for 7 columns) cannot fit.
   Each block has overflow-x: auto as a fallback if a row exceeds the column width. */

/* ===== Swing Trade Setup Banner ===== */
.swing-banner {
    background: var(--bg-primary);
    border-left: 4px solid var(--border-strong);
    border-radius: 4px;
    padding: 14px 16px;
    margin-bottom: 14px;
    font-family: -apple-system, 'Segoe UI', system-ui, sans-serif;
    font-size: 13px;
    line-height: 1.5;
}
.swing-long    { border-left-color: #10b981; background: linear-gradient(90deg, rgba(16,185,129,0.08), rgba(16,185,129,0.02)); }
.swing-short   { border-left-color: #ef4444; background: linear-gradient(90deg, rgba(239,68,68,0.08), rgba(239,68,68,0.02)); }
.swing-neutral { border-left-color: #fbbf24; background: linear-gradient(90deg, rgba(251,191,36,0.06), rgba(251,191,36,0.02)); }

.swing-banner-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 8px;
}
.swing-headline {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.swing-bias-pill {
    font-weight: 700;
    font-size: 13px;
    padding: 3px 10px;
    border-radius: 3px;
    letter-spacing: 0.6px;
}
.swing-long  .swing-bias-pill { background: #10b981; color: #0a0e17; }
.swing-short .swing-bias-pill { background: #ef4444; color: #0a0e17; }
.swing-neutral .swing-bias-pill { background: #fbbf24; color: #0a0e17; }

.swing-conviction {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
}
.conviction-high     { color: var(--good-text); }
.conviction-moderate { color: var(--cyan-text); }
.conviction-low      { color: var(--watch-text); }
.conviction-none     { color: var(--text-muted); }
.swing-horizon { color: var(--text-muted); font-size: 11px; }

.swing-bias-badges {
    display: flex;
    gap: 4px;
}
.bias-badge {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 3px;
    border: 1px solid;
    font-weight: 600;
}
.bias-bullish { color: var(--good-text); border-color: #10b981; background: rgba(16,185,129,0.05); }
.bias-bearish { color: var(--bad-text); border-color: #ef4444; background: rgba(239,68,68,0.05); }
.bias-neutral { color: var(--text-secondary); border-color: var(--border-strong); background: rgba(148,163,184,0.05); }

.swing-headline-text {
    color: var(--text-primary);
    font-size: 15px;
    font-weight: 700;
    margin: 4px 0 8px 0;
    letter-spacing: 0.2px;
}
.swing-rationale {
    margin: 0 0 10px 0;
    padding-left: 18px;
    color: var(--text-body);
    font-size: 12px;
    line-height: 1.6;
}
.swing-rationale li { margin-bottom: 2px; }

/* Trade plan grid */
.swing-plan {
    background: rgba(15,23,42,0.7);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px 12px;
    margin: 8px 0;
}
.swing-plan-title {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--link);
    font-weight: 600;
    margin-bottom: 8px;
}
.swing-plan-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 10px;
}
.plan-cell {
    border-left: 2px solid var(--border-strong);
    padding-left: 10px;
}
.plan-stop   { border-left-color: #ef4444; }
.plan-target { border-left-color: #10b981; }
.plan-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-secondary);
    font-weight: 600;
    margin-bottom: 2px;
}
.plan-value {
    font-family: 'JetBrains Mono', monospace;
    font-size: 16px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 2px;
}
.plan-detail {
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.4;
}
.rr-good { color: var(--good-text); }
.rr-ok   { color: var(--watch-text); }
.rr-bad  { color: var(--bad-text); }

/* Position size calculator */
.pos-calc {
    background: rgba(15,23,42,0.7);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px 12px;
    margin: 8px 0;
}
.pos-calc-title {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--link);
    font-weight: 600;
    margin-bottom: 8px;
}
.pos-calc-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}
.pos-calc-row label {
    font-size: 12px;
    color: var(--text-secondary);
    white-space: nowrap;
}
.pos-calc-input {
    background: var(--bg-primary);
    border: 1px solid var(--border-strong);
    border-radius: 4px;
    color: var(--text-primary);
    font-family: 'JetBrains Mono', monospace;
    font-size: 13px;
    padding: 6px 10px;
    width: 140px;
}
.pos-calc-input:focus { outline: none; border-color: #60a5fa; }
.pos-calc-placeholder {
    font-size: 11px;
    color: var(--text-muted);
    font-style: italic;
}
.pos-calc-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 10px;
}
.pos-calc-cell {
    border-left: 2px solid var(--border-strong);
    padding-left: 10px;
}
.pos-calc-stop   { border-left-color: #ef4444; }
.pos-calc-target { border-left-color: #10b981; }
.pos-calc-label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-secondary);
    font-weight: 600;
    margin-bottom: 2px;
}
.pos-calc-value {
    font-family: 'JetBrains Mono', monospace;
    font-size: 16px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 2px;
}
.pos-calc-sub {
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.4;
}

.swing-triggers {
    margin: 8px 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
}
.swing-triggers-label {
    font-size: 11px;
    color: var(--text-secondary);
    font-weight: 600;
}
.swing-trigger-pill {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 3px;
    background: rgba(34,211,238,0.1);
    color: var(--cyan-text);
    border: 1px solid #22d3ee;
}

.swing-warnings {
    margin-top: 10px;
    padding: 8px 12px;
    background: rgba(251,191,36,0.06);
    border-left: 2px solid #fbbf24;
    border-radius: 0 4px 4px 0;
}
.swing-warnings-title {
    font-size: 10px;
    font-weight: 700;
    color: var(--watch-text);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
}
.swing-warnings ul {
    margin: 0;
    padding-left: 18px;
    color: #fde68a;
    font-size: 11px;
    line-height: 1.5;
}

/* Per-zone trade implication line in confluence cards */
.zone-trade-impl {
    margin: 6px 0;
    padding: 6px 8px;
    background: rgba(96,165,250,0.06);
    border-left: 2px solid #60a5fa;
    border-radius: 0 3px 3px 0;
    color: var(--text-body);
    font-size: 11px;
    line-height: 1.5;
    cursor: help;
    display: flex;
    gap: 6px;
    align-items: flex-start;
}
.zone-trade-icon {
    color: var(--link);
    font-weight: 700;
    flex-shrink: 0;
}
.zone-trade-text { flex: 1; }

.chart-panels {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1px;
    background: var(--border);
}

.chart-panel {
    background: var(--bg-primary);
    padding: 8px 12px;
    position: relative;
    overflow: hidden;
}

.chart-panel-price {
    height: 400px;
}

.chart-panel-small {
    height: 250px;
}

.chart-panel-medium {
    height: 290px;
}

/* Daily/Weekly/Monthly TA workspace (dashboard.html, above .chart-panels) */
.ta-workspace {
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    padding: 12px 16px;
    background: var(--surface-deep-2);
}
.ta-workspace-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}
.ta-workspace-header h3 {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
}
.ta-workspace-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}
.chart-timeframe-group {
    display: flex;
    align-items: center;
    gap: 4px;
}
.chart-timeframe-label {
    font-size: 11px;
    color: var(--text-muted);
    margin-right: 2px;
}
.ta-range-btn {
    padding: 3px 9px !important;
    font-size: 11px !important;
}
.ta-range-btn.active {
    background: rgba(59,130,246,0.15) !important;
    border-color: #3b82f6 !important;
    color: var(--link) !important;
}
/* Price vs Fundamentals - price (left axis) against one SEC metric (right axis) */
.pm-panel {
    border-bottom: 1px solid var(--border);
    padding: 12px 16px 10px;
    background: var(--surface-deep-2);
}
.pm-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 8px;
}
.pm-header h3 {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    margin: 0;
}
.pm-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}
.pm-select {
    background: var(--bg-input, var(--bg-secondary));
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 4px 8px;
    font-size: 12px;
    min-width: 200px;
}
.pm-select:focus-visible, .pm-scale-btn:focus-visible, .pm-range-btn:focus-visible {
    outline: 2px solid #60a5fa;
    outline-offset: 1px;
}
.pm-scale-btn, .pm-range-btn {
    padding: 3px 9px !important;
    font-size: 11px !important;
}
.pm-scale-btn.active, .pm-range-btn.active {
    background: rgba(59,130,246,0.15) !important;
    border-color: #3b82f6 !important;
    color: var(--link) !important;
}
.pm-canvas-wrap {
    position: relative;
    height: 520px;
}
@media (max-width: 800px) {
    .pm-canvas-wrap { height: 380px; }
    .pm-select { min-width: 0; width: 100%; }
}
.pm-note {
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-muted);
    line-height: 1.5;
}

.ta-charts-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}
@media (max-width: 900px) {
    .ta-charts-grid { grid-template-columns: 1fr; }
}
.ta-chart-panel {
    background: var(--bg-primary);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 10px;
    height: 260px;
    position: relative;
}
.ta-chart-title {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 4px;
}
.ta-compare-section {
    margin-top: 12px;
    border-top: 1px solid var(--border);
    padding-top: 10px;
}
.ta-compare-section summary {
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    list-style: none;
}
.ta-compare-section summary::-webkit-details-marker { display: none; }
.ta-compare-section summary::before { content: "▸ "; }
.ta-compare-section[open] summary::before { content: "▾ "; }
.ta-compare-controls {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 10px 0;
    flex-wrap: wrap;
}
.ta-compare-input {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text-primary);
    padding: 6px 10px;
    font-size: 12px;
    width: 180px;
}
.ta-compare-status {
    font-size: 11px;
    color: var(--text-muted);
}

.chart-data-badge {
    position: absolute;
    top: 6px;
    right: 8px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(245, 158, 11, 0.15);
    color: var(--warning);
    font-size: 13px;
    line-height: 22px;
    text-align: center;
    cursor: pointer;
    z-index: 15;
    transition: background 0.2s;
}
.chart-data-badge:hover {
    background: rgba(245, 158, 11, 0.35);
}
.chart-data-badge:hover::after {
    content: attr(data-tip);
    position: absolute;
    right: 0;
    top: 28px;
    background: var(--border);
    color: var(--text-primary);
    font-size: 0.72rem;
    padding: 6px 10px;
    border-radius: 6px;
    border: 1px solid var(--border);
    white-space: nowrap;
    box-shadow: 0 4px 12px rgba(0,0,0,0.4);
    pointer-events: none;
    z-index: 20;
}

/* Informational (not warning) badge — used for "what is this / how was it
   calculated" methodology notes, e.g. the forward P/E and P/S reference lines.
   Longer explanatory text, so it wraps instead of the warning badge's nowrap. */
.chart-data-badge-info {
    background: rgba(192, 132, 252, 0.15);
    color: #c084fc;
}
.chart-data-badge-info:hover {
    background: rgba(192, 132, 252, 0.3);
}
.chart-data-badge-info:hover::after {
    white-space: normal;
    width: 260px;
}

/* Surge_Signals diagrams */
.surge-charts-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.surge-charts-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
}

.surge-charts-header h2 {
    font-size: 1rem;
    font-weight: 600;
    flex: 1;
}

.surge-charts-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.surge-status {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.surge-charts-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1px;
    background: var(--border);
}

.surge-chart-frame {
    background: var(--bg-primary);
    position: relative;
}

.surge-chart-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    cursor: pointer;
    user-select: none;
    transition: background 0.15s;
}

.surge-chart-bar:hover {
    background: rgba(148,163,184,0.08);
}

.surge-chevron {
    color: var(--text-muted);
    transition: transform 0.2s;
    flex-shrink: 0;
}

.surge-chart-frame:not(.collapsed) .surge-chevron {
    transform: rotate(90deg);
}

.surge-chart-label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-primary);
    flex: 1;
}

.surge-chart-hint {
    font-size: 0.7rem;
    color: var(--text-muted);
    opacity: 0.6;
}

.surge-chart-hint.warn {
    color: var(--error);
    opacity: 1;
    font-weight: 600;
    font-size: 0.75rem;
}

.surge-chart-frame:not(.collapsed) .surge-chart-hint:not(.warn) {
    display: none;
}

.surge-chart-body {
    overflow: auto;
    max-height: 80vh;
}

.surge-chart-frame.collapsed .surge-chart-body {
    display: none;
}

.surge-iframe {
    width: 100%;
    height: 75vh;
    border: none;
    background: #fff;
}

.surge-chart-frame.loading .surge-chart-label::after {
    content: " — generating...";
    font-weight: 400;
    color: var(--text-muted);
    font-size: 0.7rem;
}

.section-surge.minimized .surge-charts-card {
    display: none;
}

.section-pdf {
    margin-bottom: 48px;
}

.pdf-viewer-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    max-width: 1000px;
}

.pdf-viewer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 20px;
    border-bottom: 1px solid var(--border);
}

.pdf-viewer-header h2 {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
}

.pdf-viewer-controls {
    display: flex;
    gap: 8px;
}

.pdf-viewer-frame {
    width: 100%;
    max-height: 80vh;
    overflow: auto;
    background: #525659;
    padding: 16px 0;
    text-align: center;
}

.pdf-viewer-frame canvas.pdf-page {
    display: block;
    margin: 0 auto 12px auto;
    box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}

.pdf-viewer-frame canvas.pdf-page:last-child {
    margin-bottom: 0;
}

.pdf-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 12px;
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
    font-size: 13px;
    color: var(--text-secondary);
}

/* ---- Report History ---- */
.section-history {
    max-width: 700px;
    margin: 0 auto;
}

.section-title {
    font-size: 18px;
    font-weight: 600;
    margin-bottom: 16px;
    color: var(--text-secondary);
}

.report-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.report-card {
    display: flex;
    align-items: center;
    gap: 16px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 18px;
    transition: border-color 0.15s;
}

.report-card:hover {
    border-color: var(--text-muted);
}

.report-ticker {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 15px;
    letter-spacing: 0.5px;
    min-width: 60px;
}

.report-date {
    font-size: 13px;
    color: var(--text-muted);
    flex: 1;
}

.report-status {
    font-size: 12px;
    font-weight: 500;
    padding: 3px 10px;
    border-radius: 20px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.status-completed {
    background: rgba(16, 185, 129, 0.1);
    color: var(--success);
}

.status-running {
    background: rgba(59, 130, 246, 0.1);
    color: var(--accent);
}

.status-failed {
    background: rgba(239, 68, 68, 0.1);
    color: var(--error);
}

.status-pending {
    background: rgba(100, 116, 139, 0.1);
    color: var(--text-muted);
}

.empty-state {
    text-align: center;
    padding: 40px 20px;
    color: var(--text-muted);
    font-size: 15px;
}

/* ---- Alerts, weekly digest, compare (alerts.html, digest.html, compare.html) ---- */
.notify-page { max-width: 720px; margin: 0 auto; padding: 32px 16px 90px; }
.notify-page h1 { font-size: 26px; font-weight: 700; color: var(--text-primary); margin-bottom: 6px; text-wrap: balance; }
.notify-lede { color: var(--text-secondary); font-size: 15px; line-height: 1.55; margin-bottom: 20px; }
.notify-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 16px 18px; margin-bottom: 14px; }
.notify-card h2 { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-size: 16px; font-weight: 600; color: var(--text-primary); margin-bottom: 8px; }
.notify-card h2 a, .compare-head a { color: var(--text-primary); text-decoration: none; }
.notify-hint { color: var(--text-muted); font-size: 13px; line-height: 1.5; margin: 4px 0; }
.notify-hint a, .notify-events a { color: var(--link); }
.notify-toggles { display: flex; flex-direction: column; gap: 2px; }
.notify-toggle { display: flex; align-items: center; gap: 10px; padding: 9px 0; color: var(--text-body); font-size: 14px; cursor: pointer; }
.notify-toggle input { width: 18px; height: 18px; accent-color: var(--accent); flex: none; }
.notify-day { display: inline-flex; align-items: center; gap: 8px; color: var(--text-body); font-size: 14px; margin: 6px 0; }
.notify-day select, .notify-add input, .compare-form input {
    background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-strong); border-radius: var(--radius);
    padding: 9px 11px; font: inherit; font-size: 14px;
}
.notify-add { display: flex; gap: 8px; margin-top: 10px; }
.notify-add input { flex: 1; min-width: 0; text-transform: uppercase; }
.notify-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.notify-chip { display: inline-flex; align-items: center; gap: 4px; padding: 4px 4px 4px 10px; border-radius: 999px; background: var(--surface-deep);
    border: 1px solid var(--border-strong); color: var(--text-strong); font: 600 13px var(--font-mono); }
.notify-chip button { background: none; border: none; color: var(--text-muted); font-size: 16px; line-height: 1; padding: 2px 6px; cursor: pointer; border-radius: 999px; }
.notify-chip button:hover, .notify-chip button:focus-visible { color: var(--bad-text); }
.notify-status { min-height: 20px; font-size: 13px; color: var(--good-text); margin: 8px 0; }
.notify-status.bad { color: var(--bad-text); }
.notify-events { list-style: none; padding: 0; margin: 0; }
.notify-events li { display: flex; flex-wrap: wrap; gap: 2px 10px; padding: 8px 0; border-top: 1px solid var(--border); color: var(--text-body); font-size: 14px; line-height: 1.45; }
.notify-events li:first-child { border-top: none; }
.notify-when { color: var(--text-muted); font-size: 12px; font-variant-numeric: tabular-nums; min-width: 86px; }
.notify-detail { flex: 1 0 100%; color: var(--text-secondary); font-size: 13px; }
.notify-src, .compare-head .notify-src { color: var(--text-muted); font-size: 10px; letter-spacing: 0.06em; margin-left: auto; align-self: center; }
.notify-chg { font-size: 13px; font-weight: 500; }
.notify-chg.up { color: var(--good-text); }
.notify-chg.down { color: var(--bad-text); }
.notify-scores { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 6px; }
.notify-score { font-size: 13px; color: var(--text-secondary); background: var(--surface-deep); border: 1px solid var(--border); border-radius: var(--radius); padding: 4px 9px; }
.notify-score b { color: var(--text-primary); }
.compare-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 4px; }
.compare-form input { flex: 1 1 120px; min-width: 0; text-transform: uppercase; }
.notify-add input::placeholder, .compare-form input::placeholder { text-transform: none; }
.compare-vs { color: var(--text-muted); font-size: 13px; }
.compare-head { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 8px 0 14px; }
.compare-head > div { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 15px; color: var(--text-body);
    background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 12px 14px; font-variant-numeric: tabular-nums; }
.compare-head a { font: 700 20px var(--font-mono); }
.compare-row { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr); gap: 8px; padding: 7px 0; border-top: 1px solid var(--border);
    font-size: 14px; color: var(--text-body); font-variant-numeric: tabular-nums; }
.compare-row > span:not(:first-child) { text-align: right; }
.compare-row .win { color: var(--good-text); font-weight: 600; }
.compare-cols { border-top: none; padding-top: 0; color: var(--text-muted); font: 600 12px var(--font-mono); }
.compare-lead { margin-left: auto; font: 600 12px var(--font-mono); color: var(--good-text); border: 1px solid currentColor; border-radius: 999px; padding: 1px 9px; }
.compare-lead.even { color: var(--text-muted); }
.compare-why { color: var(--text-muted); font-size: 12px; line-height: 1.4; margin: -2px 0 6px; }
.compare-sub { font-size: 14px; font-weight: 600; color: var(--text-strong); margin: 12px 0 2px; }

/* ---- 30-second brief (stock page and economy Overview) ---- */
.brief-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 10px 0; }
.brief-btn { display: inline-flex; align-items: center; gap: 7px; background: var(--surface-deep); color: var(--text-strong); border: 1px solid var(--border-strong);
    border-radius: 999px; padding: 7px 14px; font: 500 13px var(--font-sans); cursor: pointer; }
.brief-btn:hover, .brief-btn:focus-visible { border-color: var(--accent); }
.brief-btn svg { width: 14px; height: 14px; fill: currentColor; }
.brief-text { flex: 1 0 100%; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 12px 14px;
    color: var(--text-body); font-size: 14px; line-height: 1.6; }
.brief-text[hidden], .brief-bar[hidden] { display: none; }

/* ---- Legal Pages ---- */
.legal-page {
    max-width: 720px;
    margin: 0 auto;
    padding: 40px 24px 80px;
}

.legal-page h1 {
    font-size: 28px;
    font-weight: 700;
    margin-bottom: 6px;
    color: var(--text-primary);
}

.legal-updated {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 32px;
}

.legal-page h2 {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
    margin-top: 28px;
    margin-bottom: 10px;
}

.legal-page p {
    font-size: 14px;
    line-height: 1.7;
    color: var(--text-secondary);
    margin-bottom: 12px;
}

.legal-page ul {
    margin: 0 0 12px 20px;
    font-size: 14px;
    line-height: 1.7;
    color: var(--text-secondary);
}

.legal-page li {
    margin-bottom: 6px;
}

.legal-page strong {
    color: var(--text-primary);
}

/* ---- Utility ---- */
.hidden {
    display: none !important;
}

/* ---- Scrollbar ---- */
::-webkit-scrollbar {
    width: 12px;
}

::-webkit-scrollbar-track {
    background: rgba(255,255,255,0.05);
}

::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.6);
    border-radius: 6px;
    border: 2px solid transparent;
    background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
    background: rgba(255,255,255,0.85);
    border: 2px solid transparent;
    background-clip: padding-box;
}

/* Firefox scrollbar */
* {
    scrollbar-width: auto;
    scrollbar-color: rgba(255,255,255,0.6) rgba(255,255,255,0.05);
}

/* ---- Responsive ---- */
/* Sidebar backdrop: hidden/inert on desktop (sidebar sits inline there, never
   needs a dismiss-by-tapping-outside affordance). On mobile it's toggled to
   "visible" in lockstep with the sidebar itself, sitting between the sidebar
   (z-index 200) and page content so tapping outside the panel closes it -
   the standard off-canvas mobile-nav pattern. */
.sidebar-backdrop {
    display: none;
    position: fixed;
    /* --navbar-height is measured live by base.html (the navbar wraps to a
       taller, variable height once it's wrapping multiple mobile rows, so a
       hardcoded 56px here would sit on top of the wrapped nav instead of
       below it); 56px is only the pre-JS/no-ResizeObserver fallback. */
    inset: var(--navbar-height, 56px) 0 0 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 150;
}

/* Medium desktop/laptop widths (roughly 769-1100px - a non-maximized laptop
   window, or a maximized 1280px+ display at less than 100% zoom): nothing
   below ever handled this range at all (only <=768px and <=600px had
   overrides), so the fixed-width brand area (260px) + full tagline text +
   generous nav-analyze margins simply didn't fit and pushed the hamburger
   menu off the right edge of the viewport with no scrollbar hint that
   anything was cut off - measured at 900px wide: hamburger's left edge at
   x=931, past the 900px-wide viewport entirely. That hamburger is the only
   way to reach Sign Out and Admin, so losing it reads as "no way to
   navigate." This doesn't wrap the layout (still one row, unlike the
   <=768px stacked layout below) - it just reclaims enough width to fit. */
@media (max-width: 1100px) {
    .nav-tagline {
        display: none;
    }

    .nav-macro-link {
        padding-left: 0;
        border-left: none;
    }

    .nav-brand-area {
        width: auto;
        min-width: auto;
        padding: 0 16px;
    }

    .nav-analyze {
        margin: 0 4px;
        gap: 6px;
        max-width: none;
    }

    .btn-nav {
        padding: 7px 12px;
    }
}

/* <=800px: everything through here down to the narrowest phones stacks
   into full-width rows (brand / user menu / ticker row). This used to only
   kick in at <=600px, leaving a real dead zone from 601-~719px (confirmed
   by testing, not assumed: measured overflow at 640px and 680px, zero
   at 600px and 720px) where the layout was neither the wide desktop row
   nor the narrow stacked column - the hamburger menu landed off-screen
   there too, same failure as the >800px gap above. One combined
   breakpoint here removes that gap entirely rather than trying to tune a
   second, separate threshold to close it. The threshold sits at 800, not
   768, for the same reason: with the Macro Dashboard link added to this
   row, shrink-in-place stopped fitting cleanly right above 768 too
   (measured overflow from 769-792px) - rather than re-tune the shrink
   amounts again for whatever gets added next, the guaranteed-safe stacked
   layout now starts early enough to absorb that margin outright. */
@media (max-width: 800px) {
    .nav-container-full {
        flex-wrap: wrap;
        height: auto;
        min-height: 56px;
        gap: 8px;
        padding: 8px 12px;
    }

    /* space-between (not center) so the avatar/Login-SignUp button can sit
       right-justified on the same row as the logo - per explicit request
       to move the user's identity up out of its own separate row.
       flex: 1 1 100% (not just width:auto) is required for that
       right-justification to actually reach the screen edge: this is a
       flex item inside .nav-container-full's flex-wrap row, so without a
       forced 100% basis it only claims as much width as its own content
       (logo + avatar) needs, leaving space-between nothing to distribute
       past the avatar - confirmed live, the avatar was landing ~120px
       short of the real edge on a 390px phone. Same fix .nav-main-area
       already uses below for the same reason. */
    .nav-brand-area {
        flex: 1 1 100%;
        width: 100%;
        min-width: auto;
        border-right: none;
        padding: 0;
        height: auto;
        justify-content: space-between;
    }
    /* Hidden on desktop by default (style.css base rule below) - this row
       only exists <=800px, sharing the logo's row instead of stacking a
       whole separate one just for the user's name/login links. */
    .nav-brand-mobile-actions {
        display: flex;
        align-items: center;
        gap: 10px;
    }
    /* Hidden here (not removed from the DOM - desktop still uses these
       exact elements) since they're now redundant with
       .nav-brand-mobile-actions above. */
    .nav-right > .nav-user, .nav-right > a.nav-link, .nav-right > .hamburger-wrap {
        display: none;
    }

    /* flex: 1 1 100% (not just width: 100%) is deliberate, on both rules
       below: .nav-main-area and .nav-analyze each have a base rule of
       flex:1, which gives a flex-basis of 0% - that wins over a plain
       `width` override in a flex layout. Left as only `width:100%`,
       .nav-main-area still shares its line with the brand logo (both
       fit within 768px, so flex-wrap never triggers a line break) and
       squeezes its own children into whatever's left over, which is
       what actually overflowed. Forcing the basis to 100% on both makes
       each claim its own full-width row in turn. */
    .nav-main-area {
        flex: 1 1 100%;
        flex-wrap: wrap;
        width: 100%;
        padding: 0;
        gap: 8px;
    }

    /* .nav-analyze also needs its own flex-wrap here: it's a flex container
       for the (hidden) tagline, the macro-dashboard link, and the ticker
       input row, and without wrap those last two fought for space exactly
       like nav-main-area/nav-analyze did against nav-brand-area above -
       measured overflowing on both sides at once (nav-analyze centers its
       content via justify-content:center, so an overflow this container
       can't fit pushes equally past the left AND right edges).
       flex-basis 220px (not 100%) - shares its row with .nav-right (same
       order, so they sit side by side - per explicit request to put the
       ticker search box on the same row as the Macro Toggles gear icon,
       reclaiming the row that search used to have to itself) rather than
       each claiming a full-width row of its own; .nav-main-area's own
       flex-wrap still catches the case where a truly narrow phone can't
       fit both, letting them drop to stacked rows automatically instead
       of needing a second hardcoded breakpoint. */
    .nav-analyze {
        flex: 1 1 220px;
        flex-wrap: wrap;
        justify-content: flex-start;
        margin: 0;
        max-width: none;
        min-width: 0;
        order: 3;
    }
    /* Shares .nav-analyze's row (same order, DOM order puts .nav-analyze
       first so the search box sits left of whatever's left in here - on
       the macro dashboard that's just the Macro Toggles gear icon, since
       the user/login/hamburger children right above are hidden on mobile;
       on every other page .nav-right ends up empty here and the search
       box simply takes the full row). flex:0 0 auto - shrink-to-fit,
       leaving .nav-analyze to absorb the remaining width. */
    .nav-right {
        order: 3;
        flex: 0 0 auto;
    }

    .nav-macro-link {
        flex: 1 1 100%;
    }

    /* flex-wrap: once a report is open, Lock Charts / Reset Zoom / Patterns join this row - without wrapping they
       squeezed the ticker box to a ~25px sliver on a 390px phone, too narrow to type in */
    .nav-input-row {
        flex: 1 1 auto;
        min-width: 0;
        flex-wrap: wrap;
        row-gap: 8px;
    }

    /* Desktop fixes this to 150px (freeing space for the world-clock ticker
       next to it there) - here it shares a row with the ticker too, just a
       narrower one, so it stays flex:1 (grow to fill whatever .nav-analyze
       itself is given) rather than the old full-row-width stretch. */
    .nav-ticker-input {
        flex: 1 1 140px;
        width: auto;
        min-width: 140px;
    }

    /* Full-width row of its own (flex-basis 100%, not sharing with
       .nav-analyze) per explicit request to expand it the same way
       .market-ticker-wrap already gets a dedicated full-width row below
       the whole nav - cramming both the ticker-input row AND a real
       32-city clock strip onto one shared mobile row left it too
       squeezed to actually read.

       Per explicit follow-up ("make the time ticker extend to the edge of
       the screen") - the base rule's own margin:0 16px plus this
       container's own 12px side padding (.nav-container-full above) left
       it visibly inset as a rounded pill floating mid-row, not reaching
       either edge. margin:0 -12px cancels out exactly that parent padding
       (bleeding the ticker back out to the true screen edge - this value
       is coupled to .nav-container-full's own 12px, re-check both
       together if either changes); the border-radius/left-right borders
       are dropped too so it reads as a genuine edge-to-edge strip, the
       same visual language .market-ticker-wrap already uses one row
       below. Horizontal padding moves onto the ticker's own box instead
       (the per-city items already carry their own internal padding, this
       is just a little extra breathing room at the true edges). */
    .world-clock-ticker {
        flex: 1 1 100%;
        min-width: 0;
        max-width: none;
        order: 4;
        margin: 0 -12px;
        padding: 6px 10px;
        border-left: none;
        border-right: none;
        border-radius: 0;
    }

    .nav-tagline {
        display: none;
    }

    /* The tagline it normally sits beside is hidden here, so drop the
       divider that implied "beside the tagline" - it'd otherwise read as a
       stray line with nothing to its left. */
    .nav-macro-link {
        padding-left: 0;
        border-left: none;
    }

    .sidebar {
        position: fixed;
        top: var(--navbar-height, 56px);
        left: 0;
        bottom: 0;
        z-index: 200;
        box-shadow: 4px 0 20px rgba(0, 0, 0, 0.4);
    }

    .sidebar.collapsed {
        margin-left: -260px;
    }

    .sidebar-expand {
        top: calc(var(--navbar-height, 56px) + 8px);
    }

    .sidebar-backdrop.visible {
        display: block;
    }

    /* Hamburger menu becomes a right-side sliding drawer here instead of a
       dropdown pinned to the button - the button's own position within the
       wrapped nav rows is no longer guaranteed to sit at the visual right
       edge of the viewport (see .nav-container-full's flex-wrap above), so
       a dropdown anchored purely via `right: 0` on the button's own
       positioning context could - and did - render with its min-width body
       pushed off the LEFT edge of the screen whenever that context wasn't
       actually flush against the viewport's right edge. Anchoring to the
       viewport itself (position: fixed, inset from the true edges) instead
       of the button removes that dependency entirely. */
    .hamburger-menu {
        position: fixed;
        top: var(--navbar-height, 56px);
        right: 0;
        bottom: 0;
        left: auto;
        min-width: 0;
        width: min(78vw, 300px);
        /* Soften the two edges that actually show - the drawer sits flush
           against the right/bottom of the viewport (right:0, bottom:0), so
           only its top-left and bottom-left corners are ever visible;
           rounding those two (not all four) avoids a rounded corner
           floating uselessly against the screen edge on the right side. */
        border-radius: 12px 0 0 12px;
        border-width: 0 0 0 1px;
        /* shadow only while open (below): parked off-screen, it bled a dark band onto the page's right edge */
        box-shadow: none;
        padding: 10px 0;
        overflow-y: auto;
        /* Fully off-screen (not just faded) when closed, sliding in from the
           right - the actual "drawer" motion requested, replacing the
           desktop dropdown's fade above. */
        opacity: 1;
        visibility: visible;
        transform: translateX(100%);
        transition: transform 0.25s ease;
    }

    .hamburger-menu.open {
        transform: translateX(0);
        box-shadow: -6px 0 24px rgba(0,0,0,0.4);
    }

    .hamburger-backdrop {
        display: block;
        position: fixed;
        inset: var(--navbar-height, 56px) 0 0 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 999;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.25s ease;
    }

    .hamburger-backdrop.visible {
        opacity: 1;
        pointer-events: auto;
    }

    /* iOS Safari force-zooms the whole page in whenever a focused text
       input/select/textarea computes to under 16px font-size - a jarring
       "why did the page just jump" moment the user didn't ask for, on
       every filter field and search box site-wide (several compute as low
       as 11-13px today: .sidebar-filter-input, .ta-compare-input, etc.).
       !important is deliberate here, matching the [hidden] reset above -
       this needs to beat every one of those per-component class rules
       unconditionally, and there's no legitimate reason for a text field
       to render under 16px on a phone regardless of what desktop wants.
       Scoped to real text-entry types only - checkboxes/radios/color
       swatches don't trigger this and don't need it. */
    input[type="text"], input[type="email"], input[type="password"],
    input[type="search"], input[type="number"], input[type="tel"],
    input[type="date"], input:not([type]), select, textarea {
        font-size: 16px !important;
    }

    /* .hamburger-wrap itself is hidden on mobile now (see the
       .nav-right > .hamburger-wrap rule above) - the avatar button is the
       mobile trigger instead, and inherits this same reasoning: 32px is well
       under Apple's (44pt) / Google's (48dp) minimum tappable target, and
       this is the ONE way to reach every other page from the macro
       dashboard's mobile view (the old always-visible sidebar drawer was
       removed earlier this session) - the single most-tapped control on
       the whole mobile experience is exactly the wrong place to be
       undersized. */
    .nav-avatar-btn {
        width: 44px;
        height: 44px;
    }
    .nav-avatar-initials {
        font-size: 0.8rem;
    }

    /* The 16px floor above (needed to stop iOS's auto-zoom) makes these
       filter fields noticeably taller/bulkier on mobile than their 11px
       desktop footprint - per explicit request, tighten the padding back
       down to compensate so the box stays compact without shrinking the
       text itself (which must stay >=16px - that's not negotiable, see
       the rule above). Net result is a smaller field that's still easy to
       read and tap, rather than trading one for the other. */
    .sidebar-filter-input, .sidebar-filter-select {
        padding: 3px 6px;
    }

    /* .admin-table is the site's one generic data-table class - reused
       verbatim (not a bespoke macro/admin-only style) by the Macro
       Dashboard's own tables (Full/Earnings Calendar, CPI/PPI breakdowns,
       sector/country/business-cycle tables, etc.), the Admin panel, 13F
       Filings, and Politician Trades. Every one of these is already
       wrapped in its own overflow-x:auto container, so a wide table never
       breaks the page layout - but at the DESKTOP 13px/11px font and
       8-12px padding, most of them still need real horizontal scrolling
       to see every column on a phone. Per explicit request ("shrink the
       font... maximize content on screen without too much scrolling
       right"), this shrinks the whole table down and - the bigger win -
       lets header text WRAP instead of forcing every column at least as
       wide as its (often much longer than the data underneath it) header
       label, e.g. "Consensus (Forecast)" or "Change vs. prior version"
       otherwise force a column far wider than any real value in it. */
    .admin-table {
        font-size: 11.5px;
    }
    .admin-table th {
        padding: 5px 6px;
        font-size: 9.5px;
        white-space: normal;
    }
    .admin-table td {
        padding: 5px 6px;
    }

    /* Feed-style scroll-hide chrome - .navbar slides off-screen on
       scroll-down, reappears on scroll-up, so content gets the full
       viewport while reading. transform (not display/height/top) is
       deliberate: .navbar keeps its real position:sticky layout box and
       offsetHeight while hidden, so the ResizeObserver that publishes
       --navbar-height (base.html) never misfires - every fixed-position
       element keyed off that variable (the mobile sidebar drawer,
       .hamburger-menu, macro's own #macro-tabs-mobile/
       #global-chart-controls-card) keeps working unmodified.
       .market-ticker-wrap is already a child of <nav class="navbar">
       (base.html), so it hides for free with this one transform - no
       separate rule needed. chrome-can-hide is only ever added by JS at
       <=800px, so desktop is provably unaffected by this rule's mere
       presence.

       The actual moment-to-moment slide is driven by base.html's scroll
       IIFE writing `transform: translateY(-Npx)` directly as an inline
       style every frame (1:1 with the scroll delta, no transition, so it
       moves at exactly the swipe's own speed rather than a fixed-duration
       animation) - that inline style always wins over this class rule's
       `transform`, so `body.chrome-hidden .navbar` below only ever
       matters as a fallback for the brief window before JS has run a
       single scroll frame (or if JS fails entirely) - a fully-collapsed
       rest state, not the transition itself. */
    body.chrome-can-hide .navbar {
        will-change: transform;
    }
    body.chrome-hidden .navbar {
        transform: translateY(-100%);
    }
}

/* ---- Shared mobile "sliding tabs" strip ----
   Rendered by _macro_nav.html's tab_strip() macro, imported by
   macro_dashboard.html, thirteenf.html, and politician_trades.html - one
   shared component, so it needs to live here (site-wide) rather than
   inside any one page's own <style> block. On the macro dashboard itself
   this doubles as the base styling for the desktop sidebar's vertical tab
   list (.sidebar .macro-tabs); on the other two pages only the mobile
   horizontal strip variant ever renders. */
.macro-tab-btn { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; text-align: left; background: none; border: none; border-bottom: 1px solid var(--border); color: var(--text-secondary); padding: 10px 16px; font-size: 0.85rem; cursor: pointer; border-left: 3px solid transparent; }
.macro-tab-btn:hover { color: var(--text-primary); background: var(--bg-card); }
/* |z|>=2/3 count badges (renderSidebarZscoreCounts, macro_dashboard.html
   only - always empty on thirteenf.html/politician_trades.html, which
   never populate it) - a filled dot per severity, colored the same
   red/amber used everywhere else for that exact threshold. */
.macro-tab-zcounts { font-size: 0.72rem; font-weight: 700; white-space: nowrap; display: flex; gap: 6px; flex-shrink: 0; }
/* A left accent bar plus filled background makes "which section am I on"
   readable at a glance down the desktop drawer's stacked list. */
.macro-tab-btn.active { color: var(--accent); border-left-color: var(--accent); background: rgba(148,163,184,0.14); font-weight: 600; }
/* Topical section headers in the desktop sidebar's vertical tab list only
   (macro_dashboard.html's own sidebar loop inserts these directly in
   _macro_nav.html's macro_tabs order - see that file's comment on why
   grouping is topical, not leading/lagging). tab_strip()'s mobile
   horizontal strip and the 13F/Politician cross-links never render this
   class at all, so no media-query hiding is needed - it simply doesn't
   exist there. */
.macro-tab-group-label {
    padding: 14px 16px 4px; font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.6px; color: var(--text-muted);
}
.macro-tab-group-label:first-child { padding-top: 6px; }

@media (max-width: 800px) {
    /* Horizontal, always-visible tab strip. No max-height/overflow-y (that
       would be a vertical-dropdown shape) - this scrolls horizontally
       instead, one row, no wrapping. -webkit-overflow-scrolling:touch
       gives it real momentum scrolling on iOS; the scrollbar itself is
       hidden (still fully scrollable via touch/trackpad/arrow keys) since
       a visible horizontal scrollbar under a row of tabs reads as visual
       clutter on a phone. mask-image fades both edges to transparent so a
       tab visibly "cut off" mid-fade signals there's more to scroll to,
       the same way a native iOS segmented control or a carousel does.

       position:sticky keeps it pinned just under the navbar (or at the
       very top once the navbar itself has slid away, see
       body.chrome-hidden below) so scrolling back up brings the tabs back
       regardless of how far down the page you'd scrolled - plain in-flow
       positioning would only restore it once you reached the literal top
       of the page, since un-hiding an element's opacity does nothing for
       one that isn't currently in the viewport at all. z-index sits below
       the real navbar (100) so the navbar always wins if both are ever
       visible at once mid-transition. */
    #macro-tabs-mobile {
        display: flex; flex-direction: row; flex-wrap: nowrap;
        gap: 8px; margin-bottom: 10px; padding: 8px 6px 12px;
        overflow-x: auto; -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        background: var(--bg-secondary);
        position: sticky; top: var(--navbar-height, 56px); z-index: 90;
        -webkit-mask-image: linear-gradient(to right, transparent 0, black 20px, black calc(100% - 20px), transparent 100%);
        mask-image: linear-gradient(to right, transparent 0, black 20px, black calc(100% - 20px), transparent 100%);
    }
    #macro-tabs-mobile::-webkit-scrollbar { display: none; }
    #macro-tabs-mobile.macro-tabs-pages { flex-wrap: wrap; overflow: visible; -webkit-mask-image: none; mask-image: none; }
    /* Text-only tabs, no chip/pill background - per explicit follow-up
       (tried flat underline, then a dark "folder tab" fill, then rounded
       pill chips; all rejected in turn - this pass drops any background/
       border entirely, active state is purely a text-color/weight change).
       Padding is still generous (kept from the "make them thicker" pass)
       for a comfortable touch target even with no visible box around it.
       flex:0 0 auto + white-space:nowrap stop labels from wrapping/
       shrinking, which would otherwise fight the horizontal scroll;
       width:auto overrides the desktop sidebar rule's own width:100%
       above (that's for a vertical list where each row should span the
       sidebar - without this override, flex:0 0 auto's basis falls back
       to that inherited 100% and every tab gets forced to the full row
       width regardless of padding/font). */
    #macro-tabs-mobile .macro-tab-btn {
        width: auto; flex: 0 0 auto; white-space: nowrap;
        background: none; border: none; gap: 5px;
        padding: 9px 10px;
        font-size: 0.8rem; color: var(--text-muted);
    }
    /* Active state is a soft background tint keyed to the tab's own TOPIC
       GROUP (data-group, set by _macro_nav.html's tab_strip macro from its
       group_slugs map) rather than a flat blue text color - per explicit
       follow-up: swiping between tabs previously turned every destination
       tab's label the same accent blue regardless of which one it was, so
       there was no visual distinction between e.g. landing on "Overview"
       vs. "Commodities" beyond the label text itself. A low-opacity tint
       (same "soft background, not a loud solid fill" convention as
       .tab-stretch-summary above) keyed by group instead means the active
       tab visually "belongs" to its own section as you swipe through them.
       Text stays var(--text-primary) (not colored per-group) so the tint
       alone carries the identity and legibility never depends on a
       low-contrast color-on-color pairing; the red/amber severity dots
       still read fine against any of these tints since none of them are
       full-strength fills. Falls back to a neutral slate tint if a group
       is ever added to macro_tabs without a matching slug. */
    #macro-tabs-mobile .macro-tab-btn.active {
        color: var(--text-primary); font-weight: 700;
        background: rgba(148,163,184,0.22); border-radius: 6px;
    }
    #macro-tabs-mobile .macro-tab-btn.active[data-group="overview"] { background: rgba(59,130,246,0.22); }
    #macro-tabs-mobile .macro-tab-btn.active[data-group="cycle"] { background: rgba(167,139,250,0.22); }
    #macro-tabs-mobile .macro-tab-btn.active[data-group="growth"] { background: rgba(52,211,153,0.22); }
    #macro-tabs-mobile .macro-tab-btn.active[data-group="gov"] { background: rgba(251,191,36,0.22); }
    #macro-tabs-mobile .macro-tab-btn.active[data-group="markets"] { background: rgba(56,189,248,0.22); }
    #macro-tabs-mobile .macro-tab-btn.active[data-group="realeconomy"] { background: rgba(251,146,60,0.22); }
    /* The trailing link-tabs (13F Filings/Politician Trades, or every
       macro tab when this strip renders on one of THOSE pages instead)
       navigate away/elsewhere entirely rather than switching a panel - a
       dashed underline marks that distinction at a glance without a
       background/border box, consistent with the plain-text look above. */
    #macro-tabs-mobile .macro-tab-link {
        color: var(--text-muted); text-decoration: none;
        border-bottom: 1px dashed var(--border);
    }
    /* Feed-style scroll-hide chrome - fades with the header on
       scroll-down, reappears on scroll-up, and collapses its sticky
       offset to 0 while the navbar itself is hidden so it takes over the
       navbar's old spot at the very top of the viewport instead of
       leaving a blank gap above it. As with .navbar above, the actual
       per-frame `top`/`opacity`/`transform` values are written as inline
       styles by base.html's scroll IIFE (tracking the navbar's own
       collapse 1:1, no transition, so both pieces of chrome move as one
       unit at the swipe's own speed) - `body.chrome-hidden` below is only
       the rest-state fallback for before that JS has run its first frame.
       prefers-reduced-motion is handled inside that same JS (a 0ms settle
       duration), not with a separate override rule here, since there's no
       longer a CSS transition to disable. */
    body.chrome-hidden #macro-tabs-mobile {
        top: 0; transform: translateY(-6px); opacity: 0; pointer-events: none;
    }
}
/* Belt-and-suspenders: never show the mobile-only strip on desktop even
   mid-transition. The sliding-tabs strip is a mobile pattern (the whole
   point is a horizontal-scroll affordance for a cramped phone screen,
   meaningless on a wide desktop viewport where everything fits anyway) -
   on the macro dashboard itself, desktop's real section nav lives in
   #macro-sidebar; on thirteenf.html/politician_trades.html, desktop keeps
   the plain "Back to Macro Dashboard" text link this strip replaces only
   on mobile (see .macro-back-link's own <=800px hide rule in those two
   pages' own <style> blocks) - removing it outright with no desktop
   replacement would have been a real regression. */
@media (min-width: 801px) {
    #macro-tabs-mobile { display: none !important; }
}

@media (max-width: 600px) {
    .main-content {
        padding: 0 16px;
    }

    .auth-card {
        padding: 28px 20px;
    }
}

/* ---- Admin Dashboard ---- */
.admin-page {
    max-width: 1200px;
    margin: 0 auto;
    padding: 24px;
}

.admin-summary {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 24px;
}

.admin-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 20px;
    text-align: center;
}

.admin-card-number {
    font-size: 28px;
    font-weight: 700;
    color: var(--text-primary);
}

.admin-card-label {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 4px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.admin-tabs {
    display: flex;
    gap: 0;
    border-bottom: 1px solid var(--border);
    margin-bottom: 16px;
}

.admin-tab {
    background: none;
    border: none;
    padding: 10px 24px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    transition: color 0.15s, border-color 0.15s;
}

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

.admin-tab.active {
    color: var(--text-primary);
    border-bottom-color: var(--blue);
}

.admin-tab-content {
    display: none;
}

.admin-tab-content.active {
    display: block;
}

.admin-table-wrap {
    overflow-x: auto;
}

.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.admin-table th {
    text-align: left;
    padding: 8px 12px;
    color: var(--text-muted);
    font-weight: 600;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

.admin-table td {
    padding: 10px 12px;
    border-bottom: 1px solid rgba(148,163,184,0.06);
    color: var(--text-primary);
    vertical-align: middle;
}

.admin-table tbody tr:hover {
    background: rgba(148,163,184,0.04);
}

.admin-email {
    font-family: monospace;
    font-size: 12px;
}

.admin-actions {
    white-space: nowrap;
    display: flex;
    gap: 4px;
}

.badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
}

.badge-green { background: rgba(34,197,94,0.15); color: #22c55e; }
.badge-red { background: rgba(239,68,68,0.15); color: var(--bad-text); }
.badge-blue { background: rgba(59,130,246,0.15); color: #3b82f6; }
.badge-grey { background: rgba(148,163,184,0.12); color: var(--text-secondary); }
.badge-yellow { background: rgba(251,191,36,0.15); color: var(--watch-text); }
.admin-card-number.val-yellow { color: var(--watch-text); }

.btn-admin {
    background: rgba(148,163,184,0.1);
    border: 1px solid var(--border);
    color: var(--text-secondary);
    padding: 4px 10px;
    border-radius: 4px;
    font-size: 11px;
    cursor: pointer;
    transition: background 0.15s;
}

.btn-admin:hover {
    background: rgba(148,163,184,0.2);
    color: var(--text-primary);
}

.btn-admin-danger {
    color: var(--red);
    border-color: rgba(239,68,68,0.3);
}

.btn-admin-danger:hover {
    background: rgba(239,68,68,0.1);
}

@media (max-width: 768px) {
    .admin-summary {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* ---------------------------------------------------------------------
   Claude streaming status/animation - shared by every billed Claude-API
   button sitewide (Ask Claude on the macro dashboard; Thesis Check and
   Budget Recommendation on a ticker's results page), driven by
   web/static/js/claude-stream.js. Per explicit request: "similar to
   what Claude does when I put a prompt in... something to let the user
   know it is working and what it is doing" - a real-time status line
   (Claude is thinking / searching the web / writing the response, each
   only shown while genuinely true, from macro_dashboard.py's
   stream_claude_api) plus a bouncing-dots indicator while nothing has
   started streaming yet, plus a blinking cursor at the end of the
   answer text while it's still arriving.
   --------------------------------------------------------------------- */
.claude-stream-status {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text-secondary);
    font-size: 0.85rem;
    margin-bottom: 8px;
}

.claude-stream-dots {
    display: inline-flex;
    gap: 3px;
}

.claude-stream-dots span {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent, #6366f1);
    animation: claude-stream-bounce 1.1s infinite ease-in-out both;
}

.claude-stream-dots span:nth-child(1) { animation-delay: -0.28s; }
.claude-stream-dots span:nth-child(2) { animation-delay: -0.14s; }
.claude-stream-dots span:nth-child(3) { animation-delay: 0s; }

@keyframes claude-stream-bounce {
    0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
    40% { transform: scale(1); opacity: 1; }
}

.claude-stream-cursor {
    display: inline-block;
    width: 2px;
    height: 1em;
    margin-left: 1px;
    vertical-align: text-bottom;
    background: var(--accent, #6366f1);
    animation: claude-stream-blink 0.9s steps(1) infinite;
}

@keyframes claude-stream-blink {
    0%, 50% { opacity: 1; }
    50.01%, 100% { opacity: 0; }
}

.claude-stream-error {
    color: var(--error, var(--bad-text));
}

/* Respect a reduced-motion preference - both animations degrade to a
   steady, non-flashing indicator (a plain visible dot / a solid cursor)
   rather than removing the status feedback entirely. */
@media (prefers-reduced-motion: reduce) {
    .claude-stream-dots span {
        animation: none;
        opacity: 0.8;
    }
    .claude-stream-cursor {
        animation: none;
        opacity: 0.8;
    }
    /* The scroll-hide chrome's own reduced-motion handling (a 0ms settle
       duration) lives in base.html's scroll IIFE, not here - there's no
       longer a CSS transition on .navbar/#macro-tabs-mobile to disable,
       see the comment above body.chrome-can-hide .navbar. */
}

/* Phone bottom bar (base.html .mobile-tabbar) - hidden on desktop */
.mobile-tabbar { display: none; }
@media (max-width: 800px) {
    .mobile-tabbar {
        display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
        background: var(--bg-secondary); border-top: 1px solid var(--border);
        padding: 4px 6px calc(6px + env(safe-area-inset-bottom));
    }
    .mobile-tab {
        display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
        min-height: 50px; font: 600 11.5px var(--font-sans); color: var(--text-secondary);
        background: none; border: none; text-decoration: none; cursor: pointer;
    }
    .mobile-tab svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2;
        stroke-linecap: round; stroke-linejoin: round; }
    .mobile-tab.active { color: var(--accent); font-weight: 700; }
    .mobile-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
    /* room so the bar never covers the end of a page */
    body { padding-bottom: calc(64px + env(safe-area-inset-bottom)); }
}

/* Theme switch (base.html [data-theme-toggle]) - sun shown in dark (switch to light), moon in light */
.theme-toggle {
    width: 36px; height: 36px; border-radius: 18px; display: inline-flex; align-items: center; justify-content: center;
    background: var(--bg-card); border: 1px solid var(--border); color: var(--text-primary); cursor: pointer; padding: 0;
}
.theme-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.theme-toggle .theme-icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .theme-icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .theme-icon-moon { display: block; }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* two logo files: white + gold for the dark theme, navy + gold for the light theme */
.brand-logo-on-light { display: none; }
:root[data-theme="light"] .brand-logo-on-dark { display: none; }
:root[data-theme="light"] .brand-logo-on-light { display: inline; }

/* Phone report tabs (dashboard.html) - underline style like the mockup; desktop hides the bar and shows every part */
.report-tabs { display: none; }
@media (max-width: 800px) {
    .report-tabs {
        display: flex; position: sticky; top: 0; z-index: 20; background: var(--bg-secondary);
        border-bottom: 1px solid var(--border); margin: 0 -12px 12px; padding: 0 8px;
    }
    .report-tab {
        flex: 1 1 0; min-height: 46px; background: none; border: none; margin-bottom: -1px;
        border-bottom: 3px solid transparent; color: var(--text-secondary); font: 600 14px var(--font-sans); cursor: pointer;
    }
    .report-tab[aria-selected="true"] { color: var(--text-primary); font-weight: 700; border-bottom-color: var(--accent); }
    .report-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
    #chart-viewer-section[data-report-tab="summary"] [data-report-group]:not([data-report-group="summary"]),
    #chart-viewer-section[data-report-tab="trend"] [data-report-group]:not([data-report-group="trend"]),
    #chart-viewer-section[data-report-tab="charts"] [data-report-group]:not([data-report-group="charts"]) { display: none !important; }
}

/* Evidence balance in "Is this stock cheap?" (phone only - desktop unchanged) */
.qa-balance { display: none; }
@media (max-width: 800px) {
    .chart-viewer-card { overflow: visible; display: flex; flex-direction: column; }   /* visible: lets the tab bar stick */
    /* question first (mockup): the cheapness card above the stat tiles; the other parts keep their order after them */
    #cheapness-verdict { order: 1; }
    #chart-summary { order: 2; }
    #ma-panel, .ta-workspace, #pm-panel, .chart-panels { order: 3; }
    .qa-balance { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 14px; }
    .qa-balance-labels { display: flex; justify-content: space-between; font-size: 12px; font-weight: 600; color: var(--text-secondary); }
    .qa-balance-labels b { font-family: var(--font-mono); }
    .qa-cheap { color: var(--good-text); }
    .qa-dear { color: var(--bad-text); }
    .qa-balance-bar { display: flex; gap: 2px; height: 10px; border-radius: 3px; overflow: hidden; background: var(--border); }
    .qa-balance-bar span { display: block; }
    .qa-seg-cheap { background: var(--success); }
    .qa-seg-mixed { background: var(--border-strong); }
    .qa-seg-dear { background: var(--error); }
}

@media (max-width: 800px) {
    /* the slide-out drawers end above the phone bottom bar, so their last items aren't hidden behind it */
    .sidebar { padding-bottom: calc(72px + env(safe-area-inset-bottom)); }
}

/* ---- Section pill on the stand-alone pages (_macro_nav.html section_pill) ----
   The same floating pill as the dashboard's #macro-sidebar-expand, opening a full-height list of every topic. */
.sp-pill {
    position: fixed; right: 12px; bottom: calc(70px + env(safe-area-inset-bottom)); z-index: 250;
    display: inline-flex; align-items: center; gap: 4px; min-height: 44px; max-width: 64vw; padding: 10px 14px 10px 10px;
    border: 1px solid var(--border-strong); border-radius: 999px; background: var(--bg-card); color: var(--text-primary);
    box-shadow: 0 2px 10px rgba(0,0,0,0.35); cursor: pointer; font-family: inherit;
}
.sp-pill-label { font-size: 0.78rem; font-weight: 600; max-width: 48vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sp-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 299; opacity: 0; pointer-events: none; transition: opacity 0.2s ease; }
.sp-backdrop.visible { opacity: 1; pointer-events: auto; }
.sp-sheet {
    position: fixed; top: 0; bottom: 0; right: 0; z-index: 300; width: min(100vw, 420px); display: flex; flex-direction: column;
    background: var(--bg-primary); border-left: 1px solid var(--border); box-shadow: -6px 0 24px rgba(0,0,0,0.4);
}
.sp-sheet[hidden] { display: none; }
body.sp-open { overflow: hidden; }
.sp-head { display: flex; align-items: center; gap: 12px; padding: 14px 16px 6px; }
.sp-close { width: 44px; height: 44px; border-radius: 22px; flex: none; background: var(--bg-card); border: 1px solid var(--border);
    color: var(--text-primary); display: flex; align-items: center; justify-content: center; cursor: pointer; }
.sp-title { font-size: 20px; font-weight: 800; letter-spacing: -0.3px; color: var(--text-primary); }
.sp-body { flex: 1; overflow-y: auto; padding: 4px 0 calc(24px + env(safe-area-inset-bottom)); }
.sp-group { display: flex; flex-direction: column; gap: 6px; padding: 8px 16px; }
.sp-group-label { padding: 6px 0 0; font-size: 13px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-secondary); }
.sp-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.sp-row { display: grid; grid-template-columns: minmax(0, 1fr) 16px; grid-template-areas: "name chev" "line chev"; column-gap: 12px; row-gap: 2px; align-items: center;
    min-height: 48px; padding: 10px 14px; border-top: 1px solid var(--border); color: var(--text-primary); text-decoration: none; }
.sp-card > .sp-row:first-child { border-top: none; }
.sp-row:hover { background: rgba(148,163,184,0.08); }
.sp-row-name { grid-area: name; font-size: 15px; font-weight: 700; }
.sp-row-line { grid-area: line; font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--text-secondary); }
.sp-chev { grid-area: chev; color: var(--text-muted); }
.sp-current { background: rgba(59,130,246,0.10); }
@media (min-width: 801px) {
    .sp-pill { bottom: 20px; right: 20px; }
}
