/* ── Reset & root ────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Default = dark. Light theme overrides below via [data-theme="light"]. */
:root,
[data-theme="dark"] {
  --bg:        #0b0f1a;
  --surface:   #111827;
  --surface2:  #1f2937;
  --surface3:  #28344a;
  --border:    #2d3748;
  --text:      #e2e8f0;
  --muted:     #8898aa;
  --accent:    #3b82f6;
  --accent2:   #1d4ed8;
  --green:     #22c55e;
  --green-bg:  rgba(34,197,94,0.12);
  --yellow:    #eab308;
  --yellow-bg: rgba(234,179,8,0.12);
  --orange:    #f97316;
  --orange-bg: rgba(249,115,22,0.12);
  --red:       #ef4444;
  --red-bg:    rgba(239,68,68,0.12);
  /* Candle colours — kept separate from --green/--red so the colour-blind
     palette can re-map them independently (the chart uses these via
     inline style: var(--candle-up) / var(--candle-down)). */
  --candle-up:   #22c55e;
  --candle-down: #ef4444;
}

[data-theme="light"] {
  --bg:        #f3f4f6;
  --surface:   #ffffff;
  --surface2:  #f9fafb;
  --surface3:  #e5e7eb;
  --border:    #d1d5db;
  --text:      #111827;
  --muted:     #6b7280;
  --accent:    #2563eb;
  --accent2:   #1e40af;
  --green:     #15803d;
  --green-bg:  rgba(34,197,94,0.16);
  --yellow:    #a16207;
  --yellow-bg: rgba(234,179,8,0.18);
  --orange:    #c2410c;
  --orange-bg: rgba(249,115,22,0.15);
  --red:       #b91c1c;
  --red-bg:    rgba(239,68,68,0.14);
}

html, body { height: 100%; }

body {
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text);
  overflow: hidden;
  font-size: 14px;
}

#root {
  display: flex;
  flex-direction: column;
  /* 100vh on mobile browsers is the LARGE viewport (URL bar hidden), so it's
     taller than what's actually visible while the browser's dynamic toolbar
     is shown — which pushed the fixed bottom-nav clearance off and let page
     content slip under the nav in mobile web (the Capacitor app has no
     toolbar, so 100vh was fine there). 100dvh tracks the real visible
     height; the 100vh line stays as a fallback for browsers without dvh. */
  height: 100vh;
  height: 100dvh;
}

/* ── Header ──────────────────────────────────── */
header {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  /* Reserve the iOS status-bar inset on top (0 on devices without a notch).
     Keeps the logo/clock/hamburger clear of the status bar under
     viewport-fit=cover. The 52px stays the content height; the inset is
     added above it. */
  padding: env(safe-area-inset-top, 0) 24px 0;
  height: 52px;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
  z-index: 100;
  /* Anchor for the mobile dropdown menu - `.header-menu` is
     position: absolute and positions itself relative to this element
     via `top: 100%`, so it always opens just below the header even
     when a trial banner pushes the header down the page. */
  position: relative;
}

.logo {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.4px;
  display: flex;
  align-items: center;
  gap: 9px;
  user-select: none;
  /* `.logo` itself is sometimes wrapped in a button; reset any default. */
  background: none;
  border: none;
  padding: 0;
}
/* The brand mark - sized small for the header, scales up cleanly thanks
   to being a vector. Drop shadow gives the candle silhouettes a tiny
   sense of depth on light backgrounds. */
.logo-mark {
  width:  38px;
  height: 38px;
  flex-shrink: 0;
  object-fit: contain;
  display: block;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.35));
}
/* If logo-mark.png hasn't been added yet, hide the broken-image icon
   so the wordmark still looks intentional. */
.logo-mark:not([src]),
.logo-mark[src=""] { display: none; }
.logo-text   {
  display: inline-flex;
  align-items: baseline;
  font-family: 'Segoe UI', 'SF Pro Display', system-ui, sans-serif;
  letter-spacing: 0.4px;
}
.logo-swing  {
  color: var(--text);
  font-weight: 700;
  text-transform: uppercase;
}
/* Gradient fill the "Mentalist" half to mirror the SVG mark's blue→green ring */
.logo-rest   {
  font-weight: 700;
  text-transform: uppercase;
  margin-left: 4px;
  background: linear-gradient(90deg, #3b82f6 0%, #22d3ee 50%, #84cc16 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
}
.logo-icon   { display: none; }   /* legacy emoji span kept hidden in case anything still emits it */

.header-tag {
  font-size: 10px;
  font-weight: 600;
  background: var(--green-bg);
  color: var(--green);
  border: 1px solid rgba(34,197,94,0.25);
  padding: 2px 7px;
  border-radius: 20px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}

/* Hide the market-regime badge ("BULLISH / NEUTRAL / BEARISH" pill that
   appears in the header after a scan completes) on phones — the header
   already has logo + brand + Pro pill + clock + hamburger competing for
   horizontal space, and the regime info is also surfaced in the scan
   results view, so dropping it on phones costs nothing. */
@media (max-width: 900px) {
  .regime-badge { display: none; }
}

.regime-badge {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 20px;
  letter-spacing: 0.4px;
  font-variant-numeric: tabular-nums;
}
.regime-bullish {
  background: var(--green-bg);
  color: var(--green);
  border: 1px solid rgba(34,197,94,0.4);
}
.regime-neutral {
  background: var(--yellow-bg);
  color: var(--yellow);
  border: 1px solid rgba(234,179,8,0.4);
}
.regime-bearish {
  background: var(--red-bg);
  color: var(--red);
  border: 1px solid rgba(239,68,68,0.4);
}

/* ── Market clock ─────────────────────────────────────────── */
.market-clock {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: rgba(0,0,0,0.18);
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
}
[data-theme="light"] .market-clock {
  background: rgba(0,0,0,0.04);
}
.market-clock .clock-icon {
  font-size: 13px;
  opacity: 0.85;
}
.market-clock .clock-time {
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-weight: 700;
  letter-spacing: 0.5px;
  font-size: 13px;
}
.market-clock .clock-tz {
  margin-left: 4px;
  font-size: 9px;
  opacity: 0.6;
  font-weight: 600;
  vertical-align: 2px;
  letter-spacing: 0.5px;
}
.market-clock .clock-sep {
  width: 1px;
  height: 14px;
  background: var(--border);
}
.market-clock .clock-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.market-clock .clock-status {
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0.2px;
}
.market-clock .clock-status strong {
  font-weight: 700;
  color: var(--text);
  margin-left: 2px;
}

.market-clock.mkt-open {
  border-color: rgba(34,197,94,0.45);
  background: var(--green-bg);
}
.market-clock.mkt-open .clock-dot {
  background: var(--green);
  box-shadow: 0 0 0 0 rgba(34,197,94,0.6);
  animation: clockPulse 1.6s ease-out infinite;
}
.market-clock.mkt-open .clock-status strong { color: var(--green); }

.market-clock.mkt-closed {
  border-color: rgba(239,68,68,0.4);
  background: var(--red-bg);
}
.market-clock.mkt-closed .clock-dot {
  background: var(--red);
}
.market-clock.mkt-closed .clock-status strong { color: var(--red); }

@keyframes clockPulse {
  0%   { box-shadow: 0 0 0 0   rgba(34,197,94,0.55); }
  70%  { box-shadow: 0 0 0 6px rgba(34,197,94,0);    }
  100% { box-shadow: 0 0 0 0   rgba(34,197,94,0);    }
}

.header-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 12px;
}

/* Mobile-only right cluster + dropdown menu - hidden on desktop. CSS
   inside the @media (max-width: 900px) block flips this back on. */
.header-right-mobile,
.header-hamburger,
.header-menu,
.header-menu-backdrop { display: none; }

.status-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
}

.status-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--border);
  flex-shrink: 0;
}
.status-dot.idle    { background: var(--border); }
.status-dot.running { background: var(--green); animation: blink 1.2s ease-in-out infinite; }
.status-dot.done    { background: var(--green); }
.status-dot.error   { background: var(--red); }

@keyframes blink { 0%,100%{opacity:1} 50%{opacity:.35} }

/* ── Layout ──────────────────────────────────── */
.layout {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* ── Sidebar ─────────────────────────────────── */
aside {
  width: 288px;
  background: var(--surface);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  flex-shrink: 0;
  padding: 16px 14px 24px;
}

.section-title {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--muted);
  margin: 18px 0 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.section-title:first-child { margin-top: 0; }
.section-title .sub-note {
  font-size: 10px;
  font-weight: 400;
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0;
}

.preset-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

.btn-preset {
  padding: 5px 11px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.btn-preset:hover { border-color: var(--accent); color: var(--accent); }

.field { margin-bottom: 11px; }
.field label {
  display: block;
  font-size: 11px;
  color: var(--muted);
  margin-bottom: 4px;
}
.field input[type="number"],
.field input[type="text"],
.field select {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 7px 10px;
  font-size: 13px;
  outline: none;
  transition: border-color .15s;
}
.field input:focus,
.field select:focus { border-color: var(--accent); }

.range-pair { display: flex; align-items: center; gap: 6px; }
.range-pair input { text-align: center; }
.range-pair span { color: var(--muted); font-size: 12px; flex-shrink: 0; }

.checkboxes { display: flex; flex-direction: column; gap: 7px; }

.cb-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  cursor: pointer;
  user-select: none;
}
.cb-label input[type="checkbox"] {
  accent-color: var(--accent);
  width: 15px; height: 15px;
  cursor: pointer;
}
.cb-sub { font-size: 11px; color: var(--muted); }

.slider-wrap {
  display: flex;
  align-items: center;
  gap: 10px;
}
.slider-wrap input[type="range"] {
  flex: 1;
  accent-color: var(--accent);
  cursor: pointer;
}
.slider-val {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  min-width: 28px;
  text-align: right;
}

.btn-run {
  width: 100%;
  padding: 13px;
  margin-top: 18px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  letter-spacing: 0.2px;
  transition: background .15s, opacity .15s;
}
.btn-run:hover:not(:disabled) { background: var(--accent2); }
.btn-run:disabled { opacity: .5; cursor: not-allowed; }

/* ── Main ───────────────────────────────────── */
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ── Progress strip ─────────────────────────── */
.progress-strip {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 14px 24px 12px;
  flex-shrink: 0;
}
.prog-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}
.prog-phase { font-size: 13px; font-weight: 500; }
.prog-count { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

.prog-pct-big {
  font-size: 22px;
  font-weight: 800;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.3px;
}

.prog-stats {
  display: flex;
  gap: 22px;
  margin-top: 10px;
  flex-wrap: wrap;
}

.prog-stat {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.prog-stat-lbl {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
}

.prog-stat-val {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.prog-stat-val.accent { color: var(--green); }

.track {
  height: 5px;
  background: var(--surface2);
  border-radius: 3px;
  overflow: hidden;
}
.fill {
  position: relative;
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--green));
  border-radius: 3px;
  transition: width .35s cubic-bezier(0.4, 0.0, 0.2, 1);
  overflow: hidden;
}
/* Moving sheen so the bar reads as "working" even between progress
   ticks. Disabled under the reduce-motion accessibility preference. */
.fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.35) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  animation: prog-sheen 1.4s ease-in-out infinite;
}
@keyframes prog-sheen {
  0%   { transform: translateX(-100%); }
  60%  { transform: translateX(100%); }
  100% { transform: translateX(100%); }
}
html.a11y-reduce-motion .fill::after { animation: none; }

.live-feed {
  margin-top: 10px;
  height: 90px;
  overflow-y: auto;
  font-size: 12px;
  font-family: 'Cascadia Code', 'Consolas', 'Courier New', monospace;
  background: var(--bg);
  border-radius: 6px;
  padding: 7px 10px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.feed-row {
  display: flex;
  gap: 10px;
  align-items: center;
  color: var(--muted);
}
.feed-sym { color: var(--accent); font-weight: 600; min-width: 58px; }
.feed-sys { color: var(--muted); font-style: italic; }
.feed-err { color: var(--red); }

.feed-s0,.feed-s1,.feed-s2,.feed-s3 { color: var(--red);    font-weight: 600; }
.feed-s4,.feed-s5                   { color: var(--orange); font-weight: 600; }
.feed-s6                            { color: var(--yellow); font-weight: 600; }
.feed-s7,.feed-s8                   { color: var(--green);  font-weight: 600; }

.mini-bar {
  display: inline-block;
  width: 60px;
  height: 4px;
  background: var(--surface2);
  border-radius: 2px;
  overflow: hidden;
  vertical-align: middle;
  margin-left: 4px;
}
.mini-bar > span {
  display: block;
  height: 100%;
}

/* ── Stats bar ──────────────────────────────── */
.stats-bar {
  display: flex;
  /* Wrap to additional rows when the stats don't fit the content width
     (e.g. iPad-Pro-width desktop layout, ~700px content). Without this the
     row stayed a single line with `overflow: visible`, so the stat blocks
     spilled OUT past the bar's background — the bar looked "shorter than the
     data". Wide desktops fit on one row, so they're unaffected. */
  flex-wrap: wrap;
  row-gap: 12px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 12px 24px;
  flex-shrink: 0;
  align-items: center;
  /* Don't trap tooltips that extend above the bar */
  overflow: visible;
  position: relative;
  z-index: 2;
}
/* On phones the 8 stat blocks would overflow off the right edge. Rather
   than a horizontal scroll (which slices the last visible stat mid-label
   and looks cut), lay them out as an auto-fit grid so EVERY metric is
   visible, wrapping onto as many rows as needed. */
@media (max-width: 900px) {
  .stats-bar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
    gap: 12px 10px;
    overflow: visible;
    padding: 10px 14px;
  }
  .stats-bar .stat {
    flex-shrink: 1;
    min-width: 0;
    padding: 0;
  }
  /* No vertical dividers in the grid — the gap separates cells, and the
     base `+ .stat` border would land at row starts and look misaligned. */
  .stats-bar .stat + .stat { border-left: none; padding-left: 0; }
}

.stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-right: 28px;
}
.stat + .stat { border-left: 1px solid var(--border); padding-left: 28px; }

.stat-lbl {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.7px;
  color: var(--muted);
}
.stat-val {
  font-size: 22px;
  font-weight: 700;
  line-height: 1.1;
}
.stat-val.sm { font-size: 16px; }

.btn-export {
  padding: 8px 14px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s, color .15s;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.btn-export:hover { border-color: var(--accent); color: var(--accent); }

/* Wrapper for the right-aligned action buttons in StatsBar - keeps them
   packed together as one group instead of each becoming its own spacer. */
.stats-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ── Table ──────────────────────────────────── */
.table-area {
  flex: 1;
  overflow: auto;
}

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

thead th {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--bg);
  padding: 10px;
  text-align: left;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
  user-select: none;
}
thead th:hover { color: var(--text); }
thead th.sort-asc::after  { content: " ↑"; color: var(--accent); }
thead th.sort-desc::after { content: " ↓"; color: var(--accent); }

tbody tr { border-bottom: 1px solid rgba(45,55,72,0.6); }
tbody tr:hover { background: rgba(31,41,55,0.7); }
/* Whole scanner result row opens the chart on click. The action buttons
   inside (watch / note / compare) stopPropagation so they keep working. */
tbody tr.row-clickable { cursor: pointer; }

td { padding: 9px 10px; vertical-align: middle; }

/* Symbol cell layout - icons + ticker stay on one line, never reflow */
tbody tr td:first-child {
  white-space: nowrap;
  min-width: 110px;
  padding-right: 14px;
}

/* ── Impersonation banner (sits above everything) ── */

.impersonation-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 14px;
  background: linear-gradient(90deg, #f59e0b22, #d9770622);
  border-bottom: 1px solid #f59e0b;
  color: var(--text);
  font-size: 13px;
}
.impersonation-msg { color: var(--text); }
.impersonation-msg strong { color: #f59e0b; }
.impersonation-exit {
  background: #f59e0b;
  color: #fff;
  border: none;
  font-size: 12px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: 6px;
  cursor: pointer;
  flex-shrink: 0;
}
.impersonation-exit:hover { background: #d97706; }


/* Admin-shortcut header button (the 🛠 next to ⚙ Settings) */
.btn-admin-shortcut {
  /* Slight amber tint so it visually announces "you're a dev" */
  color: #f59e0b !important;
}
.btn-admin-shortcut:hover {
  background: rgba(245, 158, 11, 0.15) !important;
}


/* ── Admin panel (full-screen, opened from header 🛠) ────── */

.admin-panel-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(2px);
  /* Above the .mobile-bottom-nav (z-index: 200) so the admin panel
     covers the bottom nav on phones instead of being trapped behind
     it. Also matches .modal-backdrop's z-index: 1000 — both are
     viewport-takeover surfaces, neither should be obscured by the
     bottom nav. */
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.admin-panel-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  width:  min(1400px, 96vw);
  height: min(900px,  92vh);
  display: flex;
  flex-direction: column;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
  overflow: hidden;
}
.admin-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
  background: var(--surface2);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.admin-panel-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 17px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -0.2px;
}
.admin-panel-emoji {
  font-size: 22px;
  line-height: 1;
}
.admin-panel-close {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 30px;
  width: 36px;
  height: 36px;
  line-height: 1;
  border-radius: 6px;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.admin-panel-close:hover { background: var(--surface); color: var(--text); }
.admin-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px 24px 24px;
}

@media (max-width: 900px) {
  .admin-panel-backdrop { padding: 0; }
  .admin-panel-card {
    width: 100vw;
    /* `dvh` accounts for the iOS Safari URL bar collapsing — falls
       back to `vh` for older browsers via the cascade. */
    height: 100vh;
    height: 100dvh;
    border-radius: 0;
    border: none;
    /* Prevent the body's scroll from bleeding into the page below
       when the user keeps swiping at the top/bottom of the content. */
    overscroll-behavior: contain;
  }
  .admin-panel-body {
    /* iOS momentum scrolling — without this, drag-scrolling on iPhone
       feels stiff and stops the moment your finger lifts. */
    -webkit-overflow-scrolling: touch;
    /* Allow the body to shrink inside its flex parent. Without
       `min-height: 0`, the flex column can refuse to shrink below the
       intrinsic content size — which means the body never overflows
       and `overflow-y: auto` does nothing on tall content. */
    min-height: 0;
    /* Reserve room for the iPhone home-indicator / Android nav bar so
       the last content (table rows, the bottom of a Deleted-Users
       list, etc.) isn't hidden under the system gesture area. */
    padding: 14px 14px calc(14px + env(safe-area-inset-bottom));
  }
}


/* ── Admin tab (dev-only user management) ──────────────── */

/* Metrics row across the top of the admin panel */
.admin-metrics {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 12px;
  margin-bottom: 20px;
}
.admin-metric {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 12px;
  text-align: center;
}
.admin-metric-n {
  font-size: 26px;
  font-weight: 800;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.admin-metric-l {
  font-size: 11px;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  margin-top: 6px;
}
.admin-metric-mrr {
  background: linear-gradient(135deg, rgba(245,158,11,0.10), rgba(217,119,6,0.02));
  border-color: rgba(245,158,11,0.4);
}
.admin-metric-mrr .admin-metric-n { color: #f59e0b; }

/* ── Growth-funnel analytics ─────────────────────────────── */
.admin-analytics {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 20px;
}
.admin-analytics-funnel {
  display: flex;
  align-items: stretch;
  gap: 6px;
  flex-wrap: wrap;
}
.admin-funnel-step {
  flex: 1 1 auto;
  min-width: 84px;
  text-align: center;
  padding: 10px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
}
.admin-funnel-n {
  font-size: 22px;
  font-weight: 800;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.admin-funnel-l {
  font-size: 10px;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  margin-top: 5px;
}
.admin-funnel-arrow {
  align-self: center;
  color: var(--muted);
  font-size: 15px;
  flex: 0 0 auto;
}
.admin-funnel-hi {
  background: linear-gradient(135deg, rgba(34,197,94,0.12), rgba(34,197,94,0.02));
  border-color: rgba(34,197,94,0.45);
}
.admin-funnel-hi .admin-funnel-n { color: var(--green, #22c55e); }
.admin-analytics-sub {
  margin-top: 12px;
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.admin-spark-wrap { margin-top: 14px; }
.admin-spark-label {
  font-size: 10px;
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  margin-bottom: 5px;
}
.admin-spark {
  display: block;
  width: 100%;
  height: 40px;
}

/* Users / Audit-log sub-tabs */
.admin-subtabs {
  display: flex;
  gap: 4px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.admin-subtab {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  padding: 8px 14px;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.admin-subtab:hover { color: var(--text); }
.admin-subtab-active { color: var(--accent); border-bottom-color: var(--accent); }



.admin-tab {
  font-size: 12px;
}
.admin-tab-warn {
  background: rgba(245, 158, 11, 0.10);
  border: 1px solid rgba(245, 158, 11, 0.40);
  color: var(--text);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 11.5px;
  line-height: 1.5;
  margin: 0 0 12px;
}

/* ── Score-bucket diagnostic chart (admin Diagnostics tab) ── */
.admin-diag-controls {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 12px 0 16px;
  flex-wrap: wrap;
}
.admin-diag-input {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--muted);
}
.admin-diag-input input {
  width: 70px;
  padding: 6px 8px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
}
.admin-diag-verdict {
  font-size: 12px;
  font-weight: 700;
  padding: 6px 12px;
  border-radius: 999px;
  letter-spacing: 0.3px;
}
.admin-diag-verdict-clean_signal { background: rgba(74,222,128,0.15); color: #4ade80; border: 1px solid rgba(74,222,128,0.35); }
.admin-diag-verdict-weak_signal  { background: rgba(245,158,11,0.15); color: #f59e0b; border: 1px solid rgba(245,158,11,0.35); }
.admin-diag-verdict-noisy        { background: rgba(148,163,184,0.15); color: var(--muted); border: 1px solid rgba(148,163,184,0.35); }
.admin-diag-verdict-inverted     { background: rgba(239,68,68,0.15);  color: #ef4444; border: 1px solid rgba(239,68,68,0.35); }

.admin-diag-meta {
  font-size: 11.5px;
  color: var(--muted);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  margin-bottom: 12px;
}
.admin-diag-chart {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 16px 18px;
}
.admin-diag-bar-row {
  display: grid;
  grid-template-columns: 64px 1fr 240px;
  gap: 14px;
  align-items: center;
}
.admin-diag-bar-label {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  text-align: right;
}
.admin-diag-bar-track {
  position: relative;
  height: 26px;
  background: var(--surface3);
  border-radius: 4px;
  overflow: hidden;
}
.admin-diag-bar-mid {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border);
  z-index: 1;
}
.admin-diag-bar-fill {
  position: absolute;
  top: 4px;
  bottom: 4px;
  border-radius: 3px;
  transition: width 250ms ease;
}
.admin-diag-bar-fill.pos { background: linear-gradient(90deg, rgba(74,222,128,0.5), rgba(74,222,128,0.9)); }
.admin-diag-bar-fill.neg { background: linear-gradient(270deg, rgba(239,68,68,0.5), rgba(239,68,68,0.9)); }
.admin-diag-bar-value {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  z-index: 2;
  padding: 0 6px;
  background: rgba(0,0,0,0.35);
  border-radius: 3px;
}
.admin-diag-bar-meta {
  font-size: 11px;
  color: var(--muted);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  text-align: left;
}
.admin-diag-legend {
  margin-top: 14px;
  padding: 10px 14px;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.admin-diag-legend strong { color: var(--text); font-weight: 600; }

@media (max-width: 760px) {
  .admin-diag-bar-row {
    grid-template-columns: 50px 1fr;
    grid-template-areas:
      "label  track"
      "meta   meta";
    gap: 8px;
  }
  .admin-diag-bar-label { grid-area: label; }
  .admin-diag-bar-track { grid-area: track; }
  .admin-diag-bar-meta  { grid-area: meta; text-align: right; }
}
.admin-search {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}
.admin-search input {
  flex: 1;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 8px 10px;
  font-size: 13px;
}
.admin-search input:focus { border-color: var(--accent); outline: none; }
.admin-search .btn-preset { padding: 8px 14px; }

.admin-count {
  font-size: 11px;
  color: var(--muted);
  margin: 6px 2px;
}
.admin-empty {
  text-align: center;
  color: var(--muted);
  padding: 24px 12px;
  font-size: 13px;
}

/* ── Admin support inbox ─────────────────────────────────────── */
.admin-support-filters {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.admin-support-filters select {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  padding: 7px 10px;
  cursor: pointer;
}
.admin-support-filters select:focus { border-color: var(--accent, #3b82f6); outline: none; }
.admin-support-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 4px;
}
.admin-support-msg {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
  background: var(--surface-2, rgba(255,255,255,0.02));
}
/* Unread (new) messages get a left accent so they stand out. */
.admin-support-msg.admin-support-new { border-left: 3px solid var(--accent, #3b82f6); }
.admin-support-msg.admin-support-closed { opacity: 0.62; }
.admin-support-top {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.admin-support-cat {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  padding: 2px 8px;
  border-radius: 20px;
  background: var(--surface3, rgba(255,255,255,0.06));
  color: var(--text);
}
.admin-support-cat-bug        { background: var(--red-bg);    color: var(--red); }
.admin-support-cat-billing    { background: var(--green-bg);  color: var(--green); }
.admin-support-cat-suggestion { background: var(--yellow-bg); color: var(--yellow, #eab308); }
.admin-support-status {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--muted);
}
.admin-support-date { font-size: 11px; color: var(--muted); margin-left: auto; }
.admin-support-from { font-size: 13px; color: var(--text); margin-bottom: 4px; }
.admin-support-from a { color: var(--accent, #3b82f6); text-decoration: none; }
.admin-support-subject { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.admin-support-body {
  font-size: 13px;
  color: var(--text);
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
}
.admin-support-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.admin-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border);
  border-radius: 8px;
}
.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.admin-table thead th {
  background: var(--surface2);
  text-align: left;
  font-weight: 700;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.admin-table tbody td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.admin-table tbody tr:last-child td { border-bottom: none; }
.admin-table tbody tr:hover { background: var(--surface2); }

.admin-email {
  font-weight: 700;
  color: var(--text);
}
.admin-email-sub {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.admin-tag {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  background: rgba(255,255,255,0.06);
  color: var(--muted);
  padding: 2px 6px;
  border-radius: 8px;
  border: 1px solid var(--border);
}
.admin-tag-admin { background: rgba(245,158,11,0.15); color: #f59e0b; border-color: rgba(245,158,11,0.4); }
.admin-tag-warn  { background: rgba(239,68,68,0.15); color: var(--red);   border-color: rgba(239,68,68,0.4); }

.admin-tier {
  display: inline-block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.6px;
  padding: 3px 8px;
  border-radius: 8px;
  white-space: nowrap;
}
.admin-tier-pro {
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: #fff;
}
.admin-tier-free {
  background: var(--surface2);
  color: var(--muted);
  border: 1px solid var(--border);
}
.admin-status {
  font-size: 11px;
  color: var(--muted);
  text-transform: capitalize;
}
.admin-date {
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.admin-actions {
  display: flex;
  gap: 4px;
  white-space: nowrap;
}
.admin-btn {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 11px;
  font-weight: 600;
  padding: 4px 8px;
  border-radius: 5px;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
  min-height: 0 !important;
}
.admin-btn:hover { border-color: var(--accent); color: var(--accent); }
.admin-btn-pro:hover { border-color: #f59e0b; color: #f59e0b; }
.admin-btn-danger { color: var(--red); }
.admin-btn-danger:hover { background: var(--red-bg); border-color: var(--red); color: var(--red); }
.admin-btn-impersonate { padding: 4px 6px; }
.admin-btn-impersonate:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

/* On mobile the 6-card metrics row + dense user table need adjustments */
@media (max-width: 900px) {
  .admin-metrics {
    grid-template-columns: repeat(3, 1fr);
  }
  .admin-metric-n { font-size: 16px; }
  .admin-metric    { padding: 10px 8px; }
  .admin-metric-l  { font-size: 10px; letter-spacing: 0.4px; }

  /* Sub-tabs (Users / Audit log / Deleted / Diagnostics) total ~400 px,
     wider than a phone. Allow horizontal scroll + tighter padding so
     all four are reachable. */
  .admin-subtabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .admin-subtabs::-webkit-scrollbar { display: none; }
  .admin-subtab {
    padding: 8px 9px;
    flex-shrink: 0;
    font-size: 11px;
  }

  /* Diagnostic-tool controls (symbol input + run button + verdict pill)
     stack vertically — gap: 14 px horizontal is too generous when
     children stretch full width. */
  .admin-diag-controls {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .admin-diag-input input { width: 100%; }

  /* Admin panel head: title can be smaller; close button stays size. */
  .admin-panel-title { font-size: 15px; }
  .admin-panel-emoji { font-size: 18px; }
  .admin-panel-head  { padding: 12px 14px; }
}
/* Very narrow phones (≤480 px) — even 3 columns of metrics is cramped.
   Drop to 2 columns so each card's number stays at a legible size. */
@media (max-width: 480px) {
  .admin-metrics { grid-template-columns: repeat(2, 1fr); }
  .admin-metric-n { font-size: 18px; }
}


/* ── Billing tab (inside the Settings modal) ──────────────── */

.billing-tab {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.billing-status {
  border-radius: 10px;
  padding: 18px 18px 16px;
  border: 1px solid var(--border);
}
.billing-status-active {
  background: linear-gradient(135deg, rgba(245,158,11,0.10), rgba(217,119,6,0.04));
  border-color: rgba(245, 158, 11, 0.45);
}
.billing-status-trial {
  background: linear-gradient(135deg, rgba(59,130,246,0.10), rgba(59,130,246,0.02));
  border-color: rgba(59, 130, 246, 0.45);
}
.billing-status-free {
  background: var(--surface2);
}
.billing-status-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.billing-status-name {
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
}
.billing-status-detail {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.55;
}
.billing-blurb {
  font-size: 13px;
  color: var(--text);
  line-height: 1.6;
  margin: 4px 0;
}
.billing-foot {
  font-size: 11.5px;
  color: var(--muted);
  margin: 12px 0 0;
  text-align: center;
  line-height: 1.6;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.billing-foot a { color: var(--accent); text-decoration: none; }
.billing-foot a:hover { text-decoration: underline; }


/* ─────────────────────────────────────────────────────────
   Marketing landing page (LandingPage component in modals.jsx)
   Default view for unauthenticated visitors.
   ───────────────────────────────────────────────────────── */

.landing {
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', -apple-system, Segoe UI, system-ui, sans-serif;
  width: 100%;
  min-height: 100vh;
  overflow-x: hidden;
}

/* Top bar - logo + sign-in link */
.landing-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Add the status-bar inset on top so the logo/sign-in clear the notch
     (0 on non-notched devices). See the body @supports note. */
  padding: calc(22px + env(safe-area-inset-top, 0)) 5vw 22px;
  max-width: 1280px;
  margin: 0 auto;
}
.landing-brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
.landing-logo {
  width: 36px;
  height: 36px;
}
.landing-name {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.3px;
}
.landing-beta-pill {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.5px;
  padding: 3px 8px;
  border-radius: 6px;
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: #fff;
  margin-left: 8px;
  box-shadow: 0 1px 4px rgba(245, 158, 11, 0.4);
}
.landing-signin-link {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  padding: 8px 16px;
  border-radius: 8px;
  cursor: pointer;
  /* Prevent the button text from wrapping to two lines on narrow phone
     viewports — "Sign in →" was breaking after "Sign" because the brand
     "SwingMentalist BETA" beside it consumed most of the width. */
  white-space: nowrap;
  flex-shrink: 0;
  transition: border-color .15s, background .15s;
}
.landing-signin-link:hover {
  border-color: var(--accent);
  background: rgba(59,130,246,0.08);
}

/* Hero - the first thing visitors see */
.landing-hero {
  text-align: center;
  padding: 60px 5vw 100px;
  max-width: 920px;
  margin: 0 auto;
}
.landing-hero-eyebrow {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 28px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.landing-hero-title {
  font-size: clamp(38px, 6.5vw, 72px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -2.5px;
  margin: 0 0 28px;
  font-family: 'Inter', -apple-system, 'Segoe UI', system-ui, sans-serif;
}
.landing-hero-accent {
  background: linear-gradient(90deg, #3b82f6 0%, #22d3ee 50%, #84cc16 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
}
.landing-hero-sub {
  font-size: clamp(15px, 1.5vw, 17px);
  color: var(--muted);
  line-height: 1.7;
  margin: 0 auto 44px;
  max-width: 660px;
  font-weight: 400;
}
.landing-hero-cta {
  display: inline-flex;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: center;
}
.landing-btn {
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 600;
  padding: 13px 22px;
  border-radius: 8px;
  cursor: pointer;
  transition: transform .12s ease, box-shadow .15s ease, background .15s ease, border-color .15s;
  border: 1px solid transparent;
  letter-spacing: -0.1px;
}
.landing-btn-primary {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 4px 16px rgba(59,130,246,0.28);
}
.landing-btn-primary:hover {
  background: #2563eb;
  transform: translateY(-1px);
  box-shadow: 0 1px 0 rgba(255,255,255,0.1) inset, 0 6px 22px rgba(59,130,246,0.42);
}
.landing-btn-secondary {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.landing-btn-secondary:hover {
  border-color: var(--accent);
  background: rgba(59,130,246,0.06);
}
.landing-hero-note {
  margin-top: 24px;
  font-size: 13px;
  color: var(--muted);
}

/* Trust strip - verifiable specifications */
.landing-hero-trust {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 40px;
  margin-top: 80px;
  flex-wrap: wrap;
  padding: 32px 40px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 12px;
}
.landing-hero-trust-item {
  text-align: center;
}
.landing-hero-trust-n {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -1px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.landing-hero-trust-l {
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.4px;
  margin-top: 4px;
}
.landing-hero-trust-sep {
  width: 1px;
  height: 28px;
  background: var(--border);
}

/* ── Sticky marketing nav (brand + anchor "tabs" + persistent CTA) ── */
.landing-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg);                                   /* fallback */
  background: color-mix(in srgb, var(--bg) 68%, transparent);
  -webkit-backdrop-filter: saturate(165%) blur(16px);
          backdrop-filter: saturate(165%) blur(16px);
  border-bottom: 1px solid color-mix(in srgb, var(--border) 75%, transparent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04),
              0 8px 28px -18px rgba(0, 0, 0, 0.7);
  padding-top: env(safe-area-inset-top, 0);
}
.landing-nav-inner {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 18px 5vw;
}
.landing-nav .landing-brand { text-decoration: none; color: var(--text); }
.landing-nav .landing-logo { width: 42px; height: 42px; transition: transform .25s ease; }
.landing-nav .landing-name { font-size: 21px; }
.landing-nav .landing-brand:hover .landing-logo { transform: rotate(-8deg) scale(1.08); }

.landing-nav-links {
  display: flex;
  gap: 4px;
  margin-left: auto;
  margin-right: 8px;
}
.landing-nav-links a {
  position: relative;
  color: var(--muted);
  text-decoration: none;
  font-size: 15px;
  font-weight: 600;
  padding: 10px 16px;
  border-radius: 8px;
  transition: color .15s ease, background .15s ease;
}
.landing-nav-links a:hover {
  color: var(--text);
  background: color-mix(in srgb, var(--text) 7%, transparent);
}
/* Animated gradient underline on hover. */
.landing-nav-links a::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 5px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), #22d3ee);
  transform: scaleX(0);
  transition: transform .24s cubic-bezier(.4, 0, .2, 1);
}
.landing-nav-links a:hover::after { transform: scaleX(1); }
/* Scroll-spy: the section currently in view stays lit with the underline. */
.landing-nav-links a.is-active { color: var(--text); }
.landing-nav-links a.is-active::after { transform: scaleX(1); }

.landing-nav-cta {
  position: relative;
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.14);
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  padding: 11px 24px;
  border-radius: 10px;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  box-shadow: 0 6px 18px rgba(59, 130, 246, 0.40),
              inset 0 1px 0 rgba(255, 255, 255, 0.22);
  transition: transform .14s ease, box-shadow .2s ease, filter .2s ease;
}
.landing-nav-cta:hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
  box-shadow: 0 10px 28px rgba(59, 130, 246, 0.52),
              inset 0 1px 0 rgba(255, 255, 255, 0.30);
}
.landing-nav-cta:active { transform: translateY(0); }

/* Anchor-jump offset so the sticky nav doesn't cover section headings. */
.landing-features, .landing-showcase, .landing-pricing, .landing-faq { scroll-margin-top: 96px; }

/* ── Framed product screenshot (browser-chrome mockup) ── */
.landing-shot-frame {
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface);
  box-shadow: 0 30px 60px -22px rgba(0,0,0,0.55), 0 8px 20px -10px rgba(0,0,0,0.40);
}
.landing-shot-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background: var(--surface2);
  border-bottom: 1px solid var(--border);
}
.landing-shot-bar > span {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--border);
  flex-shrink: 0;
}
.landing-shot-bar > span:nth-child(1) { background: rgba(239,68,68,0.75); }
.landing-shot-bar > span:nth-child(2) { background: rgba(245,158,11,0.75); }
.landing-shot-bar > span:nth-child(3) { background: rgba(34,197,94,0.75); }
.landing-shot-bar-url {
  margin-left: 12px;
  font-size: 11.5px;
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 3px 12px;
  flex: 1;
  max-width: 300px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.landing-shot-img { display: block; width: 100%; height: auto; }
.landing-shot-ph {
  aspect-ratio: 16 / 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  background:
    radial-gradient(120% 120% at 50% 0%, rgba(59,130,246,0.10), transparent 60%),
    repeating-linear-gradient(45deg, transparent 0 14px, rgba(127,127,127,0.045) 14px 28px);
  color: var(--muted);
}
.landing-shot-ph-label { font-size: 17px; font-weight: 700; color: var(--text); letter-spacing: -0.3px; }
.landing-shot-ph-path {
  font-size: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: 6px;
  padding: 4px 12px;
}

/* Hero product shot — break out wider than the hero text column so it reads big. */
.landing-hero-shot {
  width: min(1440px, 96vw);
  margin: 64px auto 0;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

/* ── Showcase — interactive screenshot tabs ── */
.landing-showcase {
  max-width: 1700px;
  margin: 0 auto;
  padding: 84px 16px;
  text-align: center;
}
.landing-showcase-tabs {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px;
  margin: 26px 0 38px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.landing-showcase-tab {
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  background: transparent;
  border: none;
  border-radius: 8px;
  padding: 9px 18px;
  cursor: pointer;
  transition: color .15s, background .15s;
}
.landing-showcase-tab:hover { color: var(--text); }
.landing-showcase-tab.is-active {
  color: #fff;
  background: var(--accent);
  box-shadow: 0 4px 12px rgba(59,130,246,0.30);
}

/* ── Workflow stepper: showcase tabs rendered as
      Scan → Analyze → Plan → Track → Improve ── */
.landing-showcase-tabs.landing-stepper {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 2px;
  padding: 0;
  background: transparent;
  border: none;
  margin: 26px auto 40px;
}
.landing-step {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  border-radius: 999px;
  color: var(--muted);
}
.landing-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-size: 13px;
  font-weight: 800;
  background: rgba(127,138,163,0.12);
  border: 1px solid var(--border);
  color: var(--muted);
  transition: background .15s, border-color .15s, color .15s;
}
.landing-step-name { font-weight: 700; font-size: 14px; }
/* arrow connector between consecutive stages */
.landing-step:not(:last-child)::after {
  content: "→";
  margin-left: 12px;
  font-weight: 700;
  color: var(--muted);
  opacity: 0.45;
}
/* stages up to and including the active one get an accent number */
.landing-step.is-reached .landing-step-num {
  background: rgba(59,130,246,0.16);
  border-color: rgba(59,130,246,0.5);
  color: var(--accent);
}
/* active stage — subtle pill + filled number (overrides the plain tab style) */
.landing-showcase-tab.landing-step.is-active {
  background: rgba(59,130,246,0.12);
  box-shadow: none;
  color: var(--text);
}
.landing-step.is-active .landing-step-num {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
/* Stack: a compact caption header on top, then a BIG full-width screenshot. */
.landing-showcase-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
}
.landing-showcase-caption { order: 1; max-width: 940px; margin: 0 auto; }
.landing-showcase-shot    { order: 2; width: 100%; text-align: center; }
/* Full image, no crop — every screenshot shows all its content. The frame
   shrink-wraps the image: wide shots fill the (wide) container for max height,
   while tall shots are capped at 78vh so they don't dominate. width/height
   auto means nothing is ever upscaled, so captures stay crisp. */
.landing-showcase-shot .landing-shot-frame { display: inline-block; max-width: 100%; }
.landing-showcase-shot .landing-shot-img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 78vh;
}
.landing-showcase-step {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 10px;
}
.landing-showcase-title {
  font-size: clamp(22px, 2.6vw, 28px);
  font-weight: 700;
  letter-spacing: -0.5px;
  margin: 0 0 20px;
}
.landing-showcase-bullets {
  list-style: none;
  margin: 0 auto 22px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px 28px;
  max-width: 900px;
  text-align: left;
}
.landing-showcase-bullets li {
  position: relative;
  padding-left: 28px;
  color: var(--muted);
  font-size: 14.5px;
  line-height: 1.55;
}
.landing-showcase-bullets li::before {
  content: '✓';
  position: absolute;
  left: 0; top: 0;
  color: var(--accent);
  font-weight: 800;
}

@media (max-width: 860px) {
  .landing-nav-links { display: none; }
  .landing-showcase-bullets { grid-template-columns: 1fr; max-width: 460px; }
}

/* Eyebrow above section heads - restrained typographic label */
.landing-section-eyebrow {
  font-size: 11.5px !important;
  font-weight: 600 !important;
  letter-spacing: 2px !important;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
  margin: 0 0 18px !important;
  display: block;
}
.landing-section-head {
  margin-bottom: 12px;
}
.landing-section-sub {
  text-align: center;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.6;
  max-width: 640px;
  margin: 0 auto 16px;
}

/* Problem section - restrained, editorial */
.landing-problem {
  padding: 100px 5vw;
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.landing-problem-inner {
  max-width: 1180px;
  margin: 0 auto;
}
.landing-problem-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-top: 50px;
}
.landing-problem-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px 28px;
}
.landing-problem-num {
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--muted);
  margin-bottom: 22px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.landing-problem-title {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.3px;
  margin-bottom: 10px;
}
.landing-problem-desc {
  font-size: 14px;
  color: var(--muted);
  line-height: 1.65;
  margin: 0;
}
.landing-problem-solution {
  text-align: center;
  margin-top: 60px;
  padding: 44px 32px;
  background: var(--bg);
  border: 1px solid var(--accent);
  border-radius: 12px;
  position: relative;
}
.landing-problem-solution::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
}
.landing-problem-solution-head {
  font-size: clamp(20px, 2.6vw, 26px);
  font-weight: 700;
  letter-spacing: -0.4px;
  margin: 0 0 14px;
  color: var(--text);
}
.landing-problem-solution-sub {
  font-size: 15px;
  color: var(--muted);
  line-height: 1.7;
  margin: 0 auto;
  max-width: 640px;
}

/* Built for / not for section */
.landing-built {
  padding: 80px 5vw;
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.landing-built-inner {
  max-width: 1080px;
  margin: 0 auto;
}
.landing-built-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 30px;
  margin-top: 44px;
}
.landing-built-col {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 36px 32px;
}
.landing-built-col-head {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 24px;
}
.landing-built-col-yes { color: var(--text); }
.landing-built-col-no  { color: var(--muted); }
.landing-built-list {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 14px;
  line-height: 2;
  color: var(--text);
}
.landing-built-list li {
  padding-left: 22px;
  position: relative;
}
.landing-built-list li::before {
  content: '+';
  color: #22c55e;
  font-weight: 600;
  position: absolute;
  left: 0;
  font-size: 16px;
  line-height: 1.7;
}
.landing-built-list-no li::before {
  content: '−';
  color: #ef4444;
}

/* FAQ */
.landing-faq {
  padding: 80px 5vw;
  max-width: 880px;
  margin: 0 auto;
}
.landing-faq-list {
  margin-top: 36px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.landing-faq-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  transition: border-color .15s;
}
.landing-faq-item[open] { border-color: var(--accent); }
.landing-faq-item summary {
  padding: 18px 22px;
  font-size: 15.5px;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  user-select: none;
}
.landing-faq-item summary::-webkit-details-marker { display: none; }
.landing-faq-item summary::after {
  content: '+';
  font-size: 22px;
  font-weight: 400;
  color: var(--muted);
  transition: transform .2s ease;
  margin-left: 12px;
  flex-shrink: 0;
}
.landing-faq-item[open] summary::after {
  transform: rotate(45deg);
  color: var(--accent);
}
.landing-faq-body {
  padding: 0 22px 20px;
  font-size: 14px;
  color: var(--muted);
  line-height: 1.7;
}
.landing-faq-body strong { color: var(--text); }
.landing-mono {
  font-family: 'Cascadia Code', Consolas, monospace;
  color: var(--text);
  font-size: 0.92em;
  padding: 1px 6px;
  background: var(--surface2);
  border-radius: 4px;
}

/* Section heading style - used by features / how-it-works / pricing */
.landing-section-head {
  font-size: clamp(26px, 3.2vw, 38px);
  font-weight: 700;
  letter-spacing: -1px;
  text-align: center;
  margin: 0 0 14px;
  line-height: 1.2;
  color: var(--text);
}

/* Features section */
.landing-features {
  padding: 70px 5vw;
  max-width: 1180px;
  margin: 0 auto;
}
.landing-features-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  margin-top: 40px;
}
.landing-feature {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px 28px;
  transition: border-color .2s, background .2s;
}
.landing-feature:hover {
  border-color: var(--accent);
  background: rgba(59,130,246,0.03);
}
.landing-feature-num {
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--accent);
  margin-bottom: 22px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.landing-feature-name {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.3px;
  margin-bottom: 10px;
  color: var(--text);
}
.landing-feature-desc {
  font-size: 14px;
  color: var(--muted);
  line-height: 1.65;
  margin: 0;
}

/* How-it-works section - numbered steps */
.landing-how {
  padding: 70px 5vw;
  max-width: 1180px;
  margin: 0 auto;
  background: var(--surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.landing-how-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 30px;
  margin-top: 44px;
}
.landing-how-grid-5 { grid-template-columns: repeat(5, 1fr); gap: 22px; }
.landing-how-step { text-align: center; }
.landing-how-icon { font-size: 26px; line-height: 1; margin-bottom: 8px; }
/* 5-up workflow grid: 3 cols on tablets, 1 col on phones. 2-class selector
   so it beats the generic single-class .landing-how-grid mobile collapse. */
@media (max-width: 1150px) {
  .landing-how-grid.landing-how-grid-5 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 900px) {
  .landing-how-grid.landing-how-grid-5 { grid-template-columns: 1fr; }
  .landing-step:not(:last-child)::after { display: none; }
  .landing-showcase-tabs.landing-stepper { gap: 6px; }
}
.landing-how-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(59,130,246,0.18), rgba(59,130,246,0.06));
  border: 1px solid rgba(59,130,246,0.4);
  color: var(--accent);
  font-size: 22px;
  font-weight: 800;
  margin-bottom: 16px;
}
.landing-how-title {
  font-size: 17px;
  font-weight: 800;
  margin-bottom: 10px;
}
.landing-how-desc {
  font-size: 13.5px;
  color: var(--muted);
  line-height: 1.6;
  margin: 0 auto;
  max-width: 320px;
}

/* Pricing */
.landing-pricing {
  padding: 70px 5vw;
  max-width: 1080px;
  margin: 0 auto;
  text-align: center;
}
.landing-pricing-sub {
  color: var(--muted);
  margin: 0 auto 36px;
  font-size: 14px;
}
.landing-pricing-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
  max-width: 800px;
  margin: 0 auto;
  text-align: left;
}
.landing-plan {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 40px 32px;
  position: relative;
}
.landing-plan-pro {
  border-color: var(--accent);
  background: rgba(59,130,246,0.03);
}
.landing-plan-badge {
  position: absolute;
  top: -1px; left: 32px;
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.4px;
  padding: 5px 12px;
  border-radius: 0 0 6px 6px;
}
.landing-plan-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.4px;
}
.landing-plan-price {
  font-size: 42px;
  font-weight: 700;
  letter-spacing: -1.5px;
  margin: 14px 0 4px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.landing-plan-price span {
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
}
.landing-plan-sub {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 28px;
}
.landing-plan-features {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 14px;
  line-height: 2;
  color: var(--text);
}
.landing-plan-features li {
  padding-left: 22px;
  position: relative;
}
.landing-plan-features li::before {
  content: '→';
  color: var(--accent);
  font-weight: 600;
  position: absolute;
  left: 0;
}

/* Final CTA before footer */
.landing-final-cta {
  text-align: center;
  padding: 80px 5vw 60px;
  background: var(--surface);
  border-top: 1px solid var(--border);
}
.landing-final-head {
  font-size: clamp(22px, 2.8vw, 30px);
  font-weight: 800;
  letter-spacing: -0.5px;
  margin: 0 0 12px;
}
.landing-final-sub {
  color: var(--muted);
  margin: 0 0 28px;
  font-size: 14.5px;
}

/* Footer */
.landing-footer {
  padding: 30px 5vw 40px;
  max-width: 1180px;
  margin: 0 auto;
  text-align: center;
}
.landing-footer-row {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 10px;
}
.landing-footer-sep { opacity: 0.5; }
.landing-footer-links {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0 4px;
  margin-bottom: 14px;
}
.landing-footer-links a {
  color: var(--muted);
  text-decoration: none;
  transition: color 120ms ease;
}
.landing-footer-links a:hover { color: var(--text, #e6edf6); text-decoration: underline; }
.landing-footer-disclaimer {
  font-size: 11.5px;
  max-width: 900px;
  margin: 10px auto 0;
  line-height: 1.55;
}

/* "Back to home" link on non-landing auth views */
.auth-gate-back {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 12px;
  cursor: pointer;
  padding: 6px 10px;
  margin-top: 8px;
  border-radius: 6px;
  transition: color .15s, background .15s;
}
.auth-gate-back:hover { color: var(--text); background: var(--surface2); }

/* ── Mobile (≤720px) ── */
@media (max-width: 900px) {
  .landing-header { padding: calc(18px + env(safe-area-inset-top, 0)) 16px 18px; gap: 12px; }
  /* Smaller, denser sign-in button on phones — the desktop padding/
     font feels oversized next to the brand mark + BETA pill and was
     visually crowding the right edge. */
  .landing-signin-link {
    padding: 6px 12px;
    font-size: 13px;
  }
  .landing-hero { padding: 50px 18px 70px; }
  .landing-features,
  .landing-how,
  .landing-pricing { padding: 50px 18px; }
  .landing-final-cta { padding: 60px 18px 50px; }
  .landing-footer { padding: 24px 18px 36px; }

  .landing-features-grid,
  .landing-how-grid,
  .landing-pricing-grid,
  .landing-problem-grid,
  .landing-built-grid {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  .landing-plan-pro { order: -1; }   /* show Pro first on mobile */

  .landing-name { font-size: 16px; }
  .landing-logo { width: 32px; height: 32px; }

  /* Trust strip - stack on mobile */
  .landing-hero-trust {
    gap: 16px;
    padding: 18px 14px;
  }
  .landing-hero-trust-sep {
    display: none;     /* hide separators when wrapping */
  }
  .landing-hero-trust-item {
    flex: 0 0 calc(50% - 8px);
  }
  .landing-hero-trust-n { font-size: 22px; }

  /* Problem / built / FAQ sections */
  .landing-problem,
  .landing-built,
  .landing-faq { padding: 50px 18px; }
  .landing-problem-solution { padding: 28px 18px; }
}


/* ── Pro badge in header (sits next to "SwingMentalist") ── */

.pro-badge {
  /* Common pill geometry */
  display: inline-flex;
  align-items: center;
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.8px;
  padding: 3px 9px;
  border-radius: 10px;
  line-height: 1;
  margin-left: 6px;
  vertical-align: middle;
  white-space: nowrap;
}
.pro-badge-active {
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: #fff;
  box-shadow: 0 1px 4px rgba(245, 158, 11, 0.35);
}
.pro-badge-trial {
  background: rgba(59, 130, 246, 0.18);
  color: var(--accent);
  border: 1px solid rgba(59, 130, 246, 0.45);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
  /* Button reset */
  font-family: inherit;
}
.pro-badge-trial:hover {
  background: rgba(59, 130, 246, 0.30);
  border-color: var(--accent);
}


/* ── Welcome-to-Trial modal (opens once after first signup) ── */

.welcome-trial-card {
  /* Now displays the full 8-perk grid (2×4) so it wants more horizontal
     room than the previous 4-perk version. 820px ≈ matches the upgrade
     modal width so the two surfaces feel consistent. */
  width:      min(820px, 96vw) !important;
  max-width:  min(820px, 96vw) !important;
  max-height: min(940px, 94vh) !important;
  overflow-y: auto;
  padding: 48px 52px 36px !important;
  text-align: center;
}
.welcome-trial-burst {
  font-size: 52px;
  line-height: 1;
  margin-bottom: 8px;
  animation: welcome-pro-pop .6s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.welcome-trial-title {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.3px;
  margin: 6px 0 6px;
}
.welcome-trial-tag {
  font-size: 15px;
  color: var(--muted);
  line-height: 1.55;
  margin: 0 0 22px;
  max-width: 460px;
  margin-left: auto;
  margin-right: auto;
}

/* Big blue callout - what's the headline benefit */
.welcome-trial-callout {
  display: grid;
  grid-template-columns: 56px 1fr;
  align-items: center;
  gap: 16px;
  background: linear-gradient(135deg, rgba(59,130,246,0.10), rgba(59,130,246,0.02));
  border: 1px solid rgba(59, 130, 246, 0.45);
  border-radius: 12px;
  padding: 16px 18px;
  text-align: left;
  margin-bottom: 22px;
}
.welcome-trial-callout-icon {
  font-size: 32px;
  text-align: center;
  line-height: 1;
}
.welcome-trial-callout-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 3px;
}
.welcome-trial-callout-sub {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.5;
}

/* Section divider - matches the upgrade modal's style */
.welcome-trial-section-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 16px;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}
.welcome-trial-section-head::before,
.welcome-trial-section-head::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* 2x2 feature grid - same cells as the welcome-pro modal */
.welcome-trial-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 22px;
  text-align: left;
}

/* "After 14 days" disclosure - soft amber */
.welcome-trial-after {
  background: rgba(245, 158, 11, 0.08);
  border: 1px solid rgba(245, 158, 11, 0.3);
  border-radius: 8px;
  padding: 12px 16px;
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.6;
  text-align: left;
  margin-bottom: 20px;
}
.welcome-trial-after strong { color: var(--text); }

.welcome-trial-btn {
  width: 100%;
  padding: 14px 16px;
  font-size: 15px;
  font-weight: 700;
}

/* WelcomeBackModal action row - primary CTA + muted "continue free" */
.welcome-back-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 18px;
}


/* ── Welcome-to-Pro modal (opens once after a successful purchase) ── */

.welcome-pro-card {
  /* Override the .modal-card 380px default so the celebration has
     room to breathe. */
  width:      min(820px, 96vw) !important;
  max-width:  min(820px, 96vw) !important;
  max-height: min(860px, 94vh) !important;
  overflow-y: auto;
  padding: 48px 52px 36px !important;
  text-align: center;
}
.welcome-pro-burst {
  font-size: 56px;
  line-height: 1;
  margin-bottom: 8px;
  animation: welcome-pro-pop .6s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes welcome-pro-pop {
  from { transform: scale(0.3); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}
.welcome-pro-title {
  font-size: 24px;
  font-weight: 800;
  margin: 6px 0 6px;
}
.welcome-pro-tag {
  font-size: 15px;
  color: var(--muted);
  line-height: 1.55;
  margin: 0 0 22px;
}
.welcome-pro-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 20px;
  text-align: left;
}
.welcome-pro-cell {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 14px 12px;
}
.welcome-pro-cell-icon {
  font-size: 20px;
  margin-bottom: 6px;
  line-height: 1;
}
.welcome-pro-cell-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 4px;
}
.welcome-pro-cell-sub {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.4;
}
.welcome-pro-foot {
  font-size: 12px;
  color: var(--muted);
  margin: 0 0 16px;
}
.welcome-pro-btn {
  width: 100%;
  padding: 12px 16px;
  font-size: 15px;
  font-weight: 700;
}


/* ── Abort-scan button ──
   Same slot as "Run Scan" but contextual: red palette to signal
   destructive/cancel action while a scan is in-flight. */
.btn-abort {
  background: linear-gradient(135deg, #ef4444, #b91c1c) !important;
  color: #fff !important;
  border-color: rgba(239, 68, 68, 0.7) !important;
}
.btn-abort:hover { filter: brightness(1.08); }
.btn-abort:active { transform: scale(0.98); }


/* ── Free-tier scan-cap banner ──
   Sits above the results table when a scan was clipped to the free
   25-symbol limit. Click anywhere to open the upgrade modal. */

.scan-cap-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  margin: 10px 0;
  background: linear-gradient(90deg, rgba(245,158,11,0.10), rgba(245,158,11,0.04));
  border: 1px solid rgba(245, 158, 11, 0.40);
  border-radius: 8px;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.scan-cap-banner:hover {
  background: linear-gradient(90deg, rgba(245,158,11,0.18), rgba(245,158,11,0.06));
  border-color: rgba(245, 158, 11, 0.65);
}
.scan-cap-icon {
  font-size: 16px;
  line-height: 1;
  flex-shrink: 0;
}
.scan-cap-msg {
  flex: 1;
  font-size: 12.5px;
  color: var(--text);
  line-height: 1.5;
}
.scan-cap-msg strong {
  color: #f59e0b;
  font-weight: 700;
}
.scan-cap-cta {
  font-size: 12px;
  font-weight: 700;
  color: #f59e0b;
  white-space: nowrap;
  flex-shrink: 0;
}


/* ── Trade journal quota pill + locked rows ── */

/* Quota indicator next to "Log new trade" - colour shifts with usage:
   ok (<80%) → warn (≥80%) → max (at cap) → over (above cap). */
.trades-quota {
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface2);
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, border-color .15s, color .15s;
}
.trades-quota:hover { background: var(--surface); }
.trades-quota-ok    { /* default styling above */ }
.trades-quota-warn {
  border-color: rgba(245, 158, 11, 0.55);
  color: #f59e0b;
  background: rgba(245, 158, 11, 0.08);
}
.trades-quota-max,
.trades-quota-over {
  border-color: rgba(239, 68, 68, 0.55);
  color: var(--red);
  background: var(--red-bg);
}

/* "Log new trade" button when at-cap: still clickable (opens upgrade
   modal) but visually communicates locked state. */
.trades-new-btn-locked {
  background: linear-gradient(135deg, #f59e0b, #d97706) !important;
  color: #fff !important;
}
.trades-new-btn-locked:hover {
  filter: brightness(1.08);
}

/* Locked trade rows - collapsed to a single banner row with NO data
   visible. The actual <td> spans all columns; click anywhere on the
   row opens the upgrade modal. */
.trade-row-locked-row {
  cursor: pointer;
  background: rgba(245, 158, 11, 0.05);
  transition: background .15s;
}
.trade-row-locked-row:hover { background: rgba(245, 158, 11, 0.13); }
.trade-locked-cell {
  text-align: center;
  padding: 14px 16px !important;
  border-top: 1px dashed rgba(245, 158, 11, 0.45);
  border-bottom: 1px dashed rgba(245, 158, 11, 0.45);
}
.trade-locked-icon {
  font-size: 18px;
  margin-right: 10px;
  vertical-align: middle;
}
.trade-locked-text {
  font-size: 13px;
  color: var(--muted);
  vertical-align: middle;
}
.trade-locked-cta {
  margin-left: 14px;
  font-size: 13px;
  font-weight: 700;
  color: #f59e0b;
  vertical-align: middle;
}


/* ── Composite-history locked card (chart modal, free tier) ── */

.composite-history-locked {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  margin: 12px 0 4px;
  background: linear-gradient(90deg, rgba(245,158,11,0.10), rgba(245,158,11,0.03));
  border: 1px dashed rgba(245, 158, 11, 0.55);
  border-radius: 10px;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.composite-history-locked:hover {
  background: linear-gradient(90deg, rgba(245,158,11,0.18), rgba(245,158,11,0.05));
  border-color: rgba(245, 158, 11, 0.85);
}
.composite-history-locked-icon {
  font-size: 22px;
  line-height: 1;
  flex-shrink: 0;
}
.composite-history-locked-text {
  flex: 1;
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
}
.composite-history-locked-text strong { color: #f59e0b; font-weight: 700; }
.composite-history-locked-cta {
  font-size: 13px;
  font-weight: 700;
  color: #f59e0b;
  white-space: nowrap;
  flex-shrink: 0;
}


/* ── Inline locked-view placeholder for Pro-only tabs ── */

.pro-locked-view {
  max-width: 540px;
  margin: 80px auto 60px;
  padding: 36px 32px;
  text-align: center;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 14px;
}
.pro-locked-icon {
  font-size: 44px;
  line-height: 1;
  margin-bottom: 12px;
  opacity: 0.8;
}
.pro-locked-title {
  font-size: 24px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -0.3px;
  margin-bottom: 6px;
}
.pro-locked-tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: #fff;
  padding: 3px 10px;
  border-radius: 10px;
  margin-bottom: 14px;
}
.pro-locked-desc {
  font-size: 14px;
  color: var(--muted);
  line-height: 1.6;
  margin: 0 0 22px;
}
.pro-locked-btn {
  padding: 12px 22px;
  font-size: 14px;
  font-weight: 700;
}
.pro-locked-foot {
  font-size: 11.5px;
  color: var(--muted);
  margin: 18px 0 0;
}


/* ── Trial countdown banner + Upgrade modal (Pro subscription) ── */

.trial-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 8px 14px;
  background: linear-gradient(90deg, #2563eb22, #3b82f622);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  transition: background .15s ease;
}
.trial-banner:hover { background: linear-gradient(90deg, #2563eb33, #3b82f633); }
.trial-banner-urgent {
  background: linear-gradient(90deg, #ef444422, #f9731622);
  border-bottom-color: #ef4444;
}
.trial-banner-urgent:hover {
  background: linear-gradient(90deg, #ef444433, #f9731633);
}
.trial-banner-msg { color: var(--text); }
.trial-banner-cta {
  color: var(--accent);
  font-weight: 700;
}
.trial-banner-urgent .trial-banner-cta { color: #ef4444; }

/* The upgrade modal must outrank other modals that may have triggered
   it (e.g. the user clicked "Enable alerts" inside SettingsModal and
   the 402 response opened the upgrade modal). Without this z-index
   bump, the later-rendered modal in the tree would obscure us.
   Uses .modal-backdrop.upgrade-modal-backdrop (specificity 0,0,2,0)
   so it beats the base .modal-backdrop rule defined further down in
   this file regardless of source order. */
.modal-backdrop.upgrade-modal-backdrop { z-index: 1100; }

.upgrade-modal-card {
  /* The base .modal-card width is 380px which is way too tight for a
     full pricing surface. Also override .modal-card's max-height since
     pricing + features + sandbox notice want vertical room too.
     Viewport-relative so it scales smoothly across resolutions. */
  width:      min(1000px, 96vw) !important;
  max-width:  min(1000px, 96vw) !important;
  max-height: min(900px, 94vh) !important;
  overflow-y: auto;
  /* Generous padding so headlines, price cards, and features all breathe. */
  padding: 44px 56px 36px !important;
}
/* Centered header - calm and symmetrical at this width */
.upgrade-head {
  text-align: center;
  margin-bottom: 28px;
}
.upgrade-modal-card .modal-title {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.4px;
  margin-bottom: 6px;
  /* Cancel the global mobile rule that adds `padding-right: 48px` to
     leave room for the close-×. That makes the title visually
     left-shifted inside our centered upgrade-head - we'd rather the
     close-× overlap a few characters at the corner than break the
     centering of the entire heading. */
  padding-right: 0;
  text-align: center;
}
.upgrade-tag {
  font-size: 15px;
  color: var(--muted);
  line-height: 1.55;
  margin: 0;
  max-width: 540px;
  /* Center the line within the modal */
  margin-left: auto;
  margin-right: auto;
}

/* Two price cards laid out as a 2-col grid, capped to a comfortable
   centered max-width so they don't sprawl across the full 1000px modal. */
.upgrade-prices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  max-width: 900px;
  margin: 0 auto 30px;
}
/* Native-app "manage billing on the web" notice (replaces the in-app
   checkout cards on Android/iOS where store-billing policy applies). */
.upgrade-web-notice {
  max-width: 560px;
  margin: 0 auto 30px;
  text-align: center;
}
.upgrade-web-notice p {
  color: var(--muted);
  font-size: 14.5px;
  line-height: 1.65;
  margin: 0 0 18px;
}
.upgrade-web-notice strong { color: var(--text); }
.upgrade-price-card {
  position: relative;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 24px 22px 22px;
  text-align: center;
}

/* Section divider with horizontal rule on each side */
.upgrade-section-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 22px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}
.upgrade-section-head::before,
.upgrade-section-head::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* 2-column × 4-row feature grid - visually symmetric to the prices row */
.upgrade-features-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px 18px;
  margin-bottom: 24px;
}
.upgrade-feat {
  display: grid;
  grid-template-columns: 36px 1fr;
  align-items: start;
  gap: 4px 14px;
  padding: 14px 16px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.upgrade-feat-icon {
  grid-row: span 2;
  font-size: 22px;
  line-height: 1;
  align-self: center;
  text-align: center;
}
.upgrade-feat-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
}
.upgrade-feat-sub {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.45;
}

/* Sandbox note - subtle, centered */
.upgrade-sandbox-note {
  background: rgba(245, 158, 11, 0.08);
  border: 1px dashed rgba(245, 158, 11, 0.4);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 11.5px;
  color: var(--muted);
  text-align: center;
  margin: 4px 0 0;
}
.upgrade-sandbox-note strong { color: var(--text); }
.upgrade-sandbox-note code {
  background: var(--surface2);
  padding: 1px 5px;
  border-radius: 4px;
  font-family: 'Cascadia Code', Consolas, monospace;
}
/* When rendered as a <button> for click-to-subscribe - strip the
   browser's default chrome but keep the card visuals. */
.upgrade-price-button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  display: block;
  width: 100%;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.upgrade-price-button:hover:not(:disabled) {
  border-color: var(--accent);
  box-shadow: 0 4px 18px rgba(59,130,246,0.20);
  transform: translateY(-1px);
}
.upgrade-price-button:disabled {
  opacity: 0.6;
  cursor: progress;
}
.upgrade-price-cta {
  margin-top: 14px;
  color: var(--accent);
  font-weight: 700;
  font-size: 14px;
}
.upgrade-price-best .upgrade-price-cta { color: var(--accent); }
.upgrade-price-best {
  border-color: var(--accent);
  background: linear-gradient(180deg, rgba(59,130,246,0.10), rgba(59,130,246,0.02));
}
.upgrade-price-badge {
  position: absolute;
  top: -10px; left: 50%; transform: translateX(-50%);
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.5px;
  padding: 3px 8px;
  border-radius: 10px;
}
.upgrade-price-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 0.6px;
  text-transform: uppercase;
}
.upgrade-price {
  font-size: 32px;
  font-weight: 800;
  color: var(--text);
  margin: 8px 0 4px;
  font-variant-numeric: tabular-nums;
}
.upgrade-price span {
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
}
.upgrade-price-sub {
  font-size: 12px;
  color: var(--muted);
}
.upgrade-features {
  list-style: none;
  padding: 0;
  margin: 0 0 20px;
  font-size: 14px;
  line-height: 1.85;
}
.upgrade-features li {
  color: var(--text);
}
.upgrade-soon {
  background: var(--surface2);
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
  margin-bottom: 14px;
}
.upgrade-soon strong { color: var(--text); }
.upgrade-close {
  width: 100%;
  padding: 10px 14px;
}


.sym-link {
  font-weight: 700;
  font-size: 14px;
  color: var(--accent);
  text-decoration: none;
  letter-spacing: 0.3px;
  display: inline-block;
  vertical-align: middle;
  /* Used to be an <a>; now a <button> that opens our chart modal. Reset
     the browser's default button chrome so it visually matches the old
     link styling. */
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
}
.sym-link:hover { text-decoration: underline; }

/* Watchlist star button */
.star-btn {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px 0 0;
  margin: 0;
  width: 22px;
  display: inline-block;
  vertical-align: middle;
  transition: color .15s, transform .15s;
}
.star-btn:hover { color: var(--yellow); transform: scale(1.15); }
.star-btn.star-on { color: var(--yellow); }

/* Custom tickers textarea */
.custom-tickers-input {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 7px 10px;
  font-size: 13px;
  font-family: 'Cascadia Code', 'Consolas', monospace;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  outline: none;
  resize: vertical;
  transition: border-color .15s;
}
.custom-tickers-input:focus { border-color: var(--accent); }
.custom-tickers-hint {
  display: block;
  margin-top: 5px;
  font-size: 11px;
  color: var(--accent);
}

/* Active toggle state (Watchlist filter button when on) */
.btn-active {
  background: var(--accent) !important;
  color: #fff !important;
  border-color: var(--accent) !important;
}

/* ── Auth: login button, user badge, modal ── */
.btn-login {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  letter-spacing: 0.3px;
  transition: background .15s;
}
.btn-login:hover { background: var(--accent2); }

.user-badge {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text);
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 4px 4px 4px 12px;
}
.user-email {
  font-weight: 600;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.btn-logout {
  background: transparent;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 14px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s;
}
.btn-logout:hover { background: var(--surface3); color: var(--red); }

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  backdrop-filter: blur(4px);
}

.modal-card {
  position: relative;            /* anchor for absolutely-positioned close-X */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 28px 30px;
  width: min(380px, 92vw);
  /* Cap at 720px so tall content (Alerts tab) doesn't sprawl across the
     whole desktop viewport. 92vh otherwise — viewport-relative so the
     modal scales smoothly across phone-to-monitor without breakpoint
     math. Content scrolls internally via overflow-y below if it exceeds
     the cap. */
  max-height: min(720px, 92vh);
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}

/* Close-X overlay (mobile + desktop). Each modal opts in by including
   <button className="modal-close-x" onClick={onClose}>×</button>.
   On desktop it's a discreet corner button; at mobile widths the modal
   itself fills the screen so this is the primary way to dismiss. */
.modal-close-x {
  position: absolute;
  top: 10px;
  right: 12px;
  z-index: 2;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  transition: background .12s, color .12s;
}
.modal-close-x:hover  { color: var(--text); background: rgba(255,255,255,0.06); }
.modal-close-x:active { background: rgba(255,255,255,0.12); }
.modal-title {
  font-size: 18px;
  font-weight: 700;
  margin-bottom: 18px;
  color: var(--text);
}
/* ── Signup consent checkboxes ── */
.signup-consent {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 14px 0 16px;
  padding: 12px 14px;
  background: var(--surface2, rgba(255,255,255,0.03));
  border: 1px solid var(--border, rgba(255,255,255,0.08));
  border-radius: 8px;
}
.signup-consent-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text);
  cursor: pointer;
}
.signup-consent-item input[type="checkbox"] {
  flex-shrink: 0;
  margin-top: 2px;
  width: 16px;
  height: 16px;
  accent-color: var(--accent, #3b82f6);
  cursor: pointer;
}
.signup-consent-item a {
  color: var(--accent, #3b82f6);
  text-decoration: none;
}
.signup-consent-item a:hover { text-decoration: underline; }

.modal-error {
  background: var(--red-bg);
  color: var(--red);
  border: 1px solid rgba(239,68,68,0.3);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 12px;
  margin-bottom: 12px;
}
.modal-switch {
  width: 100%;
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 12px;
  margin-top: 12px;
  cursor: pointer;
  padding: 6px;
}
.modal-switch:hover { text-decoration: underline; }

.modal-card .field input {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 9px 12px;
  font-size: 14px;
  outline: none;
}
.modal-card .field input:focus { border-color: var(--accent); }

/* ── Full-screen login gate (no nav, no scanner until signed in) ── */
.auth-gate {
  position: fixed;
  inset: 0;
  background:
    radial-gradient(ellipse at top, rgba(59,130,246,0.15) 0%, transparent 60%),
    var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Centering uses auto margins on first/last children rather than
     `justify-content: center`. The trade-off: when content overflows
     the viewport (e.g. with the a11y "Large" / "Extra large" text-zoom
     modes), `justify-content: center` clips the top because there's
     nowhere to scroll *up* past the centered start. Auto margins
     collapse to 0 in that case so the form stacks from the top and the
     scroll bar (`overflow-y: auto` below) reveals everything. */
  justify-content: flex-start;
  gap: 32px;
  /* Status-bar inset on top (0 without a notch) since this is a fixed,
     full-screen surface that escapes any body padding. */
  padding: calc(24px + env(safe-area-inset-top, 0)) 24px 24px;
  overflow-y: auto;
  /* z-index 940 keeps the auth shell above any stray background content
     while sitting BELOW the accessibility FAB (950) and any modals
     (.modal-backdrop = 1000). Originally 2000, which hid the FAB. */
  z-index: 940;
}
.auth-gate > :first-child { margin-top: auto; }
.auth-gate > :last-child  { margin-bottom: auto; }
.auth-gate-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.auth-gate-title {
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.5px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
/* Closed-beta pill - sits to the right of "SwingMentalist". Renders
   only when the server reports beta_mode=true (BETA_DISABLE_OAUTH or
   BETA_CODES env vars set). */
.auth-gate-beta {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.5px;
  padding: 3px 8px;
  border-radius: 6px;
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: #fff;
  vertical-align: middle;
  box-shadow: 0 1px 4px rgba(245, 158, 11, 0.4);
}
.auth-gate-sub {
  font-size: 13px;
  color: var(--muted);
  margin-top: 4px;
}
.auth-gate-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 28px 30px;
  width: min(380px, 92vw);
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.auth-gate-card .modal-title {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: 18px;
  color: var(--text);
}
.auth-gate-card .field input {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 9px 12px;
  font-size: 14px;
  outline: none;
}
.auth-gate-card .field input:focus { border-color: var(--accent); }

/* Password policy checklist (live, in register mode) */
.pwd-checks {
  list-style: none;
  padding: 0;
  margin: 6px 0 0;
  font-size: 11px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-variant-numeric: tabular-nums;
}
.pwd-checks li        { transition: color .15s; }
.pwd-checks li.ok     { color: var(--green); }
.pwd-checks li.bad    { color: var(--muted); }

/* Inline match hint under "Repeat password" */
.pwd-hint-ok,
.pwd-hint-bad {
  display: block;
  margin-top: 5px;
  font-size: 11px;
  font-weight: 600;
}
.pwd-hint-ok  { color: var(--green); }
.pwd-hint-bad { color: var(--red); }

/* Disabled submit (when policy not met) - keep the Run button styling consistent */
.btn-run:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* ── My Presets (sidebar) ── */
.preset-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 6px;
}
.preset-row-saved {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px;
  transition: border-color .15s;
}
.preset-row-saved:hover { border-color: var(--accent); }
.preset-name {
  flex: 1;
  background: transparent;
  border: none;
  color: var(--text);
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  padding: 6px 8px;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.preset-del {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 16px;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  cursor: pointer;
}
.preset-del:hover { color: var(--red); background: var(--surface3); }

.preset-add-row {
  display: flex;
  gap: 4px;
  margin-top: 6px;
}
.preset-add-row input {
  flex: 1;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 6px 8px;
  font-size: 12px;
  outline: none;
}
.preset-add-row input:focus { border-color: var(--accent); }
.preset-add-row .btn-preset { padding: 6px 10px; }

.empty-hint {
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
  padding: 6px 2px;
}

/* ── Per-stock notes ── */
.note-btn {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  padding: 0 0 0 6px;
  margin: 0;
  width: 22px;
  display: inline-block;
  vertical-align: middle;
  opacity: .55;
  transition: opacity .15s, color .15s;
}
.note-btn:hover           { opacity: 1; }
.note-btn.note-on         { opacity: 1; color: var(--accent); }

.note-textarea {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 10px 12px;
  font-size: 13px;
  outline: none;
  font-family: 'Segoe UI', system-ui, sans-serif;
  resize: vertical;
  min-height: 100px;
}
.note-textarea:focus { border-color: var(--accent); }

/* ── Scan history panel (top of main area, collapsible) ── */
/* ─────────────────────────────────────────────────────────────────
   Scanner: Scan History panel (collapsible, above the results table)

   Section-card design with a sky-blue accent. Each prior run renders
   as a horizontal row-card: left meta block (timestamp + headline
   "N qualifying" stat), middle chip strip with the top tickers,
   right Load button. Reuses the visual language of the backtest
   form's section cards / saved-configs section.
   ───────────────────────────────────────────────────────────────── */

.scan-hist {
  --sec-r: 56;
  --sec-g: 189;
  --sec-b: 248;
  --sky-bg:   rgba(56, 189, 248, 0.06);
  --sky-bg2:  rgba(56, 189, 248, 0.12);

  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

/* Header bar (clickable to toggle) */
.scan-hist-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 12px 22px;
  background: linear-gradient(180deg, var(--surface2) 0%, var(--surface) 100%);
  border: none;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background 120ms ease;
}
.scan-hist-head:hover { background: var(--surface3); }
.scan-hist-head:focus-visible {
  outline: 2px solid rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.5);
  outline-offset: -2px;
}
.scan-hist-head-left {
  display: flex;
  align-items: center;
  gap: 10px;
}
.scan-hist-head-icon {
  color: var(--muted);
  font-size: 10px;
  width: 10px;
  text-align: center;
}
.scan-hist-head-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.scan-hist-head-count {
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
  font-size: 10.5px;
  font-weight: 800;
  padding: 2px 8px;
  border-radius: 999px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.scan-hist-head-preview {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.scan-hist-head-preview-l {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--muted);
  font-weight: 600;
}
.scan-hist-head-preview-v {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.2px;
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}

/* Body */
.scan-hist-body {
  display: flex;
  flex-direction: column;
  max-height: 380px;
  overflow-y: auto;
  border-top: 1px solid var(--border);
}

/* Empty state */
.scan-hist-empty {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 14px 18px;
  padding: 14px 16px;
  background: var(--surface2);
  border: 1px dashed var(--border);
  border-radius: 8px;
}
.scan-hist-empty-icon { font-size: 22px; line-height: 1; flex-shrink: 0; }
.scan-hist-empty-text {
  font-size: 12px;
  line-height: 1.55;
  color: var(--muted);
}
.scan-hist-empty-text strong { color: var(--text); }

/* Each row */
.scan-hist-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 20px;
  padding: 16px 22px 16px 28px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  transition: background 140ms ease;
}
.scan-hist-row:last-of-type { border-bottom: none; }
.scan-hist-row:hover {
  background: linear-gradient(90deg, var(--sky-bg) 0%, var(--surface2) 60%);
}

/* Colored left stripe */
.scan-hist-row-stripe {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}
.scan-hist-row-newest .scan-hist-row-stripe {
  box-shadow: 0 0 12px 0 rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}

/* Left column */
.scan-hist-row-info {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 0;
}
.scan-hist-row-toprow {
  display: flex;
  align-items: center;
  gap: 8px;
}
.scan-hist-row-time {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--muted);
  font-size: 11.5px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  font-weight: 600;
}
.scan-hist-row-newest-tag {
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1px;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

.scan-hist-row-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.scan-hist-chip {
  display: inline-flex;
  align-items: center;
  background: var(--surface3);
  color: var(--text);
  font-size: 11.5px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 5px;
  white-space: nowrap;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  border: 1px solid var(--border);
  letter-spacing: 0.3px;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.scan-hist-row:hover .scan-hist-chip {
  background: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.10);
  border-color: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.30);
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}

.scan-hist-row-mini {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
}
.scan-hist-mini {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
}
.scan-hist-mini-v {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 13px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -0.1px;
}
.scan-hist-mini-l {
  font-size: 10.5px;
  color: var(--muted);
  letter-spacing: 0.3px;
}

/* Hero column: oversized qualifying count */
.scan-hist-row-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  line-height: 1;
  min-width: 110px;
  padding-right: 4px;
}
.scan-hist-row-hero-trend {
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 2px;
  letter-spacing: -0.5px;
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}
.scan-hist-row-hero-val {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -1px;
  line-height: 1.05;
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}
.scan-hist-row-hero-lbl {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--muted);
  margin-top: 6px;
  font-weight: 700;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

/* Actions */
.scan-hist-row-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}
.scan-hist-row-load {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface3);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 8px 14px;
  border-radius: 7px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: all 140ms ease;
  white-space: nowrap;
}
.scan-hist-row-load:hover {
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  transform: translateY(-1px);
  box-shadow: 0 4px 12px -4px rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}
.scan-hist-row-load:active { transform: translateY(0); box-shadow: none; }
.scan-hist-row-load-icon {
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}

/* Footer */
.scan-hist-foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  font-size: 11px;
  color: var(--muted);
  background: var(--surface2);
  border-top: 1px solid var(--border);
  letter-spacing: 0.3px;
  font-weight: 500;
}
.scan-hist-foot-dot {
  display: inline-block;
  width: 5px;
  height: 5px;
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-radius: 50%;
  box-shadow: 0 0 6px 0 rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}

/* Mobile */
@media (max-width: 760px) {
  .scan-hist-row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "info  hero"
      "actions actions";
    gap: 14px;
    padding: 16px 18px 16px 22px;
  }
  .scan-hist-row-info    { grid-area: info; }
  .scan-hist-row-hero    { grid-area: hero; min-width: 100px; }
  .scan-hist-row-hero-val { font-size: 24px; }
  .scan-hist-row-actions { grid-area: actions; justify-content: flex-end; }
  .scan-hist-row-mini    { flex-wrap: wrap; }
  .scan-hist-head-preview { display: none; }
  .scan-hist-head { padding: 12px 14px; }
}


/* ── Settings modal: wider card, tabs, danger zone ── */
/* The Settings modal got a sixth tab (Billing) which makes the
   previous 440px width too narrow - the tab bar overflowed and
   tabs ran into each other. Bump to 580px on desktop so all six
   tabs fit comfortably; mobile already takes 100vw via the media
   query so this doesn't affect phones. */
.modal-wide { width: min(580px, 94vw); }

.modal-success {
  background: var(--green-bg);
  color: var(--green);
  border: 1px solid rgba(34,197,94,0.3);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 12px;
  margin-bottom: 12px;
}

.tab-bar {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 18px;
  flex-wrap: nowrap;
  /* Six tabs now (Password / Trading / Preferences / Billing / Alerts
     / Danger zone). They share the modal's width evenly via flex: 1
     on .tab. If the content STILL overflows on very narrow displays,
     the bar scrolls horizontally rather than wrapping into two rows
     (cleaner look). */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Hide the horizontal scrollbar that would otherwise clip the
     bottom border. The content remains swipeable on touch. */
  scrollbar-width: none;
}
.tab-bar::-webkit-scrollbar { display: none; }
/* On phones the 6 tab labels (Password / Trading / Preferences / Billing
   / Alerts / Danger zone) need ~340 px in one row, more than the ~310 px
   available inside the modal — so the bar scrolls horizontally and the
   last tabs become invisible (user reported "Alert" cut and "Danger
   zone" missing). Switch to a grid that wraps to multiple rows so every
   tab is visible without scrolling. Each cell auto-fits a minimum of
   95 px → 3 columns × 2 rows on a typical phone, 4+2 on a wider tablet,
   6 columns (single row) at 720 px+. */
@media (max-width: 900px) {
  .tab-bar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(95px, 1fr));
    gap: 4px;
    overflow-x: visible;
    /* The bottom border is the visual underline track. Keep it. */
  }
  .tab-bar .tab {
    flex: initial;
    min-width: 0;
    padding: 8px 4px;
  }
}
.tab {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  padding: 8px 6px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color .15s, border-color .15s;
  white-space: nowrap;
  flex: 1 1 auto;
  text-align: center;
  /* Minimum tab width so flex doesn't squeeze short labels (Billing)
     into half the size of long ones (Preferences / Danger zone). */
  min-width: 72px;
}
.tab:hover            { color: var(--text); }
.tab-active           { color: var(--accent); border-bottom-color: var(--accent); }
.tab-danger.tab-active { color: var(--red);    border-bottom-color: var(--red); }

.danger-box {
  background: var(--red-bg);
  border: 1px solid rgba(239,68,68,0.3);
  border-radius: 6px;
  padding: 12px 14px;
  margin-bottom: 16px;
  font-size: 12px;
  color: var(--text);
}
.danger-box strong { color: var(--red); display: block; margin-bottom: 4px; }
.danger-box p      { color: var(--muted); margin: 0; line-height: 1.5; }
.danger-box code   { background: var(--surface3); padding: 1px 5px; border-radius: 3px; font-size: 11px; color: var(--red); }

/* Trading-tab live preview of $ at risk */
.trade-preview {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--green-bg);
  border: 1px solid rgba(34,197,94,0.3);
  border-radius: 6px;
  padding: 10px 14px;
  margin: 6px 0 14px;
  font-size: 13px;
}
.trade-preview-lbl {
  color: var(--muted);
  font-weight: 500;
}
.trade-preview-val {
  font-family: 'Cascadia Code', Consolas, monospace;
  font-weight: 700;
  color: var(--green);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}

.btn-danger {
  width: 100%;
  padding: 13px;
  margin-top: 6px;
  background: var(--red);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  letter-spacing: 0.2px;
  transition: background .15s, opacity .15s;
}
.btn-danger:hover:not(:disabled) { background: #dc2626; }
.btn-danger:disabled              { opacity: .45; cursor: not-allowed; }

.modal-card .field code {
  font-family: 'Cascadia Code', 'Consolas', monospace;
  background: var(--surface3);
  padding: 1px 6px;
  border-radius: 3px;
}

.modal-switch-muted { color: var(--muted) !important; font-size: 11px; }
.modal-switch-muted:hover { color: var(--accent) !important; }

/* ── Sparkline (in table row) ── */
.sparkline {
  display: block;
  transition: filter .15s;
}
/* Area-fill colour matches the line, so the colour-blind palette can
   re-tint both via --candle-up / --candle-down without touching the JSX.
   We can't put alpha on a CSS var directly, so we layer a colored shape
   under the line via opacity. */
.sparkline.spark-fill-up   .spark-area { fill: var(--candle-up,   #22c55e); opacity: .12; }
.sparkline.spark-fill-down .spark-area { fill: var(--candle-down, #ef4444); opacity: .12; }
.spark-btn {
  background: transparent;
  border: none;
  padding: 2px 4px;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.spark-btn:hover {
  background: var(--surface3);
}
.spark-btn:hover .sparkline {
  filter: brightness(1.25);
}
.spark-empty {
  color: var(--muted);
  font-size: 11px;
}

/* ── Chart modal ── */
.modal-chart-card {
  /* Modal sizing is viewport-relative: always 92% of the actual
     viewport, capped at 1200×960 on big monitors so the modal doesn't
     grow absurdly large on 4K displays where 92% would be 3500+ px
     wide. This replaces a tangle of media queries + pixel + calc()
     math with two lines that respond smoothly to ANY screen size —
     phone, laptop, 4K monitor, ultrawide — without breakpoints. */
  width: min(92vw, 1200px);
  max-height: 92vh;
}

/* ── Full-page chart view ── */
/* Override the capped sizing so the chart fills the viewport. !important
   beats the responsive zoom-scaled width rules in the media query below. */
.modal-chart-card.is-fullscreen {
  width: 100vw !important;
  max-width: 100vw !important;
  height: 100vh;
  max-height: 100vh !important;
  border-radius: 0;
  zoom: 1 !important;
}
.modal-fullscreen-x {
  position: absolute;
  top: 10px;
  right: 56px;            /* sits just left of the × close button */
  z-index: 2;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color .12s, background .12s;
}
.modal-fullscreen-x:hover  { color: var(--text); background: rgba(255,255,255,0.06); }
.modal-fullscreen-x:active { background: rgba(255,255,255,0.12); }

/* On laptop+desktop screens between 721 px and 1920 px, proportionally
   shrink the entire modal by 15% via CSS zoom. Every internal element
   — chart, alerts, news, notes, title, headers, padding, text — scales
   together, so proportions are preserved exactly. The viewport-unit
   dimensions are inflated by 1/zoom so the modal's VISIBLE size stays
   at the same ~92 % of the viewport after zoom is applied.

   The `min-width: 901px` floor is critical — on phones and tablet-
   portrait the modal is already tight, and an additional 0.85× zoom
   compounds with the small viewport to make everything unreadable.
   Those widths get the un-zoomed sizing + the dedicated mobile rules
   below (the mobile layout now spans up to 900px to cover iPad
   portrait). */
@media (min-width: 901px) and (max-width: 1920px) {
  .modal-chart-card {
    zoom: 0.85;
    width: min(calc(92vw / 0.85), calc(1200px / 0.85));
    max-height: calc(92vh / 0.85);
  }
}

/* Mobile-specific chart-modal compacting (≤720 px) — the chart modal
   is the densest UI surface in the app (title + interval toggles +
   alerts/news/notes panels + price info + toolbar + chart + nav arrows
   + close). On phones the user wants to SEE the chart, not navigate a
   wall of toolbars before they reach it. Tighten everything so the
   chart is visible above the fold. */
@media (max-width: 900px) {
  .modal-chart-card {
    /* Use full viewport on phones — there's no benefit to a margin on
       a 375 px screen, and every saved pixel goes into the chart. */
    width: 100vw;
    max-height: 100vh;
    max-width: 100vw;
    border-radius: 0;
    padding: 12px 10px;
    /* Become a vertical flex container so children can be reordered
       via `order:` below — chart goes first, panels move below. */
    display: flex;
    flex-direction: column;
  }
  /* Source-order on mobile:
       title → mode toggle → interval toggle → alerts (price-alerts-bar) →
       news → notes → chart-stage → footer with Close button
     What the user actually wants to see first on a phone: chart.
     Every flex child needs an explicit `order` — anything that falls
     back to default `order: 0` floats above items with order: 1+. */
  .modal-chart-card .modal-title           { order: 1; }
  .modal-chart-card .chart-mode-toggle,
  .modal-chart-card .chart-interval-toggle { order: 2; }
  .modal-chart-card .chart-stage           { order: 3; }
  .modal-chart-card .price-alerts-bar      { order: 4; }
  .modal-chart-card .news-bar              { order: 5; }
  .modal-chart-card .notes-bar             { order: 6; }
  .modal-chart-card .chart-modal-footer    { order: 7; }
  /* Close-X stays in its absolute position regardless of flex order. */

  /* The two toggles use `margin-left: auto` on desktop to push them to
     the right of the title row. In a flex column that becomes "stick
     to the right edge", which looks lopsided next to the centered 1D/
     1W/4H/Multi toggle. Reset both and centre them as standalone rows
     so they stack symmetrically below the title. */
  .modal-chart-card .chart-mode-toggle,
  .modal-chart-card .chart-interval-toggle {
    margin-left: 0;
    margin-right: 0;
    align-self: center;
    margin-top: 4px;
  }
}

/* Toolbar icons-only on phones — the chart toolbar is 7 buttons + 2
   separators + color palette. With labels each button is ~70-90 px;
   labels-off they shrink to ~36 px which fits 4-5 per row instead of
   spilling over multiple lines. The button's `title=` attribute is
   preserved so users on touch devices still get the function name on
   long-press. */
@media (max-width: 900px) {
  .tool-btn-label { display: none; }
  .tool-btn { padding: 5px 8px; font-size: 14px; }
  .chart-toolbar { gap: 3px; padding: 6px 0; }
  .tool-sep { margin: 0 3px; }
}

/* ── A11y text-scale override — applies to ALL modals ─────────────
   The accessibility text-size widget applies `zoom` to <html>: 0.9
   (small), 1.15 (large), 1.30 (extra large). Every declared dimension
   gets multiplied visually, so a `max-height: 92vh` modal becomes
   `92 × 1.30 = 119.6vh` visible — overflows the viewport and the
   centered modal clips its close-X + bottom buttons.

   Generic cap on `.modal-card` itself catches every modal at once
   (settings, scoring guide, stats, upgrade, welcome, etc.) — the
   per-modal width / max-height declarations stay in effect, this just
   adds a tighter `max-width` / `max-height` ceiling so the visible
   modal fits. Specificity of `html.a11y-text-* .modal-card` (0,2,1)
   beats per-modal `.welcome-pro-card !important` etc. (0,1,0), so the
   cap wins even when individual modals use !important. */
html.a11y-text-lg .modal-card { max-width: 80vw !important; max-height: 80vh !important; }
html.a11y-text-xl .modal-card { max-width: 70vw !important; max-height: 70vh !important; }

/* ── A11y text-scale override — chart-modal specifics ─────────────
   The chart modal needs its own override (placed AFTER the generic
   rule above so it wins at equal specificity) because:

   1. The modal's own `zoom: 0.85` (from the media query above) would
      compose with html's zoom and break sizing. Reset to `zoom: 1`.
   2. The viewport units are still in CSS-pixel coordinate space, so
      `92vh` declared becomes `92 × html-zoom` % visible. Shrink the
      base percentage per mode so the modal lands inside the viewport
      after html zoom — otherwise the centered modal pushes past the
      viewport edges and clips the close-X + bottom buttons. */
html.a11y-text-sm .modal-chart-card,
html.a11y-text-lg .modal-chart-card,
html.a11y-text-xl .modal-chart-card {
  zoom: 1 !important;
}
/* sm (0.9): default 92vh becomes 82.8 % visible — already fits. */
html.a11y-text-sm .modal-chart-card {
  width: min(92vw, 1200px) !important;
  max-height: 92vh !important;
}
/* lg (1.15): 92 / 1.15 ≈ 80, leaves ~8 % gutter total after html zoom. */
html.a11y-text-lg .modal-chart-card {
  width: min(80vw, 1200px) !important;
  max-height: 80vh !important;
}
/* xl (1.30): 92 / 1.30 ≈ 70, same 8 % gutter logic. */
html.a11y-text-xl .modal-chart-card {
  width: min(70vw, 1200px) !important;
  max-height: 70vh !important;
}

/* Timeframe toggle (1D / 1W / 4H) - same look as the Line/Candles toggle */
.chart-interval-toggle .mode-btn {
  font-family: 'Cascadia Code', Consolas, monospace;
  font-weight: 700;
  letter-spacing: 0.4px;
  min-width: 40px;
}
.modal-chart-card .modal-title {
  display: flex;
  align-items: center;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.3px;
}
.chart-summary {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.chart-price {
  font-size: 22px;
  font-weight: 800;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.chart-change {
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* "Today's move" pill - slightly larger + bolder than the 6mo metric
   since it's the more actionable number at-a-glance. */
.chart-day {
  font-size: 14px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--surface2);
  border: 1px solid var(--border);
}
.price-chart {
  display: block;
  width: 100%;
  height: auto;
  background: var(--bg);
  border-radius: 6px;
  margin: 6px 0;
}
.chart-loading {
  padding: 60px 20px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

/* ── Price-alerts bar (in ChartModal, below the title row) ──────────────
   Compact, collapsible. Same horizontal padding as the title so the bar
   visually lines up with the chart column below it. */

.price-alerts-bar {
  margin: 0 50px 10px;
  padding: 6px 10px;
  background: var(--panel, rgba(255, 153, 0, 0.06));
  border: 1px solid rgba(249, 115, 22, 0.25);   /* match the on-chart line */
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.price-alerts-bar.is-open {
  padding-bottom: 10px;
}

.alerts-toggle {
  background: transparent;
  border: none;
  color: var(--text);
  font: 600 12px/1.3 inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  /* Full-width so clicking ANYWHERE on the bar row toggles it, not just
     the text. The caret sits at the right edge via space-between. */
  width: 100%;
  align-self: stretch;
  justify-content: space-between;
  gap: 6px;
  padding: 2px 0;
}
.alerts-toggle:hover { color: #f97316; }
.alerts-toggle-caret {
  font-size: 10px;
  opacity: 0.7;
}

.alerts-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
}
.alert-chip {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 4px 1px 6px;
  background: rgba(249, 115, 22, 0.15);
  border: 1px solid rgba(249, 115, 22, 0.45);
  color: #f97316;
  border-radius: 10px;
  font: 600 10px/1.3 'Cascadia Code', Consolas, monospace;
}
.alert-chip-x {
  background: transparent;
  border: none;
  color: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
  margin-left: 2px;
  opacity: 0.7;
}
.alert-chip-x:hover { opacity: 1; }
.alerts-more {
  font: 600 10px/1.3 inherit;
  color: var(--muted);
}

/* Open panel */
.alerts-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.alerts-create-row {
  display: flex;
  gap: 6px;
  align-items: stretch;
  flex-wrap: wrap;
}
.alerts-dir-toggle {
  display: inline-flex;
  background: rgba(0,0,0,0.18);
  border-radius: 4px;
  padding: 2px;
  gap: 2px;
}
.alerts-dir-toggle .mode-btn {
  font-size: 11px;
  padding: 4px 8px;
}
.alerts-price-input,
.alerts-note-input {
  background: var(--surface);
  border: 1px solid var(--border, rgba(255,255,255,0.15));
  color: var(--text);
  border-radius: 4px;
  padding: 4px 8px;
  font: 600 12px/1.3 'Cascadia Code', Consolas, monospace;
}
.alerts-price-input { width: 90px; }
.alerts-note-input { flex: 1; min-width: 120px; font-weight: 400; }
.alerts-add-btn {
  /* Filled orange — same colour language as the dashed alert lines on
     the chart, so the user understands "I press this, an orange line
     appears." Solid background + bold text reads as the primary action
     in the row even next to two input fields. */
  padding: 6px 16px;
  background: #f97316;
  color: #fff;
  border: 1px solid #f97316;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: background 0.12s ease, transform 0.08s ease;
}
.alerts-add-btn:hover:not(:disabled) {
  background: #ea580c;          /* orange-600 — slightly darker on hover */
  border-color: #ea580c;
}
.alerts-add-btn:active:not(:disabled) { transform: translateY(1px); }
.alerts-add-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  background: rgba(249, 115, 22, 0.4);
  border-color: rgba(249, 115, 22, 0.4);
}

.alerts-empty {
  font: 400 11px/1.4 inherit;
  color: var(--muted);
  padding: 4px 2px;
}

.alerts-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 140px;
  overflow-y: auto;
}
.alerts-row {
  display: grid;
  grid-template-columns: 14px 70px 1fr auto 18px;
  align-items: center;
  gap: 8px;
  padding: 3px 4px;
  font: 500 11px/1.3 inherit;
  border-radius: 3px;
}
.alerts-row:hover { background: rgba(255,255,255,0.04); }
.alerts-row-arrow { color: #f97316; font-weight: 700; }
.alerts-row-price {
  font-family: 'Cascadia Code', Consolas, monospace;
  font-weight: 700;
  color: var(--text);
}
.alerts-row-note {
  color: var(--muted);
  font-size: 11px;
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.alerts-row-status {
  font-size: 10px;
  white-space: nowrap;
}
.alerts-status-active     { color: var(--muted); }
.alerts-status-triggered  { color: #22c55e; font-weight: 600; }
.alerts-status-cancelled  { color: var(--muted); opacity: 0.55; }
.alerts-row-cancel {
  background: transparent;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 14px;
  padding: 0;
  line-height: 1;
}
.alerts-row-cancel:hover { color: #ef4444; }
.alerts-row-cancelled .alerts-row-price,
.alerts-row-cancelled .alerts-row-arrow {
  opacity: 0.45;
  text-decoration: line-through;
}

/* On narrow screens the bar still needs to read cleanly. */
@media (max-width: 640px) {
  .price-alerts-bar { margin-left: 14px; margin-right: 14px; }
  .alerts-row { grid-template-columns: 14px 60px 1fr auto 18px; }
  .alerts-price-input { width: 76px; }
}

/* ── News panel (in ChartModal, below the alerts bar) ──────────────────
   Same horizontal padding as the title + alerts bars so all three line
   up with the chart column. Collapsible single-row header that expands
   into a list of compact news cards (thumbnail + title + source/time). */

.news-bar {
  margin: 0 50px 10px;
  padding: 6px 10px;
  background: var(--panel, rgba(96, 165, 250, 0.04));
  border: 1px solid rgba(96, 165, 250, 0.20);   /* soft blue */
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.news-bar.is-open { padding-bottom: 8px; }

.news-toggle {
  background: transparent;
  border: none;
  color: var(--text);
  font: 600 12px/1.3 inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  /* Full-width so the whole bar row is clickable (caret right via space-between). */
  width: 100%;
  align-self: stretch;
  justify-content: space-between;
  gap: 6px;
  padding: 2px 0;
}
.news-toggle:hover { color: #60a5fa; }
.news-toggle-caret { font-size: 10px; opacity: 0.7; margin-left: 2px; }

.news-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 260px;
  overflow-y: auto;
}
.news-loading {
  font: 400 11px/1.4 inherit;
  color: var(--muted);
  padding: 4px 2px;
}
.news-item {
  /* Plain block — was `display: flex; overflow: hidden;` as scaffolding
     for the (now removed) inline body expansion. With overflow:hidden
     the right end of the meta row got clipped on rows where the title
     was long, which hid the date and time-ago span on tickers like MSFT
     ("Mayo Clinic and Microsoft collaborate to develop a frontier AI…"). */
  display: block;
  background: var(--surface, rgba(255,255,255,0.02));
  border: 1px solid var(--border, rgba(255,255,255,0.06));
  border-radius: 5px;
  transition: border-color 0.15s ease;
}
.news-item:hover { border-color: rgba(96, 165, 250, 0.45); }

.news-link {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 8px 10px;
  cursor: pointer;
  font: inherit;
  color: var(--text);
  transition: background 0.12s ease;
}
.news-link:hover { background: rgba(96, 165, 250, 0.06); }

.news-text { min-width: 0; flex: 1; }
.news-title {
  font: 600 12.5px/1.4 inherit;
  color: var(--text);
  margin-bottom: 3px;
}
.news-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;       /* date/time/read drop to next line before being clipped */
  row-gap: 3px;
  gap: 4px;
  font: 500 10px/1.2 inherit;
  color: var(--muted);
}
.news-source {
  color: #60a5fa;
  font-weight: 600;
  white-space: nowrap;
}
.news-dot { opacity: 0.6; }
.news-time { white-space: nowrap; }
.news-date {
  white-space: nowrap;
  color: var(--text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.news-expand-hint {
  color: #60a5fa;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ── News-detail modal ────────────────────────────────────────────────
   Opens over the chart modal when the user clicks a headline. Wider,
   taller, with comfortable reading typography — none of the chart-bar
   constraints. */

.news-detail-backdrop {
  /* One layer above the chart modal (which uses z-index 1000). */
  z-index: 1050;
}
.news-detail-card {
  width: min(820px, 96vw);
  max-width: 820px;
  max-height: min(90vh, 900px);
  padding: 36px 44px 30px;
  /* Override .modal-card's 380px width without fighting specificity. */
}

.news-detail-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 500 11px/1 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--muted);
  margin-bottom: 10px;
}
.news-detail-source {
  color: #60a5fa;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10.5px;
}
.news-detail-date {
  font-variant-numeric: tabular-nums;
}

.news-detail-title {
  font: 700 22px/1.3 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--text);
  margin: 0 0 18px;
  letter-spacing: -0.01em;
}

/* Sanitized HTML body. Optimized for READING: generous line-height,
   comfortable measure, clear paragraph spacing, no width-fighting
   between the chart bar and the article. */
.news-detail-body {
  font: 400 15px/1.65 'Segoe UI', Georgia, serif;
  color: var(--text);
  /* Cap measure for readability — anything wider than ~75 chars at this
     font size starts to fatigue the eye. */
  max-width: 68ch;
  margin: 0 auto;
}
.news-detail-body p  { margin: 0 0 14px; }
.news-detail-body h3, .news-detail-body h4 {
  font-weight: 700;
  margin: 18px 0 6px;
  font-size: 1.05em;
}
.news-detail-body ul,
.news-detail-body ol { margin: 6px 0 14px 22px; padding: 0; }
.news-detail-body li { margin: 4px 0; }
.news-detail-body b,
.news-detail-body strong { font-weight: 700; }
.news-detail-body a {
  color: #60a5fa;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.news-detail-body a:hover { color: #93c5fd; }

.news-detail-empty {
  font: 500 13px/1.5 inherit;
  color: var(--muted);
  text-align: center;
  padding: 40px 0;
}

@media (max-width: 640px) {
  .news-detail-card {
    width: 100vw;
    max-width: 100vw;
    max-height: 100vh;
    border-radius: 0;
    padding: 24px 18px 22px;
  }
  .news-detail-title { font-size: 18px; }
  .news-detail-body  { font-size: 14.5px; }
}

@media (max-width: 640px) {
  .news-bar { margin-left: 14px; margin-right: 14px; }
  .news-list { max-height: 220px; }
}

/* ── Multi-timeframe stacked view ─────────────────────────────────────
   Three compact PriceCharts (1W / 1D / 4H) stacked vertically. Each
   row has its own small TF label badge on the left. No per-chart
   toolbar — drawings/alerts read from parent state so they render on
   every chart automatically. */

.multi-tf-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* Scroll inside the modal when 3×260 + labels + gaps exceed the
     modal's available height (small laptops, ultrawide-but-short
     screens). The outer modal-chart-card already has overflow:auto;
     this just gives the multi stack its own bounded box so the chart
     labels stay visible while you swipe through them. */
  max-height: calc(min(960px, 100vh - 60px) - 220px);
  overflow-y: auto;
  padding-right: 4px;       /* room for the scrollbar without clipping */
}
.multi-tf-row {
  position: relative;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--border, rgba(255,255,255,0.06));
  border-radius: 6px;
  padding: 8px 6px 4px;
  flex-shrink: 0;           /* never compress when the stack overflows */
}
.multi-tf-label {
  position: absolute;
  top: 6px;
  left: 10px;
  z-index: 2;
  background: var(--surface, #1a1d24);
  color: var(--accent);
  font: 700 10px/1 'Cascadia Code', Consolas, monospace;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 7px;
  border-radius: 3px;
  border: 1px solid rgba(99, 102, 241, 0.35);
  pointer-events: none;
}
.multi-tf-loading {
  height: 260px;            /* matches the real chart height so the layout
                               doesn't reflow when data lands */
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font: 500 12px/1.4 inherit;
}

/* In compact mode the price-chart fills its slot — no summary/toolbar
   strip eating vertical space. */
.price-chart-compact { /* hook for any future compact-specific tuning */ }

@media (max-width: 640px) {
  .multi-tf-label { font-size: 9px; padding: 3px 5px; }
}

/* ── Notes panel (chart modal, below the news bar) ──────────────────── */

.notes-bar {
  margin: 0 50px 10px;
  padding: 6px 10px;
  background: var(--panel, rgba(168, 85, 247, 0.04));
  border: 1px solid rgba(168, 85, 247, 0.20);   /* soft purple */
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.notes-bar.is-open { padding-bottom: 10px; }

.notes-toggle {
  background: transparent;
  border: none;
  color: var(--text);
  font: 600 12px/1.3 inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  /* Full-width so the whole bar row is clickable, not just the text.
     The caret stays right-aligned via its margin-left:auto. */
  width: 100%;
  align-self: stretch;
  text-align: left;
  /* When the preview text is long, ellipsis the row instead of wrapping
     to keep the closed state one line tall. */
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notes-toggle:hover { color: #a855f7; }
.notes-toggle-caret { font-size: 10px; opacity: 0.7; margin-left: auto; flex-shrink: 0; }

.notes-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.notes-body {
  font: 400 13px/1.55 'Segoe UI', system-ui, sans-serif;
  color: var(--text);
  background: rgba(168, 85, 247, 0.05);
  border: 1px solid rgba(168, 85, 247, 0.14);
  border-radius: 5px;
  padding: 10px 12px;
  white-space: pre-wrap;          /* keep user newlines */
  word-wrap: break-word;
  max-height: 220px;
  overflow-y: auto;
}
.notes-empty {
  font: 400 12px/1.5 inherit;
  color: var(--muted);
  padding: 4px 2px 0;
}

.notes-edit-btn {
  align-self: flex-start;
  background: transparent;
  border: 1px solid rgba(168, 85, 247, 0.4);
  color: #a855f7;
  border-radius: 4px;
  padding: 4px 12px;
  font: 600 12px/1.2 inherit;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.notes-edit-btn:hover {
  background: rgba(168, 85, 247, 0.12);
  border-color: rgba(168, 85, 247, 0.6);
}

.notes-textarea {
  width: 100%;
  background: var(--surface, #1a1d24);
  border: 1px solid rgba(168, 85, 247, 0.35);
  border-radius: 5px;
  color: var(--text);
  font: 400 13px/1.55 'Segoe UI', system-ui, sans-serif;
  padding: 10px 12px;
  resize: vertical;
  min-height: 100px;
  outline: none;
  box-sizing: border-box;
}
.notes-textarea:focus { box-shadow: 0 0 0 3px rgba(168,85,247,0.18); }
.notes-textarea:disabled { opacity: 0.65; }

.notes-edit-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}
.notes-char-count {
  font: 500 11px/1 inherit;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.notes-edit-actions {
  display: inline-flex;
  gap: 6px;
}
.notes-save {
  background: #a855f7;
  color: #fff;
  border: 1px solid #a855f7;
  border-radius: 4px;
  padding: 5px 16px;
  font: 700 12px/1.2 inherit;
  cursor: pointer;
  transition: background 0.12s ease;
}
.notes-save:hover:not(:disabled) { background: #9333ea; border-color: #9333ea; }
.notes-save:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: rgba(168, 85, 247, 0.4);
  border-color: rgba(168, 85, 247, 0.4);
}
.notes-cancel.btn-preset {
  padding: 5px 14px;
  font-size: 12px;
}

@media (max-width: 640px) {
  .notes-bar { margin-left: 14px; margin-right: 14px; }
}

/* ── ChartModal title bar - single clean row ── */

.chart-modal-title {
  display: flex;
  align-items: center;
  gap: 12px;
  /* Override the default .modal-title bottom margin so the row sits tight */
  margin-bottom: 14px !important;
  /* Inset the header to line up with .chart-stage-inner below - the chart
     column sits at (arrow width 38px + flex gap 12px) = 50px from each edge
     of the modal. The RIGHT side reserves extra room (100px) so the
     timeframe toggles never run under the two top-right corner buttons
     (full-page ⛶ at right:56 + close × at right:12). */
  padding: 0 100px 0 50px;
}

/* The middle "NVDA  3/50  6mo · 30d composite" group - takes remaining space */
.chart-modal-sym {
  flex: 1;
  display: flex;
  align-items: center;     /* center vertically - baseline made small text sit low */
  gap: 10px;
  min-width: 0;            /* allow ellipsis if very narrow */
  overflow: hidden;
}
.chart-sym-name {
  font-size: 22px;
  font-weight: 800;
  color: var(--accent);
  letter-spacing: -0.4px;
  flex-shrink: 0;
}
.chart-nav-pos {
  font-size: 10px;
  color: var(--accent);
  font-weight: 700;
  background: rgba(59,130,246,0.12);
  border: 1px solid rgba(59,130,246,0.25);
  padding: 3px 9px;
  border-radius: 10px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.5px;
  flex-shrink: 0;
}
/* Composite score badge next to the symbol — reuses the CompositeCell
   (compact) so the colour/percentile styling matches the scanner table. */
.chart-composite-badge {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  /* Size to content (number + bar + "Top X%" badge) rather than a fixed
     84px — the percentile pill ("Top 5%", "Top 25%") was overflowing the
     fixed width and getting clipped by .chart-modal-sym's overflow:hidden. */
  width: auto;
}
.chart-composite-badge .composite-wrap { width: auto; }

.chart-modal-sub {
  font-size: 11px;
  color: var(--muted);
  font-weight: 400;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Chart stage - flexbox row of [prev arrow][chart column][next arrow].
   The chart column (.chart-stage-inner) holds BOTH PriceChart and the
   composite-over-time chart, so they share the same width. The arrows
   sit in the modal's outer gutter on either side. */
.chart-stage {
  display: flex;
  align-items: center;
  gap: 12px;
}
.chart-stage-inner {
  flex: 1;
  min-width: 0;            /* allow the chart column to shrink on narrow screens */
}

/* Circle nav buttons - flex items beside the chart, vertically centred
   by the parent's align-items: center. */
.chart-nav-arrow {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 50%;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease,
              transform .15s ease, box-shadow .15s ease, opacity .15s ease;
}
.chart-nav-arrow svg {
  width: 18px;
  height: 18px;
  display: block;
}
.chart-nav-arrow:hover:not(:disabled) {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  transform: scale(1.08);
  box-shadow: 0 3px 10px rgba(59,130,246,0.45);
}
.chart-nav-arrow:active:not(:disabled) {
  transform: scale(0.95);
}
.chart-nav-arrow:disabled {
  opacity: 0.25;
  cursor: not-allowed;
}

/* Subtle row highlight for the last-viewed stock */
tbody tr.row-recent {
  background: rgba(59,130,246,0.07);
}
tbody tr.row-recent:hover {
  background: rgba(59,130,246,0.13);
}
tbody tr.row-recent td:first-child {
  border-left: 2px solid var(--accent);
  padding-left: calc(10px - 2px);
}

/* Subtle card highlight in the dashboard */
.dash-card.dash-card-recent {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px rgba(59,130,246,0.25), 0 6px 20px rgba(59,130,246,0.18);
}

/* ── Line/Candle mode toggle in ChartModal title ── */
.chart-mode-toggle {
  margin-left: auto;
  display: flex;
  gap: 4px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px;
}
.mode-btn {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 4px;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.mode-btn:hover { color: var(--text); }
.mode-btn.mode-active {
  background: var(--accent);
  color: #fff;
}

/* ── Interactive chart toolbar (draw tools) ── */
.chart-view-info {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.chart-toolbar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 8px 0;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}

.tool-btn {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 11px;
  font-weight: 600;
  padding: 5px 10px;
  border-radius: 5px;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
  white-space: nowrap;
  /* Floor width so buttons with narrow leading glyphs (▬, ↺, ↶) don't
     look visibly smaller than buttons with wide emoji icons (✋, 📏, 🎯).
     The natural width of the widest-text button (🎯 Position) sets the
     ceiling; this just lifts the floor. */
  min-width: 72px;
  text-align: center;
}
.tool-btn:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
.tool-btn.tool-active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.tool-btn.tool-danger:hover:not(:disabled) {
  border-color: var(--red);
  color: var(--red);
}
.tool-btn:disabled {
  opacity: .4;
  cursor: not-allowed;
}

.tool-sep {
  width: 1px;
  height: 18px;
  background: var(--border);
  margin: 0 6px;
}

.tool-hint {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
}

/* ── Color palette for drawings ── */
.color-palette {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 4px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 5px;
}
.color-swatch {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--surface);
  cursor: pointer;
  padding: 0;
  transition: transform .12s, box-shadow .12s;
  box-shadow: 0 0 0 0 rgba(255,255,255,0);
}
.color-swatch:hover { transform: scale(1.18); }
.color-swatch.color-active {
  border-color: var(--text);
  box-shadow: 0 0 0 1px var(--accent);
  transform: scale(1.1);
}

/* Make the SVG not text-select on drag */
.price-chart {
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

/* ── Compare: row button + modal ── */
.cmp-btn {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  padding: 0 0 0 4px;
  margin: 0;
  width: 22px;
  display: inline-block;
  vertical-align: middle;
  opacity: .5;
  transition: opacity .15s, color .15s;
}
.cmp-btn:hover  { opacity: 1; }
.cmp-btn.cmp-on { opacity: 1; color: var(--accent); }

.modal-compare-card { width: min(640px, 96vw); }

.compare-header {
  display: grid;
  grid-template-columns: 1fr 50px 1fr;
  align-items: center;
  margin-bottom: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.compare-col-head { text-align: center; }
.compare-sym-link {
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.3px;
  cursor: pointer;
  padding: 0;
}
.compare-sym-link:hover { text-decoration: underline; }
.compare-sub {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}
.compare-vs {
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}

.compare-section-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--muted);
  margin: 12px 0 6px;
}

.compare-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.compare-table tr.cmp-primary { background: var(--surface2); }
.compare-table tr.cmp-primary .cmp-cell { font-size: 14px; font-weight: 700; }

.cmp-cell {
  padding: 8px 10px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  width: 35%;
  vertical-align: middle;
}
.cmp-cell.cmp-a, .cmp-cell.cmp-b-raw { text-align: right; }
.cmp-cell.cmp-b, .cmp-cell.cmp-a-raw { text-align: left; }
.cmp-label {
  text-align: center;
  font-weight: 600;
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
}
.cmp-diff {
  font-size: 10px;
  color: var(--muted);
  width: 70px;
  text-align: center;
  white-space: nowrap;
}
.cmp-win { color: var(--green); }
.cmp-tie { color: var(--text); }

.cmp-bar {
  height: 3px;
  background: var(--surface3);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 4px;
  width: 100%;
}
.cmp-bar-fill { height: 100%; border-radius: 2px; }
.cmp-bar-a { background: var(--accent); }
.cmp-bar-b { background: var(--green); }


/* ── View tabs at top of main area ── */
/* ── Top nav: view switcher ───────────────────────────────────
   Modern segmented-pill control. Each tab is a rounded button;
   hover gets a subtle tinted background, active is filled with
   the accent and lifts with a soft shadow. Counts render as
   small pill badges flush against the label. */
.view-tabs {
  display: flex;
  gap: 4px;
  align-items: center;
  background:
    linear-gradient(180deg,
      rgba(59, 130, 246, 0.05) 0%,
      rgba(59, 130, 246, 0.00) 70%),
    var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  padding: 8px 20px;
  overflow-x: auto;
  scrollbar-width: none;
}
.view-tabs::-webkit-scrollbar { display: none; }

.view-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.2px;
  padding: 8px 14px;
  border-radius: 9px;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  position: relative;
  transition:
    background-color 160ms ease,
    color 160ms ease,
    border-color 160ms ease,
    box-shadow 160ms ease,
    transform 80ms ease;
}
.view-tab:hover {
  background: var(--surface3);
  color: var(--text);
}
.view-tab:active { transform: translateY(0.5px); }
.view-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.view-tab-active,
.view-tab-active:hover {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  box-shadow:
    0 4px 14px -4px var(--accent),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.view-tab-icon {
  font-size: 14px;
  line-height: 1;
  flex-shrink: 0;
  filter: saturate(1.05);
}
.view-tab-label {
  letter-spacing: 0.25px;
}

.view-tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--surface3);
  color: var(--text);
  font-size: 10.5px;
  font-weight: 800;
  padding: 1px 7px;
  border-radius: 999px;
  min-width: 20px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  transition: background-color 160ms ease, color 160ms ease;
}
.view-tab:hover .view-tab-badge {
  background: var(--surface2);
}
.view-tab-active .view-tab-badge {
  background: rgba(255, 255, 255, 0.22);
  color: #fff;
}


/* ── Watchlist Dashboard ── */
.dash-container {
  flex: 1;
  overflow-y: auto;
  padding: 0 24px 24px;
}
.dash-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  padding: 16px 0 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 18px;
}
.dash-title {
  font-size: 20px;
  font-weight: 700;
  color: var(--text);
}
.dash-stamp {
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
}

.dash-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Auto-margin centering instead of `justify-content: center` — same
     pattern + same reason as .welcome / .auth-gate: when content
     exceeds container (a11y text-zoom XL on a short viewport), the
     centered overflow clips top + bottom. Auto margins collapse to 0
     in that case so content top-aligns and overflow-y scrolls it. */
  justify-content: flex-start;
  overflow-y: auto;
  text-align: center;
  padding: 40px;
  gap: 10px;
  color: var(--muted);
}
.dash-empty > :first-child { margin-top: auto; }
.dash-empty > :last-child  { margin-bottom: auto; }

.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
  gap: 14px;
}

.dash-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: border-color .15s, transform .15s;
}
.dash-card:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
}

/* Locked watchlist card - placeholder for symbols beyond the free
   cap. Same outer shape so it slots cleanly into the grid, but
   greyed out + lock overlay + amber click affordance. */
.dash-card-locked {
  align-items: center;
  justify-content: center;
  text-align: center;
  background: linear-gradient(135deg, rgba(245,158,11,0.06), rgba(245,158,11,0.01));
  border: 1px dashed rgba(245, 158, 11, 0.5);
  cursor: pointer;
  min-height: 180px;
  gap: 6px;
  transition: background .15s, border-color .15s, transform .15s;
}
.dash-card-locked:hover {
  background: linear-gradient(135deg, rgba(245,158,11,0.12), rgba(245,158,11,0.03));
  border-color: rgba(245, 158, 11, 0.8);
  transform: translateY(-1px);
}
.dash-card-locked-icon {
  font-size: 36px;
  line-height: 1;
  opacity: 0.85;
  margin-bottom: 2px;
}
.dash-card-locked-msg {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.45;
  max-width: 85%;
}
.dash-card-locked-cta {
  margin-top: 4px;
  font-size: 12px;
  font-weight: 700;
  color: #f59e0b;
}

/* ── Watchlist first-load "Scanning…" state ── */
.dash-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 56px 24px 40px;
  text-align: center;
}
.dash-loading-spinner {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  animation: dash-spin 0.8s linear infinite;
}
@keyframes dash-spin { to { transform: rotate(360deg); } }
.dash-loading-title { font-size: 17px; font-weight: 700; color: var(--text); }
.dash-loading-sub {
  font-size: 13.5px;
  color: var(--muted);
  max-width: 380px;
  line-height: 1.5;
}
.dash-loading-skeletons {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
  width: 100%;
  max-width: 760px;
  margin-top: 18px;
}
.dash-skel-card {
  height: 96px;
  border-radius: 12px;
  background: linear-gradient(100deg,
    rgba(255,255,255,0.03) 30%,
    rgba(255,255,255,0.08) 50%,
    rgba(255,255,255,0.03) 70%);
  background-size: 200% 100%;
  border: 1px solid var(--border);
  animation: dash-shimmer 1.3s ease-in-out infinite;
}
@keyframes dash-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ── Top-signals Pro lock (Today dashboard) ── */
.today-prolock-body { position: relative; }
/* Blurred dummy rows behind the lock overlay so the widget has visible
   structure (looks like real signals) without revealing any picks. */
.today-prolock-rows { filter: blur(4px); opacity: 0.55; pointer-events: none; user-select: none; }
.today-row-ph { cursor: default; }
.ph-blur { color: var(--muted); }
.today-prolock-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 8px;
  padding: 16px;
  background: linear-gradient(180deg, rgba(10,15,28,0.35), rgba(10,15,28,0.78));
  border-radius: 12px;
}
.today-prolock-icon { font-size: 30px; line-height: 1; opacity: 0.9; }
.today-prolock-msg {
  font-size: 13px;
  color: var(--text);
  line-height: 1.5;
  max-width: 88%;
}
.today-prolock-cta {
  margin-top: 2px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 800;
  color: #fff;
  background: #f59e0b;
  border: none;
  border-radius: 8px;
  padding: 8px 16px;
  cursor: pointer;
  transition: background .15s, transform .1s;
}
.today-prolock-cta:hover { background: #fbbf24; transform: translateY(-1px); }

.dash-card-head {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.dash-sym { font-size: 18px; }
.dash-sector {
  flex: 1;
  font-size: 11px;
  color: var(--muted);
  margin-left: 6px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dash-card-body {
  display: flex;
  align-items: center;
  gap: 14px;
}
/* Right cluster — current price stacked above the sparkline. The price
   is a button so a tap on it (same surface as the sparkline) opens the
   chart, matching the symbol-link affordance in the head row. */
.dash-card-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}
.dash-price {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
  background: transparent;
  border: none;
  padding: 0;
  font: 700 14px/1.1 'Cascadia Code', Consolas, monospace;
  color: var(--text);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: filter 0.15s ease;
}
.dash-price:hover { filter: brightness(1.15); }
.dash-price-up   { color: #22c55e; }
.dash-price-down { color: #ef4444; }
.dash-price-flat { color: var(--text); }

/* Tiny change-pct chip beneath the price. Inherits the parent's
   green/red colour so the row reads as one signal. */
.dash-price-chg {
  font: 600 10px/1 'Cascadia Code', Consolas, monospace;
  opacity: 0.85;
  letter-spacing: 0.02em;
}

/* Cards / List toggle in the dashboard header — borrows the existing
   .mode-btn pill style used by the chart-modal interval toggle so it
   feels familiar. */
.dash-header-left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
}
.dash-title-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

/* Cards / List view-mode toggle — segmented control. Subtle until
   active, bright accent when selected. Sits inline with the title so
   it reads as a display setting, not an action. */
.watchlist-view-toggle {
  display: inline-flex;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border, rgba(255,255,255,0.10));
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
}
.view-mode-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: none;
  color: var(--muted);
  font: 600 12px/1 'Segoe UI', system-ui, sans-serif;
  letter-spacing: 0.02em;
  padding: 6px 12px;
  border-radius: 5px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.view-mode-btn:hover { color: var(--text); background: rgba(255,255,255,0.04); }
.view-mode-glyph { font-size: 13px; line-height: 1; }
.view-mode-active {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}
.view-mode-active:hover { color: #fff; background: var(--accent2, var(--accent)); }

@media (max-width: 540px) {
  .view-mode-label { display: none; }
  .view-mode-btn { padding: 6px 10px; }
}

/* List-mode wrapper around the ResultsTable inside the watchlist
   dashboard. `.dash-container` is a vertical-scroll block (not flex),
   so the scanner's `.table-area { flex: 1 }` collapses to nothing
   when the table is dropped in. Override here: full width, natural
   height, table scrolls horizontally if columns exceed viewport. */
.watchlist-list { width: 100%; }
.watchlist-list .table-area {
  flex: none;
  height: auto;
  overflow-x: auto;
  overflow-y: visible;
}
.dash-composite {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.dash-comp-num {
  font-size: 28px;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.dash-comp-bar {
  height: 6px;
  background: var(--surface2);
  border-radius: 3px;
  overflow: hidden;
}
.dash-comp-fill { height: 100%; border-radius: 3px; }
.dash-composite.cmp-hi  .dash-comp-num,
.dash-composite.cmp-hi  .dash-comp-fill { color: var(--green);  background: var(--green); }
.dash-composite.cmp-mid .dash-comp-num,
.dash-composite.cmp-mid .dash-comp-fill { color: var(--yellow); background: var(--yellow); }
.dash-composite.cmp-lo  .dash-comp-num,
.dash-composite.cmp-lo  .dash-comp-fill { color: var(--orange); background: var(--orange); }
.dash-composite.cmp-bad .dash-comp-num,
.dash-composite.cmp-bad .dash-comp-fill { color: var(--red);    background: var(--red); }
.dash-composite .dash-comp-num { background: none !important; }   /* keep num as text color only */
.dash-spark {
  background: transparent;
  border: none;
  padding: 4px;
  border-radius: 6px;
  cursor: pointer;
}
.dash-spark:hover { background: var(--surface2); }

.dash-cats {
  display: grid;
  /* auto-fit + minmax so the 7 category chips reflow naturally on
     phones — was a hardcoded 4 columns which crowded the labels at
     narrow widths. ~70 px keeps the emoji + 3-4 char labels readable;
     anything narrower wraps to the next row. */
  grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
  gap: 6px;
  font-size: 11px;
}
.dash-cat {
  background: var(--surface2);
  border-radius: 4px;
  padding: 4px 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}
.dash-cat-lbl {
  font-size: 9px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.dash-cat-num {
  font-weight: 700;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* Per-bucket coloring — same 4-tier scheme as CompositeCell in the
   scanner table (cmp-hi green ≥75, cmp-mid yellow 60-74, cmp-lo
   orange 45-59, cmp-bad red <45). cat-na for missing data. We tint
   the WHOLE chip (background + accent left border + bold number)
   instead of just the number so the eye can scan a row of seven
   chips and instantly see the strong/weak axes. */
.dash-cat.cmp-hi {
  background: rgba(34, 197, 94, 0.14);
  border-left: 3px solid var(--green, #22c55e);
  padding-left: 5px;
}
.dash-cat.cmp-hi  .dash-cat-num { color: var(--green, #22c55e); }
.dash-cat.cmp-mid {
  background: rgba(234, 179, 8, 0.13);
  border-left: 3px solid var(--yellow, #eab308);
  padding-left: 5px;
}
.dash-cat.cmp-mid .dash-cat-num { color: var(--yellow, #eab308); }
.dash-cat.cmp-lo {
  background: rgba(249, 115, 22, 0.13);
  border-left: 3px solid var(--orange, #f97316);
  padding-left: 5px;
}
.dash-cat.cmp-lo  .dash-cat-num { color: var(--orange, #f97316); }
.dash-cat.cmp-bad {
  background: rgba(239, 68, 68, 0.13);
  border-left: 3px solid var(--red, #ef4444);
  padding-left: 5px;
}
.dash-cat.cmp-bad .dash-cat-num { color: var(--red, #ef4444); }
.dash-cat.cat-na .dash-cat-num { color: var(--muted); }

.dash-metrics {
  display: flex;
  gap: 12px;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.dash-metric { color: var(--muted); }

.dash-note-row {
  border-top: 1px solid var(--border);
  padding-top: 8px;
}
.dash-note {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 11px;
  cursor: pointer;
  text-align: left;
  padding: 0;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: inherit;
}
.dash-note:hover  { color: var(--accent); }
.dash-note.has-note { color: var(--text); font-style: italic; }

/* ── Scoring Guide: help button, modal, cards ── */

.btn-help {
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.btn-help:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* Theme toggle button (sun / moon SVG icons) */
.btn-theme {
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 32px;
  height: 32px;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: border-color .15s, color .15s, background .15s, transform .15s;
}
.btn-theme svg {
  width: 16px;
  height: 16px;
  display: block;          /* removes the inline-baseline gap */
}
.btn-theme:hover {
  border-color: var(--accent);
  color: var(--accent);
  transform: rotate(15deg);
}

/* Columns modal */
.col-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 380px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
  background: var(--surface2);
}
.col-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 4px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  transition: background .12s;
}
.col-row:hover { background: var(--surface3); }
.col-row input[type="checkbox"] {
  accent-color: var(--accent);
  width: 16px;
  height: 16px;
  cursor: pointer;
}
.col-row-required {
  cursor: not-allowed;
  color: var(--muted);
}
.col-row-required input { cursor: not-allowed; }
.col-row-label { flex: 1; }
.col-row-tag {
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
  background: var(--surface);
  padding: 2px 7px;
  border-radius: 8px;
}

/* ⓘ next to sortable column headers - click to learn about that category */
.th-info {
  display: inline-block;
  margin-left: 4px;
  font-size: 11px;
  color: var(--muted);
  cursor: help;
  opacity: .65;
  transition: opacity .15s, color .15s;
  vertical-align: 1px;
}
.th-info:hover {
  opacity: 1;
  color: var(--accent);
}

.modal-help-card {
  width: min(680px, 96vw);
  max-height: 88vh;
  overflow-y: auto;
}
.help-intro {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.6;
  margin: -8px 0 16px;
}

.help-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.help-card {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  transition: border-color .15s;
}
.help-card.help-card-open {
  border-color: var(--accent);
}
.help-card-head {
  width: 100%;
  background: transparent;
  border: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  cursor: pointer;
  color: var(--text);
  font-size: 14px;
  text-align: left;
}
.help-icon  { font-size: 18px; }
.help-title { flex: 1; font-weight: 700; }
.help-weight {
  background: var(--surface3);
  color: var(--accent);
  font-size: 10px;
  font-weight: 800;
  padding: 2px 8px;
  border-radius: 10px;
  letter-spacing: 0.3px;
}
.help-caret {
  font-size: 11px;
  color: var(--muted);
  width: 14px;
  text-align: center;
}

.help-card-body {
  padding: 4px 16px 16px 50px;
  border-top: 1px solid var(--border);
}
.help-summary {
  font-size: 13px;
  color: var(--text);
  font-weight: 600;
  margin: 12px 0 14px;
  line-height: 1.5;
}
.help-section-lbl {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--muted);
  margin: 14px 0 6px;
}
.help-bullets {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 12px;
  color: var(--text);
  line-height: 1.6;
}
.help-bullets li {
  padding-left: 14px;
  position: relative;
}
.help-bullets li::before {
  content: '·';
  color: var(--accent);
  position: absolute;
  left: 4px;
  font-weight: 700;
}

.help-tiers {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
}
.help-tier {
  display: grid;
  grid-template-columns: 70px 1fr;
  gap: 10px;
  align-items: center;
  padding: 6px 10px;
  border-radius: 4px;
  border-left: 3px solid var(--border);
  background: var(--bg);
}
.help-tier.cmp-hi  { border-left-color: var(--green); }
.help-tier.cmp-mid { border-left-color: var(--yellow); }
.help-tier.cmp-lo  { border-left-color: var(--orange); }
.help-tier.cmp-bad { border-left-color: var(--red); }

.help-tier-range {
  font-weight: 800;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.help-tier-label {
  color: var(--muted);
  font-size: 12px;
}

.help-why {
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
  margin: 0;
  font-style: italic;
}

/* ── Composite history chart (inside ChartModal) ── */
.comp-history-wrap {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.comp-history-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--muted);
  margin-bottom: 6px;
}
.comp-history-sub {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}
.comp-history-svg {
  display: block;
  width: 100%;
  background: var(--bg);
  border-radius: 6px;
}

/* ── Sector Rotation table ── */
.sect-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
  margin-top: 4px;
}
.sect-table thead th {
  position: sticky;
  top: 0;
  background: var(--bg);
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
  padding: 10px 8px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.sect-table thead th.sect-col-name { text-align: left; }
.sect-table tbody td {
  text-align: center;
  padding: 10px 8px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  border-bottom: 1px solid rgba(45,55,72,0.5);
}
.sect-table tbody tr:hover { background: rgba(31,41,55,0.5); }

.sect-name-cell {
  text-align: left !important;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 10px;
}
.sect-etf {
  background: var(--surface3);
  color: var(--accent);
  font-weight: 800;
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 4px;
}
.sect-name { font-weight: 600; color: var(--text); }

.sect-headline { font-size: 14px; font-weight: 800; }

.sect-col-trend { width: 80px; }
.sect-col-spark { width: 80px; }
.sect-col-name  { width: 22%; }

/* Return colors (background-tinted) */
.ret-vstrong { background: rgba(34,197,94,0.30); color: var(--green); }
.ret-strong  { background: rgba(34,197,94,0.18); color: var(--green); }
.ret-mild    { background: rgba(34,197,94,0.08); color: var(--green); }
.ret-flat    { color: var(--muted); }
.ret-weak    { background: rgba(239,68,68,0.08); color: var(--red); }
.ret-down    { background: rgba(239,68,68,0.18); color: var(--red); }
.ret-vdown   { background: rgba(239,68,68,0.30); color: var(--red); }

/* SPY ref colors in header (same hue, no background) */
.sect-spy-vstrong, .sect-spy-strong, .sect-spy-mild { color: var(--green); font-weight: 700; }
.sect-spy-weak, .sect-spy-down, .sect-spy-vdown    { color: var(--red);   font-weight: 700; }
.sect-spy-flat { color: var(--muted); }

/* Trend cell colors */
.sect-trend-up    { color: var(--green); font-weight: 700; }
.sect-trend-mixed { color: var(--yellow); }
.sect-trend-down  { color: var(--red); font-weight: 700; }

/* Legend strip */
.sect-legend {
  margin-top: 18px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.sect-legend-title {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--muted);
  margin-bottom: 8px;
}
.sect-legend-bar {
  display: flex;
  gap: 4px;
  font-size: 11px;
  font-weight: 700;
  /* Wrap to multiple rows on narrow viewports — 7 cells × ~85 px each
     can't fit a 400 px phone in one row, and forcing single-row makes
     the cell text wrap into a 2-3-line tangle. Multi-row wrap keeps
     each cell legible. */
  flex-wrap: wrap;
}
.sect-legend-bar span {
  padding: 4px 10px;
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
  /* Keep each cell's text on one line — the cells themselves wrap to
     the next row when the container runs out of width, but the cell
     content stays atomic. */
  white-space: nowrap;
  flex-shrink: 0;
}

/* Score column */
.score-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}
.score-num {
  font-weight: 800;
  font-size: 15px;
  min-width: 18px;
}
.score-bar {
  flex: 1;
  height: 5px;
  background: var(--surface2);
  border-radius: 3px;
  overflow: hidden;
  min-width: 50px;
}
.score-fill { height: 100%; border-radius: 3px; }

.sc0,.sc1,.sc2,.sc3 { --sc: var(--red); }
.sc4,.sc5           { --sc: var(--orange); }
.sc6                { --sc: var(--yellow); }
.sc7,.sc8           { --sc: var(--green); }

/* Composite (0-100) cell - main column */
.composite-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 95px;
}
.composite-num {
  font-weight: 800;
  font-size: 13px;
  min-width: 32px;
  font-variant-numeric: tabular-nums;
}
.composite-bar {
  flex: 1;
  height: 5px;
  background: var(--surface2);
  border-radius: 3px;
  overflow: hidden;
  min-width: 36px;
}
.composite-fill { height: 100%; border-radius: 3px; }

/* Compact variant - used for sub-category columns (Trend, Mom, Vol, etc.) */
.composite-wrap.composite-compact {
  min-width: 58px;
  gap: 4px;
}
.composite-wrap.composite-compact .composite-num {
  font-size: 11px;
  font-weight: 700;
  min-width: 18px;
}
.composite-wrap.composite-compact .composite-bar {
  height: 4px;
  min-width: 22px;
}

.cmp-hi  { --cmp: var(--green);  }
.cmp-mid { --cmp: var(--yellow); }
.cmp-lo  { --cmp: var(--orange); }
.cmp-bad { --cmp: var(--red);    }
.composite-wrap .composite-num { color: var(--cmp); }
.composite-wrap .composite-fill { background: var(--cmp); }

/* Percentile "Top X%" badge inside composite cell */
.pct-badge {
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.4px;
  padding: 1px 5px;
  border-radius: 4px;
  white-space: nowrap;
}
.pct-top5  { background: var(--green-bg);  color: var(--green); border: 1px solid rgba(34,197,94,0.4); }
.pct-top10 { background: var(--yellow-bg); color: var(--yellow); border: 1px solid rgba(234,179,8,0.4); }
.pct-top25 { background: var(--surface3);  color: var(--text); }
[class^="sc"] .score-num,
[class*=" sc"] .score-num { color: var(--sc); }
[class^="sc"] .score-fill,
[class*=" sc"] .score-fill { background: var(--sc); }

/* Bool badge */
.bool {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px; height: 24px;
  border-radius: 5px;
  font-size: 13px;
  font-weight: 700;
}
.bool-t { background: var(--green-bg); color: var(--green); }
.bool-f { background: var(--red-bg);   color: var(--red); }
.bool-n { background: var(--surface2); color: var(--muted); }

/* Reco badge */
.reco {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  padding: 3px 8px;
  border-radius: 5px;
  white-space: nowrap;
}
.reco-buy  { background: var(--green-bg); color: var(--green); }
.reco-sell { background: var(--red-bg);   color: var(--red); }
.reco-neut { background: var(--surface2); color: var(--muted); }

.n-pos { color: var(--green); }
.n-neg { color: var(--red); }
.n-ok  { color: var(--text); }

/* ── Welcome ────────────────────────────────── */
.welcome {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Auto-margin centering instead of `justify-content: center`.
     Reason: `justify-content: center` pushes overflow equally above
     and below the container — on 1920×1080 the bottom "Tap the 📚
     Scoring guide…" footer used to clip off because the rule-cards
     grid + intro + logo together exceed the available panel height.
     Auto margins expand to center when content FITS, collapse to 0
     when content overflows so the layout naturally top-aligns and the
     internal scrollbar (`overflow-y: auto` below) reveals everything. */
  justify-content: flex-start;
  overflow-y: auto;
  gap: 14px;
  text-align: center;
  color: var(--muted);
  padding: 40px;
}
.welcome > :first-child { margin-top: auto; }
.welcome > :last-child  { margin-bottom: auto; }
.welcome-icon { font-size: 60px; line-height: 1; }
/* When the welcome icon is an image (the logo mark) instead of a text
   emoji, size it like a hero badge and let the drop-shadow give it a
   bit of presence against the panel background. */
.welcome-icon-img {
  width: 140px;
  height: 140px;
  font-size: 0;             /* suppress alt-text flash before load */
  object-fit: contain;
  filter: drop-shadow(0 2px 10px rgba(59, 130, 246, 0.25));
  margin-bottom: 4px;
}
@media (max-width: 900px) {
  .welcome-icon-img { width: 110px; height: 110px; }
}
.welcome-h    { font-size: 22px; font-weight: 700; color: var(--text); }
.welcome-p    { font-size: 14px; max-width: 440px; line-height: 1.65; }

.rules-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 8px;
  max-width: 440px;
  text-align: left;
}
.rule-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 12px;
}
.rule-cat {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--accent);
  margin-bottom: 4px;
}
.rule-item { color: var(--muted); margin-top: 2px; }

/* ── Accessibility ─────────────────────────────────────────────────────
   Four orthogonal preferences applied via classes on <html>:
     .a11y-text-sm / .a11y-text-lg / .a11y-text-xl     (text scaling)
     .a11y-high-contrast                                (bolder borders/text)
     .a11y-reduce-motion                                (kill animations)
     .a11y-colorblind                                   (blue/orange palette)
   Toggled by the AccessibilityModal in modals.jsx. */

/* ── Settings toggle row (label + description + iOS-style switch) ──
   Reusable card-style preference row used in the Settings modal. The
   whole row is a <label> so clicking anywhere flips the switch. */
.setting-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  margin: 4px 0 18px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-2, rgba(255, 255, 255, 0.02));
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.setting-toggle:hover { border-color: var(--accent, #3b82f6); }
.setting-toggle.is-on {
  border-color: color-mix(in srgb, var(--accent, #3b82f6) 55%, transparent);
  background: color-mix(in srgb, var(--accent, #3b82f6) 8%, transparent);
}
.setting-toggle-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.setting-toggle-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
}
.setting-toggle-desc {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
}

/* iOS-style switch. The native checkbox is visually hidden but stays
   keyboard- and screen-reader-accessible; the track/knob render the UI. */
.switch {
  position: relative;
  flex: 0 0 auto;
  width: 46px;
  height: 26px;
}
.switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
.switch-track {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: var(--border, #3a3f4b);
  transition: background 0.2s ease;
  pointer-events: none;
}
.switch-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  transition: transform 0.2s cubic-bezier(0.4, 0.0, 0.2, 1);
}
.switch input:checked + .switch-track {
  background: var(--accent, #3b82f6);
}
.switch input:checked + .switch-track .switch-knob {
  transform: translateX(20px);
}
.switch input:focus-visible + .switch-track {
  outline: 2px solid var(--accent, #3b82f6);
  outline-offset: 2px;
}

/* ── Market index strip ───────────────────────────────────────
   Thin row above the header showing daily moves on the four major
   US indexes (S&P 500, Nasdaq-100, Dow, Russell 2000). Optional —
   gated by the showMarketStrip preference. Colours use the same
   --candle-up / --candle-down vars as the chart so the colour-blind
   palette tracks automatically. */
.market-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 28px;
  flex-wrap: nowrap;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 8px 16px;
  font: 600 12.5px/1 ui-monospace, "SF Mono", Consolas, monospace;
  letter-spacing: 0.02em;
  overflow-x: auto;
  scrollbar-width: none;            /* Firefox */
}
.market-strip::-webkit-scrollbar { display: none; }   /* Chromium */
.market-strip-item {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  white-space: nowrap;
  flex-shrink: 0;
}
.market-strip-name {
  color: var(--muted);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 11px;
}
.market-strip-close {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.market-strip-chg {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 4px;
}
.market-strip-up   .market-strip-chg { color: var(--candle-up,   #22c55e); background: rgba(34,197,94,0.10); }
.market-strip-down .market-strip-chg { color: var(--candle-down, #ef4444); background: rgba(239,68,68,0.10); }
.market-strip-flat .market-strip-chg { color: var(--muted); }
.market-strip-live {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: #ef4444;
  padding: 2px 6px;
  border: 1px solid rgba(239,68,68,0.35);
  border-radius: 4px;
  flex-shrink: 0;
}
.market-strip-live-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: #ef4444;
  animation: market-strip-pulse 1.6s ease-in-out infinite;
}
@keyframes market-strip-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}
html.a11y-reduce-motion .market-strip-live-dot { animation: none; }
/* Tighten and de-prioritise on small screens — keep absolute level off
   so the % move is still visible without horizontal scrolling. */
@media (max-width: 640px) {
  .market-strip { gap: 16px; padding: 7px 10px; }
  .market-strip-close { display: none; }
  .market-strip-name  { font-size: 10px; }
}
/* Very narrow phones (≤420 px): even the 640-px breakpoint above leaves
   the 4 ETFs spilling past the right edge. Tighten gap, reduce padding
   on container + change-pill, shrink the change font slightly, and
   tighten the gap inside each item. Net effect: SPY / QQQ / DIA / IWM
   all fit in one row at 395-px viewport with breathing room at both
   edges, no horizontal scroll needed. */
@media (max-width: 420px) {
  .market-strip {
    gap: 10px;
    padding: 6px 8px;
    font-size: 11.5px;
  }
  .market-strip-item    { gap: 5px; }
  .market-strip-chg     { padding: 1px 4px; }
}

/* ── "Today" home dashboard ────────────────────────────────────────
   An account KPI band + a responsive auto-fit widget grid: open positions,
   top signals, performance, market context, sector exposure, watchlist
   movers, earnings, alerts. Every row is a button that opens that symbol's
   chart modal. */
/* No max-width — the dashboard fills the ENTIRE content area (next to the
   sidebar) so there's no wasted margin on wide screens. width:100% is
   required because .main is a flex column (an auto margin would otherwise
   shrink the element to its content width instead of filling). */
.today-view { width: 100%; box-sizing: border-box; padding: 22px 28px 80px; }
.today-head { display: flex; align-items: baseline; gap: 12px; margin: 2px 2px 16px; }
.today-title { font-size: 26px; font-weight: 800; margin: 0; }
.today-asof { color: var(--muted); font-size: 13px; }
.today-status { color: var(--muted); font-size: 13px; padding: 40px 6px; text-align: center; }

/* Account KPI band */
.today-kpis { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
.today-kpi { position: relative; background: linear-gradient(180deg, rgba(255,255,255,0.04), transparent), var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 13px 15px; min-width: 0; box-shadow: 0 1px 3px rgba(0,0,0,0.2); transition: border-color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease; }
.today-kpi:hover { border-color: rgba(127,127,127,0.4); transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,0.26); }
.today-kpi-label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; }
.today-kpi-val { font-size: 24px; font-weight: 800; font-variant-numeric: tabular-nums; margin-top: 5px; letter-spacing: -0.01em; }
.today-kpi-val.pos { color: var(--candle-up, #22c55e); }
.today-kpi-val.neg { color: var(--candle-down, #ef4444); }
.today-kpi-sub { color: var(--muted); font-size: 11.5px; font-variant-numeric: tabular-nums; margin-top: 2px; }
@media (max-width: 900px) { .today-kpis { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 520px) { .today-kpis { grid-template-columns: repeat(2, 1fr); } }

/* Widget grid — auto-fit fills the width with as many ~330px columns as fit. */
/* Explicit, even column counts (2 / 3 / 4) so the 8 widgets always tile into
   clean rows with no ragged empty tail. No max column — at the top breakpoint
   the 4 columns simply stretch to fill the full width, making every widget
   wider on big screens. */
.today-grid { display: grid; grid-template-columns: 1fr; gap: 16px; align-items: stretch; }
@media (min-width: 700px)  { .today-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1180px) { .today-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1640px) { .today-grid { grid-template-columns: repeat(4, 1fr); } }
.today-span2 { grid-column: auto; }   /* uniform — no card spans, so rows stay even */

/* Every widget is the SAME fixed height; the header stays put and the body
   scrolls when its content overflows — so a data-rich card and an empty one
   line up to the same height instead of producing a ragged grid. */
.today-card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; overflow: hidden; min-width: 0; height: 392px; display: flex; flex-direction: column; box-shadow: 0 1px 3px rgba(0,0,0,0.22); transition: border-color 0.18s ease, box-shadow 0.18s ease; }
.today-card:hover { border-color: rgba(127,127,127,0.34); box-shadow: 0 8px 26px rgba(0,0,0,0.30); }
.today-card-head { flex: 0 0 auto; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 14px 14px 11px; border-bottom: 1px solid var(--border); background: linear-gradient(180deg, rgba(255,255,255,0.025), transparent); }
.today-card-title { display: inline-flex; align-items: center; gap: 9px; }
.today-card-title::before { content: ''; width: 3px; height: 13px; border-radius: 2px; background: var(--accent, #3b82f6); flex: 0 0 auto; }
.today-card-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 4px 0 8px; scrollbar-width: thin; scrollbar-color: rgba(127,127,127,0.3) transparent; }
.today-card-body::-webkit-scrollbar { width: 8px; }
.today-card-body::-webkit-scrollbar-thumb { background: rgba(127,127,127,0.25); border-radius: 8px; }
.today-card-body::-webkit-scrollbar-track { background: transparent; }
.today-card-title { font-weight: 700; font-size: 15px; }
.today-card-sub { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; font-variant-numeric: tabular-nums; }
.today-empty { color: var(--muted); font-size: 13px; padding: 18px 14px; line-height: 1.45; }

/* generic row (signals / movers / earnings / alerts / recent / sector-strength) */
.today-row { display: flex; align-items: center; gap: 12px; width: 100%; padding: 11px 14px; border: none; background: transparent; text-align: left; cursor: pointer; border-radius: 9px; font-size: 14px; color: var(--text); font-family: inherit; transition: background 0.12s ease; }
.today-row.today-row-static { cursor: default; }
.today-row.today-row-sm { padding: 8px 14px; font-size: 13px; }
button.today-row:hover { background: rgba(127,127,127,0.08); }
.today-spacer { flex: 1 1 auto; }
.today-sym { font-weight: 700; min-width: 50px; display: inline-flex; align-items: center; gap: 6px; }
.today-side { font-size: 9px; font-weight: 800; color: var(--candle-down,#ef4444); background: rgba(239,68,68,0.14); padding: 0 4px; border-radius: 3px; }
.today-meta { flex: 1 1 auto; min-width: 0; color: var(--muted); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.today-meta-strong { color: var(--text); font-size: 13px; }
.today-px { font-variant-numeric: tabular-nums; color: var(--text); }
.today-num { font-variant-numeric: tabular-nums; }
.today-num.pos { color: var(--candle-up,#22c55e); }
.today-num.neg { color: var(--candle-down,#ef4444); }
.today-chg { font-variant-numeric: tabular-nums; font-weight: 700; min-width: 70px; text-align: right; }
.today-chg.pos { color: var(--candle-up, #22c55e); }
.today-chg.neg { color: var(--candle-down, #ef4444); }
.today-comp { font-weight: 800; font-variant-numeric: tabular-nums; padding: 1px 7px; border-radius: 999px; font-size: 12px; }
.today-comp-hi  { color: var(--candle-up, #22c55e); background: rgba(34,197,94,0.14);  box-shadow: inset 0 0 0 1px rgba(34,197,94,0.30); }
.today-comp-mid { color: #d39e00;                   background: rgba(234,179,8,0.16);  box-shadow: inset 0 0 0 1px rgba(234,179,8,0.30); }
.today-comp-lo  { color: var(--muted);              background: rgba(127,127,127,0.10); }
.today-days { color: var(--muted); font-size: 12px; }
.today-days.soon { color: var(--candle-down, #ef4444); font-weight: 700; }
.today-held { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--accent, #3b82f6); background: rgba(59,130,246,0.14); padding: 1px 5px; border-radius: 4px; }
.today-pill { font-weight: 700; font-size: 11.5px; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.today-pill-good { color: var(--candle-up, #22c55e); background: rgba(34,197,94,0.12); }
.today-pill-bad  { color: var(--candle-down, #ef4444); background: rgba(239,68,68,0.12); }
.today-pill-warn { color: #d39e00; background: rgba(234,179,8,0.14); }

/* Open positions table */
.today-postable { padding: 2px 6px 4px; }
.today-pos-row { display: grid; grid-template-columns: 1.2fr 0.9fr 0.9fr 0.7fr 0.95fr 1.05fr; align-items: center; gap: 8px; width: 100%; padding: 9px 10px; border: none; background: transparent; cursor: pointer; border-radius: 8px; font-size: 13px; color: var(--text); font-family: inherit; text-align: left; transition: background 0.12s ease; }
.today-pos-row > span:not(.today-sym) { text-align: right; font-variant-numeric: tabular-nums; }
button.today-pos-row:hover { background: rgba(127,127,127,0.08); }
/* scannable win/loss accent down the left edge of each position row */
.today-pos-row.pos-win  { box-shadow: inset 3px 0 0 var(--candle-up,   #22c55e); }
.today-pos-row.pos-loss { box-shadow: inset 3px 0 0 var(--candle-down, #ef4444); }
.today-pos-head { position: sticky; top: 0; z-index: 1; background: var(--surface); color: var(--muted); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.03em; cursor: default; border-bottom: 1px solid var(--border); border-radius: 0; }
.today-pos-dist { color: var(--muted); font-size: 11.5px; }

/* Performance + market stat grids */
.today-perf-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px 10px; padding: 12px 14px 6px; }
.today-perf-stats > div { display: flex; flex-direction: column; padding: 6px 0; }
.today-stat-v { font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums; }
.today-stat-v.pos { color: var(--candle-up,#22c55e); }
.today-stat-v.neg { color: var(--candle-down,#ef4444); }
.today-stat-l { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; margin-top: 1px; }
.today-spark { width: 100%; height: 46px; display: block; padding: 4px 12px 6px; }
.today-spark-zero { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 3; }
.today-spark-up { fill: none; stroke: var(--candle-up,#22c55e); stroke-width: 2; vector-effect: non-scaling-stroke; }
.today-spark-down { fill: none; stroke: var(--candle-down,#ef4444); stroke-width: 2; vector-effect: non-scaling-stroke; }
.today-recent { padding: 4px 0 2px; border-top: 1px solid var(--border); margin-top: 6px; }
.today-subhead { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; padding: 10px 14px 4px; }

/* ── Market context widget (redesigned) ── */
.mkt-breadth { padding: 14px 14px 10px; }
.mkt-breadth-top { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 8px; }
.mkt-breadth-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.mkt-breadth-val { font-size: 21px; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--text); line-height: 1; }
.mkt-breadth-val.mkt-up   { color: var(--green); }
.mkt-breadth-val.mkt-flat { color: var(--yellow); }
.mkt-breadth-val.mkt-down { color: var(--red); }
.mkt-breadth-track { position: relative; height: 8px; border-radius: 999px; background: var(--surface2); overflow: hidden; }
.mkt-breadth-fill { height: 100%; border-radius: 999px; transition: width .45s cubic-bezier(.2,.8,.2,1); background: linear-gradient(90deg, var(--accent), #60a5fa); }
.mkt-breadth-fill.mkt-up   { background: linear-gradient(90deg, #16a34a, #22c55e); }
.mkt-breadth-fill.mkt-flat { background: linear-gradient(90deg, #ca8a04, #eab308); }
.mkt-breadth-fill.mkt-down { background: linear-gradient(90deg, #dc2626, #ef4444); }
.mkt-breadth-mid { position: absolute; top: -2px; bottom: -2px; left: 50%; width: 2px; transform: translateX(-50%); background: rgba(255,255,255,0.22); border-radius: 2px; }

.mkt-chips { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 4px 14px 12px; }
.mkt-chip { background: var(--surface2); border: 1px solid var(--border); border-radius: 10px; padding: 10px 8px; text-align: center; }
.mkt-chip-v { font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.mkt-chip-l { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; margin-top: 3px; line-height: 1.25; }
.mkt-chip-hi  { background: var(--green-bg);  border-color: rgba(34,197,94,0.30); }
.mkt-chip-hi .mkt-chip-v  { color: var(--green); }
.mkt-chip-mid { background: var(--yellow-bg); border-color: rgba(234,179,8,0.30); }
.mkt-chip-mid .mkt-chip-v { color: var(--yellow); }

.mkt-sectors { padding: 4px 14px 14px; }
.mkt-sectors-head { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 8px; }
.mkt-sector-row { display: grid; grid-template-columns: 16px 86px 1fr 30px; align-items: center; gap: 9px; width: 100%; padding: 4px 0; }
.mkt-sector-rank { font-size: 11px; font-weight: 800; color: var(--muted); text-align: center; }
.mkt-sector-name { font-size: 12.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.mkt-sector-bar { height: 6px; border-radius: 999px; background: var(--surface2); overflow: hidden; }
.mkt-sector-fill { display: block; height: 100%; border-radius: 999px; background: var(--accent); transition: width .45s cubic-bezier(.2,.8,.2,1); }
.mkt-sector-fill.today-comp-hi  { background: var(--green);  box-shadow: none; }
.mkt-sector-fill.today-comp-mid { background: var(--yellow); box-shadow: none; }
.mkt-sector-fill.today-comp-lo  { background: var(--accent); box-shadow: none; }
.mkt-sector-val { font-size: 12.5px; font-weight: 800; font-variant-numeric: tabular-nums; text-align: right; background: none !important; box-shadow: none !important; padding: 0; }

/* Sector exposure bars */
.today-secexp { display: flex; align-items: center; gap: 10px; padding: 7px 14px; }
.today-secexp-name { min-width: 96px; font-size: 13px; }
.today-secexp-bar { flex: 1 1 auto; height: 9px; background: rgba(127,127,127,0.12); border-radius: 999px; overflow: hidden; }
.today-secexp-bar > span { display: block; height: 100%; background: linear-gradient(90deg, var(--accent, #3b82f6), #60a5fa); border-radius: 999px; box-shadow: 0 0 8px rgba(59,130,246,0.35); }
.today-secexp-pct { min-width: 44px; text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px; }

@media (max-width: 640px) {
  .today-view { padding: 14px 12px 96px; }
  .today-title { font-size: 22px; }
  .today-row { padding: 10px 12px; font-size: 13.5px; }
  .today-pos-row { grid-template-columns: 1.1fr 0.85fr 0.85fr 0.7fr 0.95fr; font-size: 12px; }
  .today-pos-row > span.today-pos-dist { display: none; }
  .today-pos-head > span:last-child { display: none; }
  /* On phones (single column) fixed heights with nested scroll are awkward —
     let each card grow to its content; the whole page scrolls instead. */
  .today-card { height: auto; }
  .today-card-body { overflow: visible; }
}

/* Tablet portrait (iPad, 641–900px) uses the mobile layout too. Same reasoning
   as phones: on touch, a fixed-height card with an internal scroll region is
   awkward (nested scrolling) and its rows get clipped. Let the cards grow and
   the page (.main) scroll as one surface. */
@media (max-width: 900px) {
  .today-card { height: auto; }
  .today-card-body { overflow: visible; }
}

/* Big iPads (Pro 11"/12.9" landscape, 12.9" portrait) and other 901–1366px
   widths KEEP the desktop layout (docked sidebar + multi-column grids), but the
   fixed desktop shell assumes a tall window and three things break at these
   sizes:
     1. `.main` is `overflow: hidden` and relies on the viewport being tall
        enough — a 1024×1366 portrait dashboard is ~1900px and gets clipped with
        no way to scroll to the bottom. Make `.main` itself scroll.
     2. The 6-tile KPI row crams into a ~740px content column. Let it wrap.
     3. The full desktop header cluster spills a few px past a 1024px viewport.
        Tighten padding/gaps so it fits.
   Real desktops (>1366px) are wide/short enough that none of this applies, so
   the band is capped there and their behaviour is unchanged. */
@media (min-width: 901px) and (max-width: 1366px) {
  .main {
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    min-height: 0;   /* let the flex child shrink so overflow-y can engage */
  }
  .today-kpis { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  header { padding-left: 14px; padding-right: 14px; gap: 12px; }
  .header-right-desktop { gap: 8px; }
}

/* Floating Action Button — bottom-right, always above content but below
   modal backdrops (z-index 1000) so it's hidden behind any open modal. */
.a11y-fab {
  position: fixed;
  bottom: 18px;
  right: 18px;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  border: 2px solid rgba(255,255,255,0.2);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  z-index: 950;
  box-shadow: 0 6px 18px rgba(0,0,0,0.4), 0 2px 6px rgba(0,0,0,0.3);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  display: flex;
  align-items: center;
  justify-content: center;
}
.a11y-fab:hover {
  transform: scale(1.08);
  box-shadow: 0 8px 22px rgba(0,0,0,0.5), 0 3px 8px rgba(0,0,0,0.35);
}
.a11y-fab:active { transform: scale(0.96); }
.a11y-fab:focus-visible {
  outline: 3px solid #60a5fa;
  outline-offset: 2px;
}
@media (max-width: 900px) {
  /* On phones the FAB is replaced by the "♿ Accessibility" item in
     the hamburger menu — less visually noisy for the 95 % of users who
     don't need it, still one tap away for those who do. The
     accessibility statement page text remains accurate.

     EXCEPTION: pre-auth surfaces (landing, login, auth-checking) have
     no hamburger menu — those host the FAB on mobile too, marked with
     the `a11y-fab-preauth` class. The `:not(.a11y-fab-preauth)`
     selector keeps the pre-auth FAB visible while hiding only the
     authenticated-app FAB. */
  .a11y-fab:not(.a11y-fab-preauth) { display: none; }
}

/* Modal card */
.a11y-card {
  width: min(640px, 96vw);
  padding: 34px 38px 26px;
  max-height: min(88vh, 800px);
  overflow-y: auto;
}

/* ── Support / contact modal ─────────────────────────────────── */
.support-card {
  width: min(560px, 96vw);
  padding: 30px 32px 26px;
  max-height: min(90vh, 760px);
  overflow-y: auto;
}
.support-intro {
  font-size: 13px;
  color: var(--muted);
  margin: 6px 0 18px;
  line-height: 1.5;
}
.support-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin: 16px 0 8px;
}
.support-optional { font-weight: 400; color: var(--muted); }
.support-cat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.support-cat {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2, rgba(255,255,255,0.02));
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.support-cat:hover { border-color: var(--accent, #3b82f6); }
.support-cat.is-active {
  border-color: var(--accent, #3b82f6);
  background: color-mix(in srgb, var(--accent, #3b82f6) 12%, transparent);
}
.support-cat-icon { font-size: 17px; flex-shrink: 0; }
.support-cat-label { line-height: 1.25; }
.support-input,
.support-textarea {
  width: 100%;
  box-sizing: border-box;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  padding: 10px 12px;
}
.support-input:focus,
.support-textarea:focus { border-color: var(--accent, #3b82f6); outline: none; }
.support-textarea { resize: vertical; min-height: 110px; line-height: 1.5; }
.support-counter {
  text-align: right;
  font-size: 11px;
  color: var(--muted);
  margin: 4px 2px 0;
}
.support-card .btn-run { width: 100%; margin-top: 18px; }
.support-sent {
  text-align: center;
  padding: 18px 4px 8px;
}
.support-sent-check {
  width: 56px; height: 56px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: var(--green-bg, rgba(34,197,94,0.18));
  color: var(--green, #22c55e);
  font-size: 30px;
  display: flex; align-items: center; justify-content: center;
}
.support-sent p { color: var(--text); font-size: 14px; line-height: 1.55; margin: 0 0 20px; }
.support-sent .btn-run { width: auto; padding: 11px 34px; }
@media (max-width: 480px) {
  .support-cat-grid { grid-template-columns: 1fr; }
}
.a11y-section {
  margin: 24px 0;
}
.a11y-section-title {
  font: 700 13px/1 inherit;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 14px;
}

/* Text-size segmented row */
.a11y-size-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.a11y-size-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 16px 8px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border, rgba(255,255,255,0.10));
  border-radius: 9px;
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.a11y-size-btn:hover {
  background: rgba(255,255,255,0.08);
  border-color: rgba(255,255,255,0.18);
}
.a11y-size-btn.a11y-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.a11y-size-label { font: 700 15px/1 inherit; }
.a11y-size-sub   { font: 500 11px/1 inherit; opacity: 0.7; font-variant-numeric: tabular-nums; }
.a11y-size-mobile-note { display: none; }
@media (max-width: 900px) {
  /* Hide the four sm / default / lg / xl buttons on mobile — Large / XL
     are no-ops here (zoom would break page layout), Small is technically
     functional but never used on a phone, so showing the buttons reads as
     a confusing UI rather than an accessibility control. Section header
     stays so the explanation note below has a contextual title. */
  .a11y-size-row { display: none; }
  .a11y-size-mobile-note {
    display: block;
    margin: 0 2px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--muted);
    background: var(--surface2);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 12px 14px;
  }
  .a11y-size-mobile-note strong { color: var(--text); }
  .a11y-size-mobile-note em     { font-style: italic; color: var(--text); }
}

/* Toggle rows */
.a11y-toggle-row {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px 18px;
  margin-bottom: 10px;
  background: rgba(255,255,255,0.03);
  border: 1px solid var(--border, rgba(255,255,255,0.06));
  border-radius: 9px;
  cursor: pointer;
  user-select: none;
}
.a11y-toggle-row:hover { background: rgba(255,255,255,0.06); }
.a11y-toggle-row input[type="checkbox"] {
  width: 20px; height: 20px;
  accent-color: var(--accent);
  cursor: pointer;
  margin: 2px 0 0;
  flex-shrink: 0;
}
.a11y-toggle-text { flex: 1; line-height: 1.5; }
.a11y-toggle-text strong { font: 700 15px/1.3 inherit; color: var(--text); display: block; margin-bottom: 4px; }
.a11y-toggle-text small  { font: 400 15px/1.55 inherit; color: var(--muted); }

.a11y-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border, rgba(255,255,255,0.06));
}
.a11y-done.btn-run { width: auto; margin: 0; padding: 12px 30px; font-size: 14px; }
/* Reset button — `.btn-preset` is tiny by default (used in scan-panel
   chips); override here so the footer reads as a balanced pair with
   the Done button. */
.a11y-footer .btn-preset {
  padding: 12px 24px;
  font-size: 14px;
  font-weight: 600;
  border-radius: 7px;
  line-height: 1;
}

/* ─── Text-scale modes ─── Use the `zoom` property so the whole visual
   scales (text, padding, charts, icons) the way a browser zoom would.
   font-size on <html> doesn't work here because the app is overwhelmingly
   px-sized (not rem), so font-size cascade has nothing to scale. `zoom`
   is supported in every modern browser including Firefox 126+. */
html.a11y-text-sm { zoom: 0.9; }
html.a11y-text-lg { zoom: 1.15; }
html.a11y-text-xl { zoom: 1.30; }

/* On phones, the desktop zoom factors (1.15 / 1.30) push everything
   that's `width: 100%` past the viewport's right edge — header, trial
   banner, market strip, scanner welcome card all overflow horizontally
   and the user sees the layout "broken" with content cut off when they
   pan. Tighter factors on mobile preserve the same accessibility benefit
   (text scales bigger) without pushing the full-width app shell off the
   side of the screen. */
@media (max-width: 900px) {
  /* On phones, the html `zoom` for Large / Extra Large is disabled —
     CSS `zoom` multiplies layout dimensions as well as text size,
     which on a fixed-width mobile shell causes the trial banner,
     market strip, header, and bottom nav to overflow past the right
     edge of the viewport. Every workaround we tried (overflow-x:
     hidden, max-width: 100vw, viewport-compensation calc()) broke
     another component instead.

     Industry-standard practice on mobile is to defer text scaling to
     the OS (iOS Display & Text Size, Android Font Size), which both
     respect web views at the system level and don't break the page
     they're scaling. The accessibility modal hints at this on phones
     (see modals.jsx) and accessibility.html documents it in §3.

     The OTHER a11y modes — high contrast, reduce motion, colour-blind
     palette — don't multiply dimensions, so they continue to work on
     mobile. Only the text-size component degrades. Small mode (0.9)
     also still works since shrinking can't overflow. */
  html.a11y-text-lg,
  html.a11y-text-xl {
    zoom: 1;
  }
}

/* When zoom > 1, the app layout (100vh #root + overflow:hidden body)
   becomes taller than the visual viewport and the bottom gets clipped.
   Enable page-level vertical scrolling so the user can reach what's
   off-screen. Each in-app panel still scrolls internally too — we're
   just letting the OUTER container grow past the viewport when zoomed. */
html.a11y-text-lg body,
html.a11y-text-xl body {
  overflow-y: auto;
}
html.a11y-text-lg #root,
html.a11y-text-xl #root {
  height: auto;
  min-height: 100vh;
}

/* ─── High contrast ─── Bolder borders, stronger text. Use !important on
   the variables so theme tokens picked up via var() pick the contrast
   palette without per-component overrides. */
html.a11y-high-contrast {
  --border:   rgba(255,255,255,0.45) !important;
  --muted:    #d0d6e0 !important;
}
html.a11y-high-contrast[data-theme="light"] {
  --border:   rgba(0,0,0,0.55) !important;
  --muted:    #1a1f2e !important;
}
html.a11y-high-contrast .modal-card,
html.a11y-high-contrast .scan-panel,
html.a11y-high-contrast .dash-card,
html.a11y-high-contrast .open-trade-card,
html.a11y-high-contrast .equity-strip {
  border-width: 2px !important;
}
html.a11y-high-contrast :focus-visible {
  outline: 3px solid #60a5fa !important;
  outline-offset: 2px !important;
}

/* ─── Reduced motion ─── Kill every transition + animation. Use the
   widest possible selectors so no component sneaks through. */
html.a11y-reduce-motion *,
html.a11y-reduce-motion *::before,
html.a11y-reduce-motion *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  scroll-behavior: auto !important;
}

/* ─── Color-blind safe palette ─── Swap green→blue, red→orange. Targets
   the most common deuteranopia / protanopia cases (red-green confusion).
   We keep semantic positions (positive on the left/up, negative on the
   right/down) so non-colour cues survive. */
html.a11y-colorblind {
  /* Re-map the core colour tokens. Any component using these var()s
     picks up the alternative palette automatically. */
  --green:   #2563eb !important;   /* blue 600   — was emerald */
  --red:     #f59e0b !important;   /* amber 500  — was rose   */
  --yellow:  #14b8a6 !important;   /* teal 500   — was amber  */
  /* Candles re-mapped to the same blue/amber pair so up/down bars in the
     chart pick up the colour-blind palette without the rest of the page
     changing meaning. */
  --candle-up:   #2563eb !important;
  --candle-down: #f59e0b !important;
}
/* Override the hard-coded green/red literals used in inline styles +
   per-component CSS. Catches both #22c55e/#16a34a and #ef4444/#dc2626
   family colours we use throughout (P&L, candle bodies, score chips,
   alert lines, etc.). */
html.a11y-colorblind .n-pos,
html.a11y-colorblind .ret-strong,
html.a11y-colorblind .ret-vstrong,
html.a11y-colorblind .alerts-status-triggered,
html.a11y-colorblind .open-card-pos .open-card-pnl-dollar,
html.a11y-colorblind .open-card-pos .open-card-pnl-r,
html.a11y-colorblind .dash-price-up,
html.a11y-colorblind .exit-prefill-target-hit,
html.a11y-colorblind .metric-pos .open-dash-metric-value {
  color: #2563eb !important;
}
html.a11y-colorblind .n-neg,
html.a11y-colorblind .ret-down,
html.a11y-colorblind .ret-vdown,
html.a11y-colorblind .alerts-row-cancel:hover,
html.a11y-colorblind .open-card-neg .open-card-pnl-dollar,
html.a11y-colorblind .open-card-neg .open-card-pnl-r,
html.a11y-colorblind .dash-price-down,
html.a11y-colorblind .exit-prefill-stop-hit,
html.a11y-colorblind .metric-neg .open-dash-metric-value {
  color: #f59e0b !important;
}
/* Equity-curve fill + chart candles: chart candle bodies/wicks read
   var(--candle-up) / var(--candle-down) via inline style, so they pick
   up the blue/amber pair above automatically. Equity curve fill is
   class-driven and gets remapped via --green/--red. */

/* ── Tooltips ───────────────────
   Triggers are marked `class="tt" data-tt="text"` (+ optional `tt-below`).
   A SINGLETON tooltip element lives directly in <body>, positioned with
   position:fixed by JavaScript (see installTooltipPortal() in app.jsx).
   This is the only way to escape body/.layout/.main, all of which have
   `overflow: hidden` - pseudo-element tooltips would get clipped no matter
   how high we crank z-index. */
.tt { cursor: help; }

.tt-portal {
  position: fixed;
  z-index: 100000;
  /* Gradient backdrop reads as a "panel" rather than a flat label -
     subtle but lifts the box visually off the page. */
  background:
    linear-gradient(180deg,
      rgba(34, 46, 70, 0.98) 0%,
      rgba(22, 30, 48, 0.98) 100%);
  color: #f0f4ff;
  border: 1px solid rgba(99, 102, 241, 0.45);
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.55;
  /* Size to content. No min-width — short labels like "Edit trade"
     deserve a small pill, not a 280px panel that dwarfs the trigger
     it's pointing at. max-width still caps long explanations at a
     readable measure (~70 chars at 13px). */
  max-width: 360px;
  width: max-content;
  text-align: left;
  box-shadow:
    0 18px 38px -8px rgba(0,0,0,0.7),
    0 4px 12px -2px rgba(99,102,241,0.22),
    0 0 0 1px rgba(255,255,255,0.04) inset;
  letter-spacing: 0.15px;
  /* pre-line preserves literal \n in data-tt strings so callers can
     pass multi-line content (equity curve dots, heatmap cells, etc.)
     without HTML — single-line tooltips render unchanged because there
     are no newlines to preserve. */
  white-space: pre-line;
  text-transform: none;
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  pointer-events: none;
  opacity: 0;
  transition: opacity .18s ease, transform .18s ease;
  /* Default: above the trigger. */
  transform: translate(-50%, calc(-100% - 4px));
}
.tt-portal.tt-portal-visible {
  opacity: 1;
  transform: translate(-50%, calc(-100% - 10px));
}
/* Below variant: JS sets `top` to trigger's BOTTOM edge. */
.tt-portal.tt-portal-below {
  transform: translate(-50%, 4px);
}
.tt-portal.tt-portal-below.tt-portal-visible {
  transform: translate(-50%, 10px);
}
[data-theme="light"] .tt-portal {
  background: #1f2937;
  color: #f3f4f6;
}

/* Small triangle arrow on the side facing the trigger.
   `--tt-arrow-shift` lets JS slide the arrow horizontally when the tooltip
   body has been pulled back from a viewport edge - so the arrow stays
   pointed at the trigger even when the body is no longer centered over it. */
.tt-portal::after {
  content: '';
  position: absolute;
  left: calc(50% + var(--tt-arrow-shift, 0px));
  width: 11px;
  height: 11px;
  background: rgb(22, 30, 48);
  border: 1px solid rgba(99, 102, 241, 0.45);
  transform: translateX(-50%) rotate(45deg);
}
.tt-portal:not(.tt-portal-below)::after {
  bottom: -6px;
  border-top: none;
  border-left: none;
}
.tt-portal.tt-portal-below::after {
  top: -6px;
  border-bottom: none;
  border-right: none;
  background: rgb(34, 46, 70);
}


/* ── Trade Journal view ───────────────────────
   `.main` (the right-hand panel that hosts every view) has `overflow:hidden`
   to keep the view-tabs strip fixed at the top. So each view that may grow
   taller than the viewport needs to scroll INSIDE its own slot.
   - flex: 1     → take all the remaining space below the view-tabs
   - min-height: 0 → required for a flex child to allow inner overflow
   - overflow-y: auto → the actual scrollbar */
/* Auto-arm-alerts checkbox in the new-trade form. Sits in a soft orange
   panel so the "🔔" emoji visually connects to the orange alert markers
   on the chart — same colour language across the workflow. */
.auto-arm-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  margin-top: 10px;
  background: rgba(249, 115, 22, 0.07);
  border: 1px solid rgba(249, 115, 22, 0.22);
  border-radius: 6px;
  cursor: pointer;
  font-size: 12.5px;
  color: var(--text);
  user-select: none;
}
.auto-arm-row input[type="checkbox"] {
  width: 14px; height: 14px;
  accent-color: #f97316;
  cursor: pointer;
  margin: 0;
}
.auto-arm-text { line-height: 1.4; }
.auto-arm-price {
  font-family: 'Cascadia Code', Consolas, monospace;
  font-weight: 700;
  color: #f97316;
}

/* Auto-prefill hint under the Exit price field in close mode. Colors
   match the rest of the journal's win/loss semantics — green for
   target reached, red for stop hit, muted grey for "current price". */
.exit-prefill-hint {
  display: block;
  margin-top: 4px;
  font: 600 11px/1.4 inherit;
}
.exit-prefill-target-hit { color: #22c55e; }
.exit-prefill-stop-hit   { color: #ef4444; }
.exit-prefill-live       { color: var(--muted); font-weight: 500; }

/* TradeFormModal action row — equal-height submit + cancel pair.
   `.btn-run` is the global primary button (padding 13px, font 14px,
   margin-top 18px) and `.btn-preset` is a tiny outlined chip (padding
   5/11, font 11). When stacked side-by-side in the modal they looked
   mismatched — fat blue rectangle next to a small grey pill. Equalize
   both vertically here so the visual hierarchy is "same shape, different
   role" instead of "same row, different size class." */
.trade-form-actions {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  align-items: stretch;     /* stretch overrides any per-button height */
}
.trade-form-submit.btn-run {
  /* Kill the global btn-run margin-top + width:100% so the flex row
     controls layout. */
  margin-top: 0;
  width: auto;
  flex: 2;            /* primary action gets the larger share */
  padding: 12px 18px;
}
.trade-form-cancel.btn-preset {
  flex: 1;
  /* Match btn-run vertical padding + font so heights line up exactly. */
  padding: 12px 18px;
  font-size: 14px;
  font-weight: 600;
  border-radius: 8px;
}

/* ── First-run onboarding modal ───────────────────────────────────────
   4-slide wizard. Compact, friendly, easy to skip. Sits above the
   chart modal layer (z-index 1100) because it can appear on top of
   any view including ones that opened mid-session. */

.onboard-backdrop { z-index: 1100; }

.onboard-card {
  /* Large + comfortable — the tour is for learning, not skimming.
     Wide measure for the paragraphs, generous padding, internal scroll
     only on really tight viewports. */
  width: min(820px, 96vw);
  padding: 40px 56px 30px;
  text-align: center;
  max-height: min(880px, 96vh);
  display: flex;
  flex-direction: column;
}

.onboard-progress {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 18px;
  flex-shrink: 0;
}
.onboard-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--border, rgba(255,255,255,0.18));
  border: none;
  padding: 0;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.12s ease;
}
.onboard-dot:hover { transform: scale(1.2); }
.onboard-dot-active {
  background: var(--accent);
  width: 28px;
  border-radius: 5px;
}
.onboard-dot-done {
  background: var(--accent);
  opacity: 0.55;
}

.onboard-emoji {
  font-size: 64px;
  line-height: 1;
  margin: 4px 0 14px;
  /* Text shadow gives a soft glow in the slide's accent colour — the
     `color` is set inline per slide so the shadow inherits it. */
  filter: drop-shadow(0 0 22px currentColor);
}

.onboard-title {
  font: 700 28px/1.2 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--text);
  margin: 0 0 22px;
  letter-spacing: -0.012em;
}
.onboard-body {
  font: 400 15.5px/1.7 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--text);
  margin: 0 auto 24px;
  max-width: 660px;
  /* Scroll internally on dense slides instead of cropping the bullets. */
  flex: 1;
  overflow-y: auto;
  text-align: left;
  padding-right: 6px;
}
.onboard-body p {
  margin: 0 0 14px;
}
.onboard-body p:last-child { margin-bottom: 0; }
.onboard-body strong { font-weight: 700; }
.onboard-body em {
  font-style: italic;
  color: var(--muted);
}
.onboard-bullets {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}
.onboard-bullets li {
  position: relative;
  padding: 6px 0 6px 26px;
  line-height: 1.55;
  font-size: 14.5px;
}
.onboard-bullets li::before {
  content: '▸';
  position: absolute;
  left: 6px;
  top: 6px;
  color: var(--accent);
  font-weight: 700;
  font-size: 16px;
}

.onboard-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border, rgba(255,255,255,0.06));
  flex-shrink: 0;
}
.onboard-actions-right {
  display: flex;
  align-items: center;
  gap: 8px;
}
.onboard-skip {
  font-size: 13px;
  opacity: 0.65;
  padding: 8px 14px;
}
.onboard-skip:hover { opacity: 1; }
.onboard-next,
.onboard-finish {
  width: auto;
  margin-top: 0;
  padding: 12px 28px;
  font-size: 14.5px;
}
.onboard-finish { background: var(--accent2, var(--accent)); }

@media (max-width: 640px) {
  .onboard-card { padding: 28px 22px 22px; max-height: 96vh; }
  .onboard-emoji { font-size: 52px; }
  .onboard-title { font-size: 22px; margin-bottom: 16px; }
  .onboard-body  { font-size: 14px; line-height: 1.6; }
  .onboard-bullets li { font-size: 13.5px; padding-left: 22px; }
  .onboard-next, .onboard-finish { padding: 10px 20px; font-size: 13.5px; }
}

/* CSV export button — fetches with the JWT, then triggers a blob
   download. The disabled state covers both empty-journal and the
   in-flight period while the file is being assembled server-side. */
.trades-export-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.trades-export-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Override `.tt { cursor: help }` for clickable elements in the Trades
   section — the styled tooltip is just hover behaviour, the elements
   themselves are buttons and should keep the pointer cursor. */
.trade-sym.tt,
.btn-sm.tt,
.trades-new-btn.tt,
.trades-quota.tt,
.trades-export-btn.tt,
.open-dash-refresh.tt,
.open-card-anchor-price-btn.tt,
.trade-row-locked-row.tt {
  cursor: pointer;
}
.trades-export-btn.tt:disabled { cursor: not-allowed; }
.trade-row-locked-row.tt { cursor: pointer; }
.open-dash-refresh.tt:disabled { cursor: not-allowed; }

/* ── Equity strip (top of the Trades view) ───────────────────────────
   Reads as: [Cash $X] + [Open positions ±$Y · exposure] = [Total $Z]
   The auto-update badge appears next to the cash number when the user
   has enabled auto_account_size in settings. */

.equity-strip {
  display: flex;
  align-items: stretch;
  gap: 14px;
  padding: 14px 18px;
  margin: 18px 0;
  background: linear-gradient(180deg,
              rgba(99, 102, 241, 0.05) 0%,
              rgba(99, 102, 241, 0)    100%);
  border: 1px solid rgba(99, 102, 241, 0.22);
  border-radius: 10px;
  flex-wrap: wrap;
}
.equity-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  align-items: flex-start;
  position: relative;
}
.equity-block-total { margin-left: auto; align-items: flex-end; }
.equity-lbl {
  font: 500 10px/1 inherit;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.equity-val {
  font: 700 18px/1.1 'Cascadia Code', Consolas, monospace;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.equity-val-total { font-size: 22px; }
.equity-sub {
  font: 500 11px/1 inherit;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.equity-op {
  align-self: center;
  color: var(--muted);
  font: 700 16px/1 inherit;
  user-select: none;
}
.equity-auto-badge {
  display: inline-block;
  background: rgba(99, 102, 241, 0.22);
  color: #818cf8;
  font: 700 9px/1 'Cascadia Code', Consolas, monospace;
  padding: 3px 6px;
  border-radius: 3px;
  letter-spacing: 0.08em;
  margin-top: 2px;
}

@media (max-width: 640px) {
  .equity-strip { padding: 12px 14px; gap: 10px; }
  .equity-op { display: none; }
  .equity-block-total { margin-left: 0; align-items: flex-start; }
  .equity-val { font-size: 16px; }
  .equity-val-total { font-size: 18px; }
}

/* ── Settings → Trading "Auto-update account size" toggle row ───────── */

.auto-account-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  margin: 12px 0 16px;
  background: rgba(99, 102, 241, 0.06);
  border: 1px solid rgba(99, 102, 241, 0.20);
  border-radius: 6px;
  cursor: pointer;
  user-select: none;
}
.auto-account-row input[type="checkbox"] {
  width: 14px; height: 14px;
  accent-color: var(--accent, #6366f1);
  cursor: pointer;
  margin: 2px 0 0;
}
.auto-account-text { font-size: 12.5px; line-height: 1.4; }

/* ── Daily P&L heatmap (in StatsModal, below the equity curve) ──────── */

.pnl-heatmap-wrap {
  margin: 18px 0 8px;
  padding: 14px 16px 12px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--border, rgba(255,255,255,0.06));
  border-radius: 8px;
}
.pnl-heatmap-title {
  font: 700 13px/1.2 inherit;
  color: var(--text);
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}
.pnl-heatmap-sub {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font: 500 11px/1 inherit;
  color: var(--muted);
}
.pnl-heatmap-stat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.pnl-dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 2px;
}
.pnl-dot-pos { background: rgba(34, 197, 94, 0.75); }
.pnl-dot-neg { background: rgba(239, 68, 68, 0.75); }

.pnl-heatmap-scroll {
  overflow-x: auto;
  /* On a narrow modal the 53-week grid is wider than viewport — let it
     scroll horizontally inside its own panel. */
  -webkit-overflow-scrolling: touch;
}
.pnl-heatmap { display: block; }

.pnl-heatmap-legend {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 3px;
  margin-top: 8px;
  font: 600 11px/1 inherit;
  color: var(--muted);
}
.pnl-legend-cell {
  display: inline-block;
  width: 11px; height: 11px;
  border-radius: 2.5px;
}
.pnl-legend-cell-zero {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.06);
}

/* ── Open-trades live dashboard ────────────────────────────────────────
   Renders above the journal table when there are open positions. Card
   grid scales to viewport: 1 col on phones, 2-3 on tablet/desktop. */

.open-trades-dash {
  margin: 18px 0 28px;
  padding: 14px 16px 16px;
  background: linear-gradient(180deg,
              rgba(34, 197, 94, 0.05) 0%,
              rgba(34, 197, 94, 0) 100%);
  border: 1px solid rgba(34, 197, 94, 0.2);
  border-radius: 10px;
}

.open-dash-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  gap: 12px;
  flex-wrap: wrap;
  /* This is a <header> element, so the global `header {}` rule (the app's
     top bar) leaks its chrome in: a border-bottom, a fixed 52px height,
     side padding + safe-area inset, a surface background and z-index. The
     fixed height made the border-bottom draw a divider line THROUGH the
     metric values once the header stacked on mobile. Reset it all so this
     header sizes to its own content with no stray divider. */
  background: none;
  border: none;
  height: auto;
  min-height: 0;
  padding: 0;
  z-index: auto;
}
.open-dash-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: 700 14px/1.2 inherit;
  color: var(--text);
}
.open-dash-pulse {
  color: #22c55e;
  font-size: 10px;
  animation: open-dash-pulse 1.8s ease-in-out infinite;
}
@keyframes open-dash-pulse {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}
.open-dash-count {
  background: rgba(34, 197, 94, 0.2);
  color: #22c55e;
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 11px;
  font-weight: 700;
}
.open-dash-metrics {
  display: inline-flex;
  align-items: center;
  gap: 14px;
}
.open-dash-metric {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.1;
}
.open-dash-metric-label {
  font: 500 10px/1 var(--font-family, inherit);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.open-dash-metric-value {
  font: 700 14px/1.2 'Cascadia Code', Consolas, monospace;
  color: var(--text);
}
.metric-pos .open-dash-metric-value { color: #22c55e; }
.metric-neg .open-dash-metric-value { color: #ef4444; }
.open-dash-refresh {
  background: transparent;
  border: 1px solid var(--border, rgba(255,255,255,0.15));
  color: var(--text);
  border-radius: 6px;
  width: 30px;
  height: 30px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}
.open-dash-refresh:hover { background: rgba(255,255,255,0.06); }
.open-dash-refresh:disabled { opacity: 0.4; cursor: not-allowed; }

/* Card grid */
.open-trades-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}

.open-trade-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  background: var(--surface, #1a1d24);
  border: 1px solid var(--border, rgba(255,255,255,0.08));
  border-left-width: 3px;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: var(--text);
  transition: transform 0.08s ease, border-color 0.15s ease;
}
.open-trade-card:hover {
  transform: translateY(-1px);
  border-color: rgba(255,255,255,0.18);
}
.open-card-pos  { border-left-color: #22c55e; }
.open-card-neg  { border-left-color: #ef4444; }
.open-card-flat { border-left-color: var(--muted); }

.open-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.open-card-sym {
  font: 800 16px/1.1 inherit;
  color: var(--accent);
  letter-spacing: 0.02em;
}
.open-card-side {
  font: 700 9px/1 inherit;
  padding: 2px 5px;
  border-radius: 3px;
  letter-spacing: 0.05em;
}
.open-card-side-long  {
  background: rgba(34, 197, 94, 0.15);
  color: #22c55e;
}
.open-card-side-short {
  background: rgba(239, 68, 68, 0.15);
  color: #ef4444;
}
.open-card-days {
  margin-left: auto;
  font: 500 11px/1 inherit;
  color: var(--muted);
}

.open-card-numbers {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 12px;
}
.open-card-price {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}
.open-card-price-label {
  font: 500 10px/1 inherit;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.open-card-price-value {
  font: 700 18px/1.1 'Cascadia Code', Consolas, monospace;
}

.open-card-pnl {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.1;
  font-family: 'Cascadia Code', Consolas, monospace;
}
.open-card-pnl-dollar {
  font: 700 16px/1.1 inherit;
}
.open-card-pnl-r {
  font: 600 11px/1.1 inherit;
  color: var(--muted);
}
.open-card-pos .open-card-pnl-dollar,
.open-card-pos .open-card-pnl-r       { color: #22c55e; }
.open-card-neg .open-card-pnl-dollar,
.open-card-neg .open-card-pnl-r       { color: #ef4444; }

/* Stop → target progress bar */
.open-card-progress {
  position: relative;
  height: 8px;
  margin: 2px 0 0;
}
.open-card-track {
  position: absolute; inset: 0;
  background: linear-gradient(90deg,
    rgba(239, 68, 68, 0.30) 0%,
    rgba(239, 68, 68, 0.10) 50%,
    rgba(34, 197, 94, 0.10) 50%,
    rgba(34, 197, 94, 0.30) 100%);
  border-radius: 4px;
}
.open-card-fill {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 4px;
  transition: width 0.3s ease;
}
.open-card-entry-tick {
  position: absolute;
  top: -3px;
  width: 2px;
  height: 14px;
  background: var(--muted);
  transform: translateX(-1px);
  border-radius: 1px;
  opacity: 0.55;
}
.open-card-now-dot {
  position: absolute;
  top: -2px;
  width: 12px; height: 12px;
  background: var(--text);
  border: 2px solid var(--surface, #1a1d24);
  border-radius: 50%;
  transform: translateX(-6px);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.3);
  transition: left 0.3s ease;
}
.open-card-pos .open-card-now-dot { background: #22c55e; }
.open-card-neg .open-card-now-dot { background: #ef4444; }

.open-card-anchors {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.open-card-anchor {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}
.open-card-anchor-target { align-items: flex-end; text-align: right; }
.open-card-anchor-label {
  font: 500 9px/1 inherit;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.open-card-anchor-price {
  font: 700 12px/1.2 'Cascadia Code', Consolas, monospace;
  color: var(--text);
}
.open-card-anchor-pct {
  font: 500 10px/1 inherit;
  color: var(--muted);
}
.open-card-anchor-stop   .open-card-anchor-price { color: #ef4444; }
.open-card-anchor-target .open-card-anchor-price { color: #22c55e; }

/* One-tap "close trade" button shown only when the position hits its
   target or stop. Full-width call-to-action under the anchors. */
.open-card-close {
  width: 100%;
  margin-top: 12px;
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid transparent;
  font: 700 12.5px/1.2 inherit;
  cursor: pointer;
  transition: filter .15s ease;
}
.open-card-close:hover { filter: brightness(1.08); }
.open-card-close-target {
  background: rgba(34, 197, 94, 0.16);
  border-color: rgba(34, 197, 94, 0.45);
  color: #22c55e;
}
.open-card-close-stop {
  background: rgba(239, 68, 68, 0.16);
  border-color: rgba(239, 68, 68, 0.45);
  color: #ef4444;
}

/* Click-to-edit price buttons — look like the static price text but
   pick up a subtle underline-on-hover affordance so users know they
   can edit. Shrink to content width and inherit the parent column's
   text alignment so they sit exactly where the static <span> used to
   (stop = left edge, target = right edge). */
.open-card-anchor-price-btn {
  background: transparent;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  text-align: inherit;
  text-decoration: none;
  border-bottom: 1px dashed transparent;
  transition: border-color 0.15s ease, opacity 0.12s ease;
}
.open-card-anchor-stop   .open-card-anchor-price-btn { align-self: flex-start; }
.open-card-anchor-target .open-card-anchor-price-btn { align-self: flex-end; }
.open-card-anchor-price-btn:hover {
  border-bottom-color: currentColor;
}
.open-card-anchor-stop   .open-card-anchor-price-btn { color: #ef4444; }
.open-card-anchor-target .open-card-anchor-price-btn { color: #22c55e; }

/* Inline input that replaces the price during edit. */
.open-card-anchor-editor {
  width: 84px;
  font: 700 12px/1.2 'Cascadia Code', Consolas, monospace;
  background: var(--surface, #1a1d24);
  color: var(--text);
  border: 1px solid var(--accent, #6366f1);
  border-radius: 4px;
  padding: 3px 6px;
  outline: none;
  /* Right-aligned for the target side, left for stop. Cells size the
     same regardless so the row doesn't reflow when editing. */
}
.open-card-anchor-target .open-card-anchor-editor { text-align: right; }
.open-card-anchor-editor:focus { box-shadow: 0 0 0 3px rgba(99,102,241,0.18); }

.open-trade-card.is-editing { cursor: default; }
.open-trade-card.is-editing:hover { transform: none; }

@media (max-width: 640px) {
  .open-trades-dash { padding: 12px; margin: 12px 0 20px; }
  .open-trades-grid { grid-template-columns: 1fr; }
  /* Stack the header: title on its own row, then the metrics on a full-width
     row that spreads Exposure | Unrealized P&L | ↻ edge-to-edge so nothing
     gets clipped on a narrow phone. */
  .open-dash-head {
    flex-direction: column;
    /* MUST override the inherited flex-wrap: wrap — with direction:column,
       wrap makes the children break into a SECOND column beside the title
       instead of stacking, which is what clipped the metrics off-screen. */
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 12px;
    /* Anchor for the absolutely-positioned refresh button (top-right). */
    position: relative;
  }
  .open-dash-metrics {
    width: 100%;
    /* Two metrics left-aligned with a clear gap; the refresh button is
       lifted out of this row (absolute, top-right) so it no longer crowds
       the values or overlaps the card divider below. */
    justify-content: flex-start;
    gap: 36px;
  }
  .open-dash-metric { align-items: flex-start; }
  .open-dash-metric-value { font-size: 15px; }
  /* Park the refresh button on the title row, pinned to the top-right. */
  .open-dash-refresh {
    position: absolute;
    top: 0;
    right: 0;
    flex-shrink: 0;
  }
}

.trades-view {
  padding: 16px 18px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.trades-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0;
  flex-wrap: wrap;
}
.trades-new-btn {
  max-width: 180px;
  margin: 0;
}
.trades-filter-group {
  display: flex;
  gap: 4px;
  background: var(--surface2);
  padding: 3px;
  border-radius: 6px;
}
.trades-filter-group .tab {
  padding: 5px 12px;
  font-size: 12px;
  flex-shrink: 0;
}
/* On phones the 5 status tabs (All / Open / Closed / Wins / Losses)
   AND the calendar period tabs (7d / 14d / 30d / 60d / 90d) overflowed
   the right edge — user couldn't reach the last item. Allow horizontal
   scroll so every tab stays tappable, AND override the base `.tab`
   `min-width: 72px` rule (which forces 5 × 72 = 360px minimum, wider
   than a 400 px phone viewport after container padding). Tighter
   padding + smaller min-width lets the tabs fit naturally on most
   phones without scrolling. */
@media (max-width: 900px) {
  .trades-filter-group {
    overflow-x: auto;
    max-width: 100%;
    -webkit-overflow-scrolling: touch;
  }
  .trades-filter-group .tab {
    min-width: 0;
    padding: 5px 8px;
  }
}
.trades-tag-select {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 6px 10px;
  font-size: 12px;
  cursor: pointer;
}

/* Equity curve container */
.equity-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  margin: 14px 0;
}
.equity-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.equity-sub {
  font-size: 11px;
  color: var(--muted);
  font-weight: 500;
}
.equity-svg { display: block; width: 100%; height: auto; }
.equity-empty {
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 18px;
  text-align: center;
  color: var(--muted);
  font-size: 12px;
  margin: 14px 0;
}

/* ── Modern trades table ─────────────────────── */
.trades-table-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 1px 4px rgba(0,0,0,0.20);
}
.trades-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
}
.trades-table thead th {
  text-align: left;
  padding: 12px 16px;
  color: var(--muted);
  font-weight: 600;
  font-size: 10.5px;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
  background: var(--surface2);
  white-space: nowrap;
  user-select: none;
}
/* Match the first body cell's extra padding (20px) so "SYMBOL" sits directly
   above the symbol pill rather than 4px to its left. */
.trades-table thead th:first-child { padding-left: 20px; }
.trades-table thead th.head-center { text-align: center; }
.trades-table thead th.head-right  { text-align: right;  }

/* Sortable headers ── clickable + arrow indicator */
.trades-table thead th.sortable {
  cursor: pointer;
  transition: color .12s, background .12s;
}
.trades-table thead th.sortable:hover {
  color: var(--text);
  background: var(--surface);
}
.trades-table thead th .sort-arrow {
  display: inline-block;
  margin-left: 5px;
  font-size: 9px;
  opacity: 0.35;
  vertical-align: middle;
  transition: opacity .12s, color .12s;
}
/* Small ⓘ next to a column label that has a `hint` tooltip. Clickable hit
   area is bigger than the glyph so it's easy to grab. */
.trades-table thead th .head-info {
  display: inline-block;
  margin-left: 5px;
  font-size: 11px;
  color: var(--muted);
  cursor: help;
  vertical-align: middle;
  transition: color .12s;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
}
.trades-table thead th .head-info:hover { color: var(--accent); }

/* Stats-bar KPIs with a tooltip get a help cursor + an ⓘ that brightens */
.stat.tt { cursor: help; }
.stat-info {
  display: inline-block;
  margin-left: 4px;
  font-size: 10.5px;
  color: var(--muted);
  opacity: 0.65;
  transition: opacity .12s, color .12s;
}
.stat.tt:hover .stat-info { opacity: 1; color: var(--accent); }
.trades-table thead th.sortable:hover .sort-arrow {
  opacity: 0.75;
}
.trades-table thead th.sort-asc,
.trades-table thead th.sort-desc {
  color: var(--accent);
}
.trades-table thead th.sort-asc .sort-arrow,
.trades-table thead th.sort-desc .sort-arrow {
  opacity: 1;
  color: var(--accent);
}
.trades-table tbody td {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  background: var(--surface);
  transition: background .12s;
}
.trades-table tbody tr:last-child td { border-bottom: none; }
.trade-row:hover td { background: var(--surface2); }

/* Scroll WITHIN the card on both axes: horizontally when the 11 columns
   don't fit, and vertically so the header row (sticky via the global
   `thead th` rule) stays pinned while you read down a long history. The
   bounded max-height is what makes the wrapper the vertical scroll
   container — without it the whole table scrolls with the page and the
   sticky header has nothing to stick to. */
.trades-table-wrap {
  overflow: auto;
  max-height: calc(100vh - 220px);
}
.trades-table      { min-width: 1620px; table-layout: auto; }
/* The sticky header sits over scrolling rows — give it an opaque, slightly
   distinct fill so rows never ghost through, and keep its bottom border. */
.trades-table thead th {
  position: sticky;
  top: 0;
  z-index: 6;
  background: var(--surface2);
}

/* Outcome strip on the left edge of each row */
.trade-row > td:first-child {
  position: relative;
  padding-left: 18px;
}
.trade-row > td:first-child::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--border);
}
.trade-row.trade-row-open  > td:first-child::before { background: #60a5fa; }
.trade-row.trade-win       > td:first-child::before { background: var(--green); }
.trade-row.trade-loss      > td:first-child::before { background: var(--red); }
.trade-row.trade-be        > td:first-child::before { background: var(--muted); }

/* ── Column widths ─────────────────
   Setting consistent min-widths so the horizontal gaps between columns look
   even instead of each column hugging its content. */
.cell-symbol { min-width: 160px; }

.cell-sym-row {
  display: flex;
  align-items: center;
  gap: 9px;
}
.trade-side {
  display: inline-block;
  font-weight: 800;
  font-size: 17px;
  line-height: 1;
}
.trade-side-long  { color: var(--green); }
.trade-side-short { color: var(--red); }
.trade-sym {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--accent);
  font-weight: 700;
  font-size: 13px;
  font-family: 'Cascadia Code', Consolas, monospace;
  letter-spacing: 0.5px;
  cursor: pointer;
  padding: 4px 11px;
  border-radius: 6px;
  transition: background .12s, border-color .12s, transform .08s;
}
.trade-sym:hover {
  background: rgba(59,130,246,0.18);
  border-color: var(--accent);
}
.trade-sym:active { transform: translateY(1px); }

/* Outcome badge under the symbol */
.outcome-badge {
  display: inline-block;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.7px;
  padding: 2px 8px;
  border-radius: 10px;
  border: 1px solid transparent;
}
.outcome-open {
  background: rgba(59,130,246,0.15);
  color: #60a5fa;
  border-color: rgba(59,130,246,0.35);
}
.outcome-win {
  background: var(--green-bg);
  color: var(--green);
  border-color: rgba(34,197,94,0.40);
}
.outcome-loss {
  background: var(--red-bg);
  color: var(--red);
  border-color: rgba(239,68,68,0.40);
}
.outcome-be {
  background: var(--surface2);
  color: var(--muted);
  border-color: var(--border);
}

/* ── Single-value numeric / date cells - uniform widths ─────────────── */
.cell-num   { min-width: 100px; }
.cell-date  { min-width: 165px; }
.num-val {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
}
/* Live (price-fed) values get a subtle dot-prefix so the user can tell
   at a glance which numbers are real-time vs. historical. */
.num-val.live-val { position: relative; padding-left: 12px; }
.num-val.live-val::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 0 rgba(34,197,94,0.55);
  animation: livePulse 2s ease-out infinite;
}
@keyframes livePulse {
  0%   { box-shadow: 0 0 0 0   rgba(34,197,94,0.55); }
  70%  { box-shadow: 0 0 0 5px rgba(34,197,94,0);    }
  100% { box-shadow: 0 0 0 0   rgba(34,197,94,0);    }
}
.date-val {
  font-size: 12px;
  color: var(--muted);
  font-family: 'Cascadia Code', Consolas, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
}
.stack-empty {
  color: var(--muted);
  font-size: 16px;
  opacity: 0.5;
}

/* ── Result columns (R + PnL each in their own cell) ─────────────── */
.cell-r   { min-width: 90px; }
.cell-pnl { min-width: 105px; }
.result-r {
  font-size: 15px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
}
.result-pnl {
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ── Risk plan cell (SL / TP stacked, + distances for open trades) ── */
.cell-plan { min-width: 190px; }
.plan-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.plan-row + .plan-row { margin-top: 4px; }
.plan-lbl {
  display: inline-block;
  width: 22px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: var(--muted);
  text-transform: uppercase;
}
.plan-val { font-weight: 600; }
.plan-stop   { color: var(--red); }
.plan-target { color: var(--green); }

/* Live $ distance shown next to SL/TP for OPEN trades.
   - plan-dist-safe → buffer above stop (good)
   - plan-dist-hit  → already past stop (bad)
   - plan-dist-gap  → still need to reach target (neutral muted)
   - plan-dist-past → already past target (good - consider closing) */
.plan-dist {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 5px;
  font-size: 10.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
}
.plan-dist-safe { background: var(--green-bg); color: var(--green); border: 1px solid rgba(34,197,94,0.35); }
.plan-dist-hit  { background: var(--red-bg);   color: var(--red);   border: 1px solid rgba(239,68,68,0.40); }
.plan-dist-gap  { background: var(--surface2); color: var(--muted); border: 1px solid var(--border); }
.plan-dist-past { background: var(--green-bg); color: var(--green); border: 1px solid rgba(34,197,94,0.35); }

/* ── Shares cell ─────────────── */
.cell-shares { text-align: center; min-width: 90px; }
.shares-num {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.shares-lbl {
  font-size: 9.5px;
  color: var(--muted);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin-top: 2px;
}

/* ── Tags cell ───────────────
   Flex layout instead of margin-based spacing so the chips don't push past
   the cell's bottom border (which made the row-separator line look broken
   under this column). gap handles spacing without any per-chip margins. */
.cell-tags { max-width: 220px; min-width: 160px; }
.cell-tags-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 5px;
  align-items: center;
}
.trade-tag {
  display: inline-flex;
  align-items: center;
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 3px 10px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  line-height: 1.4;
  white-space: nowrap;
}

/* Wrapper td for the action buttons. We keep the td as a normal table-cell
   so the row's bottom border draws continuously across it; the flex layout
   moves to an inner div. */
.cell-actions {
  text-align: right;
  white-space: nowrap;
  min-width: 200px;
}
.cell-actions-inner {
  display: inline-flex;
  gap: 7px;
  align-items: center;
  justify-content: flex-end;
}

/* Generic small button in the trade row. Higher specificity so it can't
   fall back to browser defaults even if cached CSS lingers. */
.trades-table .btn-sm,
.trades-view .btn-sm {
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 12px;
  font-size: 14px;
  font-family: inherit;
  font-weight: 600;
  line-height: 1;
  min-width: 36px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s, transform .08s;
}
.trades-table .btn-sm:hover,
.trades-view .btn-sm:hover {
  background: rgba(59,130,246,0.12);
  border-color: var(--accent);
  color: var(--accent);
}
.trades-table .btn-sm:active,
.trades-view .btn-sm:active { transform: translateY(1px); }

/* Close-trade button - green / "go" emphasis */
.trades-table .btn-close-trade,
.trades-view .btn-close-trade {
  background: var(--green-bg);
  color: var(--green);
  border-color: rgba(34,197,94,0.38);
  font-weight: 700;
  padding: 7px 16px;
  font-size: 12.5px;
}
.trades-table .btn-close-trade:hover,
.trades-view .btn-close-trade:hover {
  background: rgba(34,197,94,0.22);
  border-color: var(--green);
  color: var(--green);
}

/* Edit (✎) - accent on hover */
.trades-table .btn-sm[title="Edit trade"]:hover,
.trades-view  .btn-sm[title="Edit trade"]:hover {
  color: var(--accent);
}

/* Delete (🗑) - red emphasis */
.trades-table .btn-danger-sm,
.trades-view  .btn-danger-sm {
  color: var(--red);
  background: var(--red-bg);
  border-color: rgba(239,68,68,0.32);
}
.trades-table .btn-danger-sm:hover,
.trades-view  .btn-danger-sm:hover {
  background: rgba(239,68,68,0.22);
  border-color: var(--red);
  color: var(--red);
}

/* Trade-form modal */
.modal-trade-card { max-width: 620px; }
.modal-trade-card .field { margin-bottom: 10px; }
.modal-trade-card .field label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 4px;
  letter-spacing: 0.2px;
}

/* Unify every form control in the trade modal: text, number, date, select, textarea */
.modal-trade-card .field input,
.modal-trade-card .field select,
.modal-trade-card .field textarea {
  width: 100%;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 8px 11px;
  font-size: 13px;
  font-family: inherit;
  outline: none;
  transition: border-color .12s, box-shadow .12s, background .12s;
  box-sizing: border-box;
}
.modal-trade-card .field input:focus,
.modal-trade-card .field select:focus,
.modal-trade-card .field textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
}
.modal-trade-card .field input:hover,
.modal-trade-card .field select:hover,
.modal-trade-card .field textarea:hover {
  background: var(--surface);
}

/* Custom select: hide native arrow, draw our own chevron */
.modal-trade-card .field select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  cursor: pointer;
  padding-right: 32px;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--muted) 50%),
    linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position:
    right 14px center,
    right 9px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.modal-trade-card .field select:focus {
  background-image:
    linear-gradient(45deg, transparent 50%, var(--accent) 50%),
    linear-gradient(135deg, var(--accent) 50%, transparent 50%);
}

/* Native date / datetime picker: nice dark-mode icon */
.modal-trade-card .field input[type="date"],
.modal-trade-card .field input[type="datetime-local"] {
  cursor: pointer;
  position: relative;
  font-variant-numeric: tabular-nums;
}
.modal-trade-card .field input[type="date"]::-webkit-calendar-picker-indicator,
.modal-trade-card .field input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  filter: invert(0.6);
  cursor: pointer;
  opacity: 0.85;
  transition: opacity .12s;
}
.modal-trade-card .field input[type="date"]:hover::-webkit-calendar-picker-indicator,
.modal-trade-card .field input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator { opacity: 1; }
[data-theme="light"] .modal-trade-card .field input[type="date"]::-webkit-calendar-picker-indicator,
[data-theme="light"] .modal-trade-card .field input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  filter: none;
}

/* Number-spinner: remove ugly default arrows */
.modal-trade-card .field input[type="number"]::-webkit-outer-spin-button,
.modal-trade-card .field input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.modal-trade-card .field input[type="number"] { -moz-appearance: textfield; }

/* Textarea sizing */
.modal-trade-card .field textarea {
  resize: vertical;
  min-height: 70px;
  line-height: 1.5;
}

/* Two-up grid */
.form-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 14px;
}

/* Section divider inside the form */
.trade-section-sep {
  height: 1px;
  background: var(--border);
  margin: 18px 0 12px;
}
.trade-section-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 10px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}

/* Bottom action row - Submit + Cancel side-by-side, proportioned */
.modal-trade-card form > div:last-child {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.modal-trade-card .btn-run {
  flex: 2;
  width: auto;
  max-width: none;
  padding: 10px 18px;
  font-size: 13px;
}
.modal-trade-card .btn-preset {
  flex: 1;
  padding: 10px 18px;
  font-size: 13px;
}

/* CTA row above the trades table - "View detailed statistics".
   Above the table so it stays visible even when many entries are logged. */
.stats-cta-row {
  margin: 4px 0 14px;
  text-align: center;
}
.btn-stats-open {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 12px 22px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s, transform .08s;
  letter-spacing: 0.3px;
}
.btn-stats-open:hover {
  background: rgba(59,130,246,0.10);
  border-color: var(--accent);
  color: var(--accent);
}
.btn-stats-open:active { transform: translateY(1px); }

/* Stats modal - wider than other modals to fit the equity chart */
.modal-stats-card {
  /* Wide enough that the eight-metric stats row sits comfortably on one line
     at full size ("Open / Closed" and "Total P&L" were getting crushed in the
     old 960px card). */
  max-width: 1340px;
  width: 94vw;
  max-height: 92vh;
  overflow-y: auto;
}

/* Inside the (narrower) stats modal the full-width flex stats row crushed the
   wider values — "Open / Closed" and "Total P&L" overflowed their cells. Lay
   them out as a tidy 4-up grid (2 on phones) so every value gets room. Scoped
   to the modal so the full-page trades-view band keeps its single flex row. */
/* Keep the original single-row flex style (matching the full-page trades
   band) — just give it room: trim the inter-stat padding a little and center
   the row so the metrics breathe instead of crowding the right edge. Below
   720px the base rule already switches this to a wrapping grid for phones. */
.modal-stats-card .stats-bar {
  justify-content: center;
  flex-wrap: nowrap;
  overflow-x: auto;            /* never crush — scroll if a tiny screen can't fit */
}
.modal-stats-card .stat {
  flex-shrink: 0;             /* keep each metric at its natural width */
  padding-right: 18px;
}
.modal-stats-card .stat + .stat { padding-left: 18px; }
/* Full-size values (same as the page band) — the wider card gives them room.
   nowrap stops the label/value from wrapping inside a squeezed cell. */
.modal-stats-card .stat-lbl { white-space: nowrap; }
.modal-stats-card .stat-val { white-space: nowrap; }

/* Period selector inside the stats modal */
.stats-period-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 12px 0 4px;
  flex-wrap: wrap;
}
.stats-period-lbl {
  font-size: 11px;
  color: var(--muted);
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.stats-period-group {
  display: flex;
  gap: 4px;
  background: var(--surface2);
  padding: 3px;
  border-radius: 6px;
  flex-wrap: wrap;
}
.stats-period-group .tab {
  padding: 6px 12px;
  font-size: 12px;
  white-space: nowrap;
}

/* Custom range date pickers */
.stats-custom-range {
  display: flex;
  gap: 14px;
  margin-top: 10px;
  padding: 12px 14px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.stats-range-field { flex: 1; margin-bottom: 0; }
.stats-range-field label {
  display: block;
  font-size: 10.5px;
  color: var(--muted);
  letter-spacing: 0.3px;
  margin-bottom: 4px;
  text-transform: uppercase;
  font-weight: 700;
}
.stats-range-field input {
  width: 100%;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
}
.stats-range-field input::-webkit-calendar-picker-indicator {
  filter: invert(0.6);
  cursor: pointer;
}
[data-theme="light"] .stats-range-field input::-webkit-calendar-picker-indicator { filter: none; }

/* Range hint */
.stats-range-hint {
  margin: 10px 0;
  padding: 8px 12px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 12px;
  color: var(--muted);
  font-family: 'Cascadia Code', Consolas, monospace;
}
.stats-range-hint strong { color: var(--accent); font-weight: 700; }

.stats-loading {
  padding: 28px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

/* Breakdowns */
.breakdowns-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
  margin: 18px 0;
}
.breakdown-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
}
.breakdown-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
}
.breakdown-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.breakdown-table th {
  text-align: left;
  padding: 5px 8px;
  color: var(--muted);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}
.breakdown-table td {
  padding: 5px 8px;
  border-bottom: 1px solid var(--border);
}
.breakdown-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.breakdown-table tr:last-child td { border-bottom: none; }

@media (max-width: 900px) {
  .breakdowns-row { grid-template-columns: 1fr; }
  .form-grid-2    { grid-template-columns: 1fr; }
}

/* ── Backtest view ─────────────────────────── */
.bt-view { padding: 16px 18px; }

/* Educational explainer at the top of the page */
.bt-explainer {
  background: linear-gradient(180deg, rgba(59,130,246,0.06), var(--surface));
  border: 1px solid var(--border);
  border-radius: 10px;
  margin-bottom: 16px;
  overflow: hidden;
  transition: border-color .15s;
}
.bt-explainer-open {
  border-color: rgba(59,130,246,0.40);
}
.bt-explainer-toggle {
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  display: grid;
  grid-template-columns: 30px 1fr 14px;
  grid-template-rows: auto auto;
  grid-template-areas:
    "icon title caret"
    "icon sub   caret";
  align-items: center;
  gap: 2px 12px;
  padding: 14px 16px;
  cursor: pointer;
  color: var(--text);
  transition: background .12s;
}
.bt-explainer-toggle:hover { background: rgba(59,130,246,0.06); }
.bt-explainer-icon {
  grid-area: icon;
  font-size: 22px;
  align-self: center;
}
.bt-explainer-title {
  grid-area: title;
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.2px;
}
.bt-explainer-sub {
  grid-area: sub;
  font-size: 11.5px;
  color: var(--muted);
  font-weight: 500;
}
.bt-explainer-caret {
  grid-area: caret;
  font-size: 14px;
  color: var(--muted);
  align-self: center;
}

.bt-explainer-body {
  padding: 8px 22px 20px 22px;
  border-top: 1px solid var(--border);
}
.bt-explainer-section {
  margin: 18px 0;
}
.bt-explainer-section h4 {
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.3px;
}
.bt-explainer-section p,
.bt-explainer-section ul,
.bt-explainer-section li {
  font-size: 12.5px;
  color: var(--text);
  line-height: 1.65;
  margin: 6px 0;
}
.bt-explainer-section ul { padding-left: 22px; }
.bt-explainer-section code {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 11.5px;
  color: var(--accent);
}
.bt-explainer-section .n-pos { color: var(--green); }
.bt-explainer-section .n-neg { color: var(--red); }

.bt-formula {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 12px 14px;
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 12px;
  color: var(--text);
  line-height: 1.55;
  white-space: pre-wrap;
  margin: 8px 0;
}

/* Reward:risk reference table */
.bt-rr-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  margin-top: 6px;
}
.bt-rr-table th {
  text-align: left;
  padding: 8px 10px;
  background: var(--surface2);
  color: var(--muted);
  font-weight: 600;
  font-size: 10.5px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  border-bottom: 1px solid var(--border);
}
.bt-rr-table th.num,
.bt-rr-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.bt-rr-table td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
.bt-rr-table tr:last-child td { border-bottom: none; }
.bt-rr-row-highlight td {
  background: rgba(59,130,246,0.10);
  color: var(--accent);
}
.bt-rr-row-highlight td strong { color: var(--accent); }

.bt-quote {
  background: var(--surface2);
  border-left: 3px solid var(--accent);
  padding: 10px 14px;
  margin: 12px 0 0 !important;
  font-size: 12.5px;
  color: var(--text);
  border-radius: 0 6px 6px 0;
}

/* Live R:R + breakeven panel inside the form */
/* ─────────────────────────────────────────────────────────────────
   Strategy toggles - color-coded cards matching the section style.
   Each toggle binds its own --sec-r/g/b tuple so border / hover /
   pill / focus glow all pick up the same accent automatically.
   ───────────────────────────────────────────────────────────────── */

.bt-toggles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 12px 0 6px;
}

/* The label-as-toggle and the outer card share most styling.
   bt-toggle is used directly when the toggle has no sub-fields;
   bt-toggle-card wraps a bt-toggle PLUS sub-fields underneath. */

.bt-toggle,
.bt-toggle-card {
  --sec-r: 100;
  --sec-g: 116;
  --sec-b: 139;
  position: relative;
  background:
    linear-gradient(135deg,
      rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.05) 0%,
      rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.015) 55%,
      transparent 100%),
    var(--surface2);
  border: 1px solid var(--border);
  border-radius: 9px;
  overflow: hidden;
  transition:
    transform 140ms ease,
    box-shadow 140ms ease,
    border-color 140ms ease;
}
.bt-toggle::before,
.bt-toggle-card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-radius: 9px 0 0 9px;
  opacity: 0.4;
  transition: opacity 140ms ease;
}
.bt-toggle.on::before,
.bt-toggle-card.on::before { opacity: 1; }

.bt-toggle:hover,
.bt-toggle-card:hover {
  transform: translateY(-1px);
  border-color: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.45);
  box-shadow:
    0 3px 10px -4px rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.25),
    0 1px 0 rgba(255,255,255,0.04) inset;
}

/* The clickable label itself */
.bt-toggle,
.bt-toggle-card .bt-toggle {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px 13px 16px;
  cursor: pointer;
}
/* When the label is inside a card, drop the duplicate border/bg/stripe */
.bt-toggle-bare {
  background: none !important;
  border: none !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: 12px 14px 13px 16px;
}
.bt-toggle-bare::before { display: none !important; }
.bt-toggle-bare:hover {
  transform: none !important;
  box-shadow: none !important;
  border: none !important;
}

/* Hidden visually but accessible (we draw our own check) */
.bt-toggle input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  margin: 3px 0 0;
  width: 18px;
  height: 18px;
  border-radius: 5px;
  border: 1.5px solid rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.5);
  background: var(--surface);
  cursor: pointer;
  position: relative;
  transition: background 140ms ease, border-color 140ms ease;
}
.bt-toggle input[type="checkbox"]:hover {
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}
.bt-toggle input[type="checkbox"]:checked {
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}
.bt-toggle input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 6px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2.2px 2.2px 0;
  transform: rotate(45deg);
}
.bt-toggle input[type="checkbox"]:focus-visible {
  outline: 2px solid rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.6);
  outline-offset: 2px;
}

.bt-toggle-text {
  display: flex;
  flex-direction: column;
  gap: 5px;
  line-height: 1.45;
  flex: 1;
  min-width: 0;
}
.bt-toggle-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.bt-toggle-icon {
  font-size: 16px;
  line-height: 1;
}
.bt-toggle-title {
  font-size: 14.5px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.1px;
}
.bt-toggle-pill {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.2px;
  padding: 2.5px 8px;
  border-radius: 999px;
  background: var(--surface3);
  color: var(--muted);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  transition: background 140ms ease, color 140ms ease;
}
.bt-toggle.on .bt-toggle-pill,
.bt-toggle-card.on .bt-toggle-pill {
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
}
.bt-toggle-sub {
  font-size: 12.5px;
  color: var(--muted);
  line-height: 1.55;
}

/* Sub-fields appear inside the toggle card when the toggle is ON.
   They share the card's accent color, including focus glow. */
.bt-toggle-subfields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px 10px;
  padding: 0 12px 11px 14px;
  margin-top: -2px;
  border-top: 1px solid rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.18);
  padding-top: 10px;
}
.bt-toggle-subfields .field { margin-bottom: 0; }
.bt-toggle-subfields .field label {
  display: block;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  color: var(--muted);
  text-transform: uppercase;
  margin-bottom: 3px;
}
.bt-toggle-subfields .field input {
  width: 100%;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 5px 8px;
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-family: inherit;
  outline: none;
  transition:
    border-color 120ms ease,
    box-shadow 120ms ease,
    background 120ms ease;
  box-sizing: border-box;
}
.bt-toggle-subfields .field input:hover { background: var(--surface2); }
.bt-toggle-subfields .field input:focus {
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  box-shadow: 0 0 0 2px rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.18);
}
.bt-toggle-subfields .field input[type="number"]::-webkit-outer-spin-button,
.bt-toggle-subfields .field input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
.bt-toggle-subfields .field input[type="number"] { -moz-appearance: textfield; }

/* ── Per-toggle color tuples ──────────────────────────────────── */
.bt-toggle-regime { --sec-r:  99; --sec-g: 102; --sec-b: 241; }  /* indigo */
.bt-toggle-trail  { --sec-r:  20; --sec-g: 184; --sec-b: 166; }  /* teal   */

/* Responsive - stack toggles on narrow screens */
@media (max-width: 900px) {
  .bt-toggles { grid-template-columns: 1fr; }
  .bt-toggle-subfields { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 480px) {
  .bt-toggle-subfields { grid-template-columns: 1fr; }
}

.bt-rr-preview {
  display: flex;
  gap: 18px;
  align-items: center;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 18px;
  margin-top: 16px;
}
.bt-rr-block {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.bt-rr-lbl {
  font-size: 10px;
  color: var(--muted);
  letter-spacing: 0.6px;
  font-weight: 700;
  text-transform: uppercase;
}
.bt-rr-val {
  font-size: 16px;
  font-weight: 800;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
}

/* Tweak the form-label ⓘ icon so it inherits the form's small style */
.bt-form .field label .head-info {
  font-size: 11px;
  margin-left: 4px;
  opacity: 0.7;
  text-transform: none;
  letter-spacing: 0;
}
.bt-form .field label .head-info:hover { opacity: 1; color: var(--accent); }

.bt-form {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px 20px;
  margin-bottom: 16px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.18);
}
.bt-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px 16px;
}

/* ─────────────────────────────────────────────────────────────────
   Modernized filter sections - color-coded cards, symmetric grids
   ───────────────────────────────────────────────────────────────── */

.bt-sections {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.bt-section {
  /* Each section binds its accent color via --sec-r/g/b so the same
     selector drives border, header color, focus glow, and hover shadow
     without duplicating the tuple. */
  --sec-r: 100;
  --sec-g: 116;
  --sec-b: 139;

  position: relative;
  background:
    linear-gradient(135deg,
      rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.05) 0%,
      rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.015) 55%,
      transparent 100%),
    var(--surface2);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 9px 11px 10px;
  overflow: hidden;
  transition:
    transform 140ms ease,
    box-shadow 140ms ease,
    border-color 140ms ease;
}
.bt-section::before {
  /* Colored stripe along the left edge */
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-radius: 9px 0 0 9px;
}
.bt-section:hover {
  transform: translateY(-1px);
  border-color: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.45);
  box-shadow:
    0 3px 10px -4px rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.25),
    0 1px 0 rgba(255,255,255,0.04) inset;
}

/* Section header - icon + title (compact) */
.bt-section-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 7px;
  padding-bottom: 5px;
  border-bottom: 1px solid rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.15);
}
.bt-section-icon {
  font-size: 12px;
  line-height: 1;
  filter: saturate(1.1);
}
.bt-section-title {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  white-space: nowrap;
}

/* Field grids inside each section */
.bt-section-fields {
  display: grid;
  gap: 7px 10px;
}
.bt-section-grid-1 { grid-template-columns: 1fr; }
.bt-section-grid-2 { grid-template-columns: 1fr 1fr; }
.bt-section-grid-3 { grid-template-columns: 1fr 1fr 1fr; }

/* Labels - small + tight */
.bt-section .field { margin-bottom: 0; }
.bt-section .field label {
  display: block;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.4px;
  color: var(--muted);
  text-transform: uppercase;
  margin-bottom: 3px;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Inputs - compact, section-colored focus */
.bt-section .field input {
  width: 100%;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 5px 8px;
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-family: inherit;
  outline: none;
  transition:
    border-color 120ms ease,
    box-shadow 120ms ease,
    background 120ms ease;
  box-sizing: border-box;
}
.bt-section .field input:hover { background: var(--surface2); }
.bt-section .field input:focus {
  background: var(--surface);
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  box-shadow:
    0 0 0 2px rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.18);
}
.bt-section .field input[type="date"] { cursor: pointer; }
.bt-section .field input[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(0.6); cursor: pointer; opacity: 0.85;
}
[data-theme="light"] .bt-section .field input[type="date"]::-webkit-calendar-picker-indicator {
  filter: none;
}
.bt-section .field input[type="number"]::-webkit-outer-spin-button,
.bt-section .field input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
.bt-section .field input[type="number"] { -moz-appearance: textfield; }

/* ── Per-section color tuples ─────────────────────────────────── */
.bt-section-dates    { --sec-r:  59; --sec-g: 130; --sec-b: 246; }  /* blue    */
.bt-section-signal   { --sec-r: 139; --sec-g:  92; --sec-b: 246; }  /* violet  */
.bt-section-capital  { --sec-r:  16; --sec-g: 185; --sec-b: 129; }  /* green   */
.bt-section-exits    { --sec-r: 245; --sec-g: 158; --sec-b:  11; }  /* amber   */
.bt-section-position { --sec-r:   6; --sec-g: 182; --sec-b: 212; }  /* cyan    */
.bt-section-earnings { --sec-r: 236; --sec-g:  72; --sec-b: 153; }  /* pink    */

/* ── Responsive ────────────────────────────────────────────────── */
@media (max-width: 1100px) {
  .bt-sections { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 900px) {
  .bt-sections { grid-template-columns: 1fr; }
  .bt-section-grid-3 { grid-template-columns: 1fr 1fr 1fr; }
}
@media (max-width: 480px) {
  .bt-section-grid-3 { grid-template-columns: 1fr 1fr; }
  /* Stop here at 2 columns by default — works for short labels. */
  .bt-section-grid-2 { grid-template-columns: 1fr 1fr; }
}
/* At phone widths the 2-column grid (e.g. FROM / TO date range) gives
   each cell ~140 px, which clips the native date picker's value +
   calendar icon ("09/06/2026" gets cut on the right). Collapse to a
   single column so every input gets the full row. Also kicks in for
   the 3-col grids when they have already collapsed to 2-col. */
@media (max-width: 420px) {
  .bt-section-grid-2,
  .bt-section-grid-3 { grid-template-columns: 1fr; }
}
.bt-form .field { margin-bottom: 0; }
.bt-form .field label {
  display: block;
  font-size: 10.5px;
  color: var(--muted);
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  margin-bottom: 4px;
}
.bt-form .field input {
  width: 100%;
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 11px;
  font-size: 13px;
  outline: none;
  transition: border-color .12s, box-shadow .12s;
  font-variant-numeric: tabular-nums;
  font-family: inherit;
  box-sizing: border-box;
}
.bt-form .field input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
}
.bt-form .field input[type="date"] { cursor: pointer; }
.bt-form .field input[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(0.6); cursor: pointer; opacity: 0.85;
}
[data-theme="light"] .bt-form .field input[type="date"]::-webkit-calendar-picker-indicator {
  filter: none;
}
.bt-form .field input[type="number"]::-webkit-outer-spin-button,
.bt-form .field input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
.bt-form .field input[type="number"] { -moz-appearance: textfield; }

.bt-form-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.bt-run-btn {
  /* Centered primary CTA - override the default .btn-run width: 100%
     so the button sizes to its content + padding instead of stretching
     across the entire form. */
  width: auto;
  margin-top: 0;
  padding: 12px 36px;
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  min-width: 220px;
  max-width: 320px;
}
/* Abort variant - shown while a backtest is running */
.bt-abort-btn {
  background: var(--red, #ef4444) !important;
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.bt-abort-btn:hover:not(:disabled) {
  background: #dc2626 !important;
}
.bt-abort-btn:focus-visible {
  outline: 3px solid rgba(239, 68, 68, 0.35);
  outline-offset: 2px;
}
/* Spinner ring inside the Abort button - communicates "in flight" */
.bt-run-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: bt-run-spin 0.8s linear infinite;
}
@keyframes bt-run-spin {
  to { transform: rotate(360deg); }
}
.bt-info-hint {
  /* Sits centered on a second row, smaller and muted */
  font-size: 11.5px;
  color: var(--muted);
  font-family: 'Cascadia Code', Consolas, monospace;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  text-align: center;
}
.bt-info-hint strong { color: var(--accent); font-weight: 700; }

/* ── Field-level validation styling ───────────────────────────────
   Applied when fieldErrors[key] returns truthy. Red border + glow
   on the input, red error caption below. Works across the section
   cards (which set their own accent color via --sec-r/g/b on the
   wrapper) and the trail-stop sub-fields (same treatment). */
.bt-section .field-invalid input,
.bt-toggle-subfields .field-invalid input {
  border-color: #ef4444 !important;
  box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.18) !important;
  background: rgba(239, 68, 68, 0.05);
}
.bt-section .field-invalid label,
.bt-toggle-subfields .field-invalid label {
  color: #ef4444;
}
.field-err {
  display: block;
  margin-top: 4px;
  color: #ef4444;
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0.1px;
}

/* Validation summary that appears under the disabled Run button */
.bt-validation-summary {
  margin-top: 2px;
  padding: 7px 14px;
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.35);
  border-radius: 6px;
  color: #f87171;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  text-align: center;
  max-width: 480px;
}

.bt-sched-pill {
  display: inline-flex;
  align-items: center;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 2px 9px;
  border-radius: 10px;
  border: 1px solid;
  font-family: 'Segoe UI', system-ui, sans-serif;
  text-transform: uppercase;
  cursor: help;
}
.bt-sched-on  {
  color: var(--green);
  background: var(--green-bg);
  border-color: rgba(34,197,94,0.35);
}
.bt-sched-off {
  color: var(--muted);
  background: var(--surface2);
  border-color: var(--border);
}

/* ─────────────────────────────────────────────────────────────────
   Saved Configs section - card grid with active-state detection.
   Uses an amber/gold accent so it's visually distinct from the six
   strategy sections above and the regime/trail toggles.
   ───────────────────────────────────────────────────────────────── */

.bt-presets-section {
  --sec-r: 251;
  --sec-g: 146;
  --sec-b: 60;     /* orange-400 - warm, distinctive */

  position: relative;
  margin-top: 16px;
  padding: 12px 14px 14px;
  background:
    linear-gradient(135deg,
      rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.05) 0%,
      rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.015) 55%,
      transparent 100%),
    var(--surface2);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.bt-presets-section::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-radius: 10px 0 0 10px;
}

/* Section header - icon + title + count badge */
.bt-presets-head {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.15);
}
.bt-presets-icon {
  font-size: 13px;
  line-height: 1;
}
.bt-presets-title {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}
.bt-presets-count {
  margin-left: auto;
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
  padding: 1px 9px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 800;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.3px;
  transition: background 140ms ease;
}
/* When at the cap, swap to a muted-red pill so it reads as "blocked" */
.bt-presets-count-full {
  background: var(--red, #ef4444);
}

/* Inline message shown in place of the save CTA when at the limit */
.bt-preset-limit-msg {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: rgba(239, 68, 68, 0.08);
  border: 1px solid rgba(239, 68, 68, 0.30);
  border-radius: 6px;
  color: #f87171;
  font-size: 12px;
  line-height: 1.45;
  font-weight: 500;
}
.bt-preset-limit-msg strong { color: #fca5a5; font-weight: 800; }
.bt-preset-limit-icon { font-size: 16px; line-height: 1; flex-shrink: 0; }

/* Empty state */
.bt-presets-empty {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 7px;
  margin-bottom: 10px;
}
.bt-presets-empty-icon {
  font-size: 22px;
  line-height: 1;
  flex-shrink: 0;
}
.bt-presets-empty-text {
  font-size: 12px;
  line-height: 1.55;
  color: var(--muted);
}
.bt-presets-empty-text strong { color: var(--text); }

/* Card grid */
.bt-preset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}

/* Each preset card */
.bt-preset-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 10px 11px 11px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  transition: border-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.bt-preset-card:hover {
  border-color: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.45);
  transform: translateY(-1px);
  box-shadow: 0 3px 10px -4px rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.30);
}
.bt-preset-card-active {
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  background:
    linear-gradient(135deg,
      rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.10) 0%,
      transparent 65%),
    var(--surface);
  box-shadow: 0 0 0 1px rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.35);
}
.bt-preset-card-badge {
  position: absolute;
  top: 0;
  right: 0;
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 1.2px;
  padding: 2px 6px;
  border-bottom-left-radius: 5px;
  border-top-right-radius: 7px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

.bt-preset-card-head {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 18px;
}
.bt-preset-card-name {
  flex: 1;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 42px;   /* room for the ACTIVE badge */
  letter-spacing: 0.1px;
}
.bt-preset-card-active .bt-preset-card-name { padding-right: 56px; }
.bt-preset-card-del {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 0 6px;
  border-radius: 4px;
  flex-shrink: 0;
}
.bt-preset-card-del:hover {
  background: var(--red, #ef4444);
  color: #fff;
}

/* Mini-preview chips on each card */
.bt-preset-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.bt-preset-card-chip {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 10.5px;
  font-weight: 600;
  padding: 2px 7px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--muted);
  white-space: nowrap;
}
.bt-preset-card-chip-on {
  background: rgba(74, 222, 128, 0.12);
  color: #4ade80;
  border-color: rgba(74, 222, 128, 0.35);
}

/* Load button - full width at the bottom of the card */
.bt-preset-card-load {
  margin-top: 2px;
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 6px 10px;
  border-radius: 5px;
  font-size: 11.5px;
  font-weight: 700;
  cursor: pointer;
  transition: all 120ms ease;
  letter-spacing: 0.2px;
}
.bt-preset-card-load:hover:not(:disabled) {
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
}
.bt-preset-card-active .bt-preset-card-load {
  background: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.12);
  border-color: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.4);
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  cursor: default;
  opacity: 0.95;
}

/* "+ Save current config as preset" - dashed-border CTA when collapsed */
.bt-preset-save-cta {
  display: block;
  width: 100%;
  background: transparent;
  border: 1px dashed rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.4);
  color: var(--muted);
  padding: 9px 14px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 120ms ease;
  letter-spacing: 0.2px;
}
.bt-preset-save-cta:hover {
  border-color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-style: solid;
  background: rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.06);
  color: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
}

/* Inline save form (revealed when CTA is clicked) */
.bt-preset-save-form {
  display: flex;
  gap: 6px;
  align-items: stretch;
}
.bt-preset-save-form input {
  flex: 1;
  background: var(--surface);
  color: var(--text);
  border: 1px solid rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  border-radius: 5px;
  padding: 7px 11px;
  font-size: 12.5px;
  font-weight: 500;
  outline: none;
  font-family: inherit;
}
.bt-preset-save-form input:focus {
  box-shadow: 0 0 0 2px rgba(var(--sec-r), var(--sec-g), var(--sec-b), 0.22);
}
.bt-preset-save-btn {
  background: rgb(var(--sec-r), var(--sec-g), var(--sec-b));
  color: #fff;
  border: none;
  padding: 7px 18px;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: background 120ms ease;
}
.bt-preset-save-btn:hover:not(:disabled) { background: #ea7c2a; }
.bt-preset-save-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.bt-preset-cancel-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 7px 14px;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 120ms ease;
}
.bt-preset-cancel-btn:hover {
  color: var(--text);
  border-color: var(--text);
}

/* Diagnostic banner shown above the equity chart - explains whether the
   composite_min floor or the max_concurrent ceiling drove the trade selection. */
.bt-diag {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 16px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  margin: 14px 0;
  font-size: 12.5px;
  line-height: 1.5;
}
.bt-diag-head {
  font-weight: 700;
  letter-spacing: 0.2px;
}
.bt-diag-body { color: var(--text); }
.bt-diag-body code {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 11px;
  color: var(--accent);
}
.bt-diag-body strong { color: var(--text); }

.bt-diag-warn {
  background: rgba(234,179,8,0.10);
  border-color: rgba(234,179,8,0.40);
}
.bt-diag-warn .bt-diag-head { color: #eab308; }

.bt-diag-info {
  background: rgba(59,130,246,0.08);
  border-color: rgba(59,130,246,0.35);
}
.bt-diag-info .bt-diag-head { color: var(--accent); }

.bt-diag-ok {
  background: var(--green-bg);
  border-color: rgba(34,197,94,0.35);
}
.bt-diag-ok .bt-diag-head { color: var(--green); }

.bt-equity-wrap { margin-bottom: 18px; }

.bt-trades-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 18px 0 10px;
  gap: 14px;
}
.bt-section-title {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.3px;
}

.bt-trades-table { min-width: 1320px; }

.bt-exit-pill {
  display: inline-block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.6px;
  padding: 2px 8px;
  border-radius: 10px;
  border: 1px solid transparent;
}
.bt-exit-target       { background: var(--green-bg);          color: var(--green);  border-color: rgba(34,197,94,0.40); }
.bt-exit-stop         { background: var(--red-bg);            color: var(--red);    border-color: rgba(239,68,68,0.40); }
.bt-exit-timeout      { background: rgba(234,179,8,0.15);     color: #eab308;       border-color: rgba(234,179,8,0.35); }
.bt-exit-end          { background: var(--surface2);          color: var(--muted);  border-color: var(--border); }
.bt-exit-pre_earnings { background: rgba(167,139,250,0.12);   color: #a78bfa;       border-color: rgba(167,139,250,0.45); }

/* Earnings-filter comparison panel */
.bt-compare-toggle-row {
  display: flex;
  justify-content: center;
  margin: 14px 0 0;
}
.bt-compare-toggle-row .btn-preset {
  padding: 8px 16px;
  font-size: 12.5px;
  font-weight: 700;
}
.bt-compare-toggle-row .btn-preset.bt-cmp-on {
  background: rgba(59,130,246,0.12);
  border-color: var(--accent);
  color: var(--accent);
}

.bt-compare {
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: 10px;
  margin: 12px 0 18px;
  overflow: hidden;
  box-shadow: 0 4px 14px rgba(0,0,0,0.30);
}
.bt-compare-head {
  background: rgba(59,130,246,0.10);
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
}
.bt-compare-close {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 14px;
  padding: 0 6px;
}
.bt-compare-close:hover { color: var(--accent); }

.bt-compare-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
}
.bt-compare-col {
  padding: 14px 18px;
}
.bt-compare-col-base { border-right: 1px solid var(--border); }
.bt-compare-col-alt  { background: rgba(59,130,246,0.04); }
.bt-compare-col-head {
  font-size: 10.5px;
  font-weight: 800;
  color: var(--muted);
  letter-spacing: 0.7px;
  text-transform: uppercase;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.bt-compare-cell {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px dashed var(--border);
  font-size: 12.5px;
}
.bt-compare-cell:last-child { border-bottom: none; }
.bt-compare-lbl {
  color: var(--muted);
  font-weight: 600;
}
.bt-compare-val {
  color: var(--text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.bt-compare-diff {
  font-weight: 600;
  font-size: 11px;
  margin-left: 4px;
}
.bt-compare-foot {
  background: var(--surface2);
  border-top: 1px solid var(--border);
  padding: 10px 16px;
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.5;
}
.bt-compare-foot strong { color: var(--accent); font-weight: 700; }

@media (max-width: 760px) {
  .bt-compare-grid { grid-template-columns: 1fr; }
  .bt-compare-col-base { border-right: none; border-bottom: 1px solid var(--border); }
}

/* ── Recent-runs history panel ───────────────────────────────────
   Premium row-card design. Each row gets a colored left stripe
   (green/red) for instant outcome signal, a subtle full-row tint
   matching the outcome, and an oversized hero return number on
   the right. Generous spacing, monospace numeric typography,
   smooth hover transitions. */

/* Local CSS variables - kept here so the panel survives even if
   --green / --red aren't defined upstream. */
.bt-hist {
  --hist-green:     #4ade80;
  --hist-green-bg:  rgba(74, 222, 128, 0.06);
  --hist-green-bg2: rgba(74, 222, 128, 0.12);
  --hist-red:       #ef4444;
  --hist-red-bg:    rgba(239, 68, 68, 0.06);
  --hist-red-bg2:   rgba(239, 68, 68, 0.12);

  margin: 20px 0;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  overflow: hidden;
  box-shadow: 0 1px 0 rgba(0,0,0,0.04), 0 6px 18px -10px rgba(0,0,0,0.3);
}

/* ── Header bar (clickable to toggle) ────────────────────────── */
.bt-hist-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 14px 18px;
  background: linear-gradient(180deg, var(--surface2) 0%, var(--surface) 100%);
  border: none;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background 120ms ease;
}
.bt-hist-head:hover { background: var(--surface3); }
.bt-hist-head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.bt-hist-head-left {
  display: flex;
  align-items: center;
  gap: 10px;
}
.bt-hist-head-icon {
  color: var(--muted);
  font-size: 10px;
  width: 10px;
  text-align: center;
}
.bt-hist-head-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.bt-hist-head-count {
  background: var(--accent);
  color: #fff;
  font-size: 10.5px;
  font-weight: 800;
  padding: 2px 8px;
  border-radius: 999px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0;
}
.bt-hist-head-preview {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.bt-hist-head-preview-l {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--muted);
  font-weight: 600;
}
.bt-hist-head-preview-v {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.2px;
}
.bt-hist-head-preview-v.pos { color: var(--hist-green); }
.bt-hist-head-preview-v.neg { color: var(--hist-red);   }

/* ── Body: stacked rows separated by hairline borders ───────── */
.bt-hist-body {
  display: flex;
  flex-direction: column;
}

/* ── Each row ──────────────────────────────────────────────── */
.bt-hist-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 20px;
  padding: 18px 22px 18px 26px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  transition: background 140ms ease, transform 140ms ease;
}
.bt-hist-row:last-of-type { border-bottom: none; }
.bt-hist-row-pos { background: linear-gradient(90deg, var(--hist-green-bg) 0%, transparent 60%); }
.bt-hist-row-neg { background: linear-gradient(90deg, var(--hist-red-bg)   0%, transparent 60%); }
.bt-hist-row:hover {
  background: var(--surface2);
}
.bt-hist-row-pos:hover { background: linear-gradient(90deg, var(--hist-green-bg2) 0%, var(--surface2) 60%); }
.bt-hist-row-neg:hover { background: linear-gradient(90deg, var(--hist-red-bg2)   0%, var(--surface2) 60%); }

/* Colored left stripe - the instant win/loss signal */
.bt-hist-row-stripe {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
}
.bt-hist-row-pos .bt-hist-row-stripe { background: var(--hist-green); }
.bt-hist-row-neg .bt-hist-row-stripe { background: var(--hist-red);   }

/* Newest row gets a subtle accent on the stripe + tag */
.bt-hist-row-newest .bt-hist-row-stripe {
  box-shadow: 0 0 12px 0 currentColor;
}
.bt-hist-row-newest.bt-hist-row-pos .bt-hist-row-stripe { color: var(--hist-green); }
.bt-hist-row-newest.bt-hist-row-neg .bt-hist-row-stripe { color: var(--hist-red); }

/* ── Left column: timestamp, chips, mini stats ─────────────── */
.bt-hist-row-info {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 0;
}
.bt-hist-row-toprow {
  display: flex;
  align-items: center;
  gap: 8px;
}
.bt-hist-row-time {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  color: var(--muted);
  font-size: 11.5px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  font-weight: 600;
}
.bt-hist-row-newest-tag {
  background: var(--accent);
  color: #fff;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1px;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

.bt-hist-row-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.bt-hist-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--surface3);
  color: var(--text);
  font-size: 11.5px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 5px;
  white-space: nowrap;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  border: 1px solid var(--border);
}
.bt-hist-chip-arrow {
  color: var(--muted);
  font-weight: 400;
  margin: 0 1px;
}

.bt-hist-row-mini {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
}
.bt-hist-mini {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
}
.bt-hist-mini-v {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 13px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -0.1px;
}
.bt-hist-mini-v-neg { color: var(--hist-red); }
.bt-hist-mini-v-pos { color: var(--hist-green, #38c880); }
.bt-hist-chip-formula {
  background: rgba(99, 102, 241, 0.12) !important;
  border-color: rgba(99, 102, 241, 0.35) !important;
  color: var(--accent, #6366f1);
}
.bt-hist-mini-l {
  font-size: 10.5px;
  color: var(--muted);
  letter-spacing: 0.3px;
}
.bt-hist-mini-sep {
  width: 1px;
  height: 14px;
  background: var(--border);
}

/* ── Hero column: oversized return number ─────────────────── */
.bt-hist-row-hero {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  line-height: 1;
  min-width: 110px;
  padding-right: 4px;
}
.bt-hist-row-hero-trend {
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 2px;
  letter-spacing: -0.5px;
}
.bt-hist-row-pos .bt-hist-row-hero-trend { color: var(--hist-green); }
.bt-hist-row-neg .bt-hist-row-hero-trend { color: var(--hist-red);   }
.bt-hist-row-hero-val {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -1px;
  line-height: 1.05;
}
.bt-hist-row-pos .bt-hist-row-hero-val { color: var(--hist-green); }
.bt-hist-row-neg .bt-hist-row-hero-val { color: var(--hist-red);   }
.bt-hist-row-hero-lbl {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--muted);
  margin-top: 6px;
  font-weight: 700;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

/* ── Actions column ────────────────────────────────────────── */
.bt-hist-row-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}
.bt-hist-row-load {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface3);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 8px 14px;
  border-radius: 7px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition: all 140ms ease;
  white-space: nowrap;
}
.bt-hist-row-load:hover {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px -4px var(--accent);
}
.bt-hist-row-load:active { transform: translateY(0); box-shadow: none; }
.bt-hist-row-load:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}
.bt-hist-row-load-icon {
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}
.bt-hist-row-del {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 6px 11px;
  border-radius: 7px;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: all 140ms ease;
}
.bt-hist-row-del:hover {
  background: var(--hist-red);
  border-color: var(--hist-red);
  color: #fff;
  transform: translateY(-1px);
}

/* ── Footer ───────────────────────────────────────────────── */
.bt-hist-foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 18px;
  font-size: 11px;
  color: var(--muted);
  background: var(--surface2);
  border-top: 1px solid var(--border);
  letter-spacing: 0.3px;
  font-weight: 500;
}
.bt-hist-foot-dot {
  display: inline-block;
  width: 5px;
  height: 5px;
  background: var(--hist-green);
  border-radius: 50%;
  box-shadow: 0 0 6px 0 var(--hist-green);
}

/* ── Mobile / narrow: stack the row vertically ────────────── */
@media (max-width: 760px) {
  .bt-hist-row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "info  hero"
      "actions actions";
    gap: 14px;
    padding: 16px 18px 16px 22px;
  }
  .bt-hist-row-info    { grid-area: info; }
  .bt-hist-row-hero    { grid-area: hero; min-width: 100px; }
  .bt-hist-row-hero-val { font-size: 24px; }
  .bt-hist-row-actions { grid-area: actions; justify-content: flex-end; }
  .bt-hist-row-mini    { flex-wrap: wrap; }
  .bt-hist-head-preview { display: none; }
}

.bt-not-ready {
  padding: 60px 20px;
  text-align: center;
}
.bt-not-ready .welcome-p { max-width: 600px; margin: 0 auto; line-height: 1.5; }
.bt-cmd {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 12px 14px;
  margin: 14px 0;
  text-align: left;
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 12px;
  color: var(--accent);
  white-space: pre-wrap;
}

/* ── Earnings badges + banners + Calendar view ─────────────────────────── */

/* Inline badge - drop next to a symbol anywhere */
.earn-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 10px;
  border: 1px solid;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  cursor: help;
  white-space: nowrap;
}
.earn-badge .earn-icon { font-size: 11px; }
.earn-badge-compact { font-size: 10px; padding: 1px 6px; }

.earn-critical {
  background: var(--red-bg);
  color: var(--red);
  border-color: rgba(239,68,68,0.45);
}
.earn-warning {
  background: rgba(234,179,8,0.14);
  color: #eab308;
  border-color: rgba(234,179,8,0.45);
}
.earn-watch {
  background: rgba(59,130,246,0.12);
  color: var(--accent);
  border-color: rgba(59,130,246,0.40);
}
.earn-ok      { background: var(--green-bg); color: var(--green); border-color: rgba(34,197,94,0.35); }
.earn-past    { background: var(--surface2); color: var(--muted); border-color: var(--border); }
.earn-unknown { background: var(--surface2); color: var(--muted); border-color: var(--border); }

/* Full-width banner */
.earn-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  margin: 0 0 12px;
  border-radius: 8px;
  border: 1px solid;
  font-size: 13px;
  line-height: 1.4;
}
.earn-banner .earn-icon { font-size: 18px; line-height: 1; }
.earn-banner-body { flex: 1; }
.earn-banner-msg  { color: var(--muted); }
.earn-banner-date {
  color: var(--muted);
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 11.5px;
}
.earn-banner.earn-critical { background: var(--red-bg);                color: var(--red);    border-color: rgba(239,68,68,0.45); }
.earn-banner.earn-warning  { background: rgba(234,179,8,0.10);         color: #eab308;       border-color: rgba(234,179,8,0.40); }
.earn-banner.earn-watch    { background: rgba(59,130,246,0.08);        color: var(--accent); border-color: rgba(59,130,246,0.35); }

/* ── Calendar view ─────────────────────────── */
.cal-view { }
.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 14px;
}
.cal-title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  color: var(--text);
}
.cal-controls {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.cal-summary {
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 14px;
}
.cal-summary strong { color: var(--accent); }
.cal-summary-hint { color: var(--muted); font-style: italic; }

.cal-timeline {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cal-day-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.cal-row {
  display: grid;
  grid-template-columns: 110px 36px 1fr 90px;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  transition: background .12s;
  position: relative;
}
.cal-row::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--border);
  border-radius: 8px 0 0 8px;
}
.cal-row:hover { background: var(--surface2); }

.cal-date {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.cal-date-when {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
}
.cal-date-rel {
  font-size: 10.5px;
  color: var(--muted);
  letter-spacing: 0.3px;
  text-transform: uppercase;
  font-weight: 600;
}

.cal-icon {
  font-size: 22px;
  text-align: center;
  line-height: 1;
}

.cal-main {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  min-width: 0;
}
.cal-name {
  color: var(--text);
  font-size: 12.5px;
}
.cal-sym {
  background: var(--surface2);
  border: 1px solid var(--border);
  color: var(--accent);
  font-family: 'Cascadia Code', Consolas, monospace;
  font-weight: 700;
  font-size: 12px;
  padding: 2px 9px;
  border-radius: 5px;
  letter-spacing: 0.4px;
}
/* Clickable symbol pill - opens the chart modal */
.cal-sym-btn {
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s, transform .08s;
}
.cal-sym-btn:hover {
  background: rgba(59,130,246,0.18);
  border-color: var(--accent);
}
.cal-sym-btn:active { transform: translateY(1px); }

.cal-type-pill {
  display: inline-block;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.7px;
  padding: 2px 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  background: var(--surface2);
  color: var(--text);
  text-transform: uppercase;
  font-family: 'Cascadia Code', Consolas, monospace;
}
.cal-type-FOMC { color: #a78bfa; border-color: rgba(167,139,250,0.45); background: rgba(167,139,250,0.10); }
.cal-type-CPI  { color: #f97316; border-color: rgba(249,115,22,0.45);  background: rgba(249,115,22,0.10); }
.cal-type-NFP  { color: #22c55e; border-color: rgba(34,197,94,0.45);   background: var(--green-bg); }
.cal-type-PPI,
.cal-type-PCE  { color: #06b6d4; border-color: rgba(6,182,212,0.45);   background: rgba(6,182,212,0.10); }

.cal-time {
  font-size: 11.5px;
  color: var(--muted);
  font-family: 'Cascadia Code', Consolas, monospace;
  letter-spacing: 0.3px;
  text-align: right;
}

/* Importance-based left strips for macro events */
.cal-macro.macro-high   ::before { background: #ef4444; }
.cal-macro.macro-medium ::before { background: #eab308; }
.cal-macro.macro-low    ::before { background: var(--muted); }

/* Earnings rows: left strip by warning level */
.cal-earnings.earn-critical::before { background: var(--red); }
.cal-earnings.earn-warning ::before { background: #eab308; }
.cal-earnings.earn-watch   ::before { background: var(--accent); }
.cal-earnings.earn-ok      ::before { background: var(--green); }
.cal-earnings.earn-past    ::before { background: var(--muted); }

@media (max-width: 700px) {
  .cal-row { grid-template-columns: 90px 28px 1fr; }
  .cal-row .cal-time { display: none; }
}

/* ── Mobile push notifications card (Preferences tab) ────────────── */
.push-card {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
}
.push-card-unavailable {
  border-color: rgba(234,179,8,0.40);
  background: rgba(234,179,8,0.06);
}
.push-card code {
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 1px 5px;
  border-radius: 4px;
  font-family: 'Cascadia Code', Consolas, monospace;
  font-size: 11px;
  color: var(--accent);
}

.push-status-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.push-status-lbl {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 0.6px;
  text-transform: uppercase;
}
.push-status-pill {
  display: inline-flex;
  align-items: center;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.4px;
  padding: 3px 10px;
  border-radius: 12px;
  border: 1px solid;
}
.push-on {
  color: var(--green);
  background: var(--green-bg);
  border-color: rgba(34,197,94,0.45);
}
.push-off {
  color: var(--muted);
  background: var(--surface);
  border-color: var(--border);
}
.push-blocked {
  color: var(--red);
  background: var(--red-bg);
  border-color: rgba(239,68,68,0.40);
}

.push-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.push-btn-primary {
  max-width: 240px;
  flex: 1;
}
.push-msg {
  margin-top: 10px;
}

/* ── Mobile responsive: basics so the app at least USES on phone screens.
   Real responsive layout is a v2 - for now we shrink padding and stack the
   sidebar above the main area so users with a phone can navigate. */
@media (max-width: 900px) {
  body { font-size: 13.5px; }

  /* ── Layout: sidebar becomes a slide-up drawer ──────────
     On desktop the <aside> sits to the left of <main> permanently. On
     mobile it's hidden by default and slides up from the bottom as a
     full-height sheet when the user taps "🎛️ Filters" in the scanner
     toolbar. The main view area gets the entire viewport. */
  .layout { flex-direction: column; }
  aside {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    width: 100%;
    height: 90vh;
    max-height: 90vh;
    z-index: 300;                  /* above bottom nav (z 200) */
    border: none;
    border-top: 1px solid var(--border);
    border-radius: 16px 16px 0 0;
    background: var(--surface);
    overflow-y: auto;
    padding: 14px 14px calc(14px + env(safe-area-inset-bottom, 0));
    transform: translateY(100%);
    transition: transform .25s ease;
    box-shadow: 0 -8px 28px rgba(0,0,0,0.4);
  }
  aside.aside-open { transform: translateY(0); }

  /* ── Header: single-row mobile bar with hamburger menu ──
     Desktop has many actions visible inline. On mobile we condense to
     three things: logo on the left, clock + hamburger on the right.
     Theme toggle / scoring guide / settings / sign out live inside the
     hamburger dropdown. Single 52px row, symmetrically balanced. */
  header {
    /* Keep the status-bar inset on top (0 without a notch) — this mobile
       override previously reset padding to `0 12px`, which wiped the inset
       and let the logo/clock clip under the iPhone status bar. */
    padding: env(safe-area-inset-top, 0) 12px 0;
    flex-wrap: nowrap;
    gap: 8px;
    height: 52px;
    min-height: 52px;
    align-items: center;
    position: relative;        /* anchor for the absolute dropdown menu */
  }

  /* Logo - at desktop "SwingMentalist" comfortably fits, but with the
     Pro badge now sitting after the wordmark the header bar overflows
     on narrow phones. Shrink the wordmark + tighten gaps so the badge
     has room without pushing the right cluster off-screen. */
  .logo { font-size: 12px; gap: 6px; flex-shrink: 0; letter-spacing: 0.2px; min-width: 0; }
  .logo-mark { width: 28px; height: 28px; flex-shrink: 0; }
  .logo-text { white-space: nowrap; }
  /* Pro badge: much smaller pill on mobile so it doesn't compete with
     the wordmark for header space. The trial users keep the blue color
     (active = gold) - so the "· Trial" suffix is redundant and we hide
     it on mobile; the color difference still signals the state.
     The trial variant is a <button>, so it gets caught by the global
     `min-height: 44px` tap-target rule above. Override that here so
     the badge stays a compact pill in the header instead of inflating
     to 44px tall. */
  .pro-badge {
    font-size: 8px;
    padding: 1px 5px;
    margin-left: 3px;
    letter-spacing: 0.3px;
    border-radius: 8px;
    min-height: 0 !important;
    line-height: 1.2;
  }
  .pro-badge-suffix { display: none; }

  /* Drop the universe pill (info lives in the Filters drawer instead) */
  .header-tag { display: none; }

  /* Regime badge: icon + label only; drop the verbose "(SPY %)" suffix */
  .regime-badge { font-size: 10px; padding: 2px 6px; flex-shrink: 0; }
  .regime-sub   { display: none; }

  /* Hide the desktop right cluster entirely on mobile */
  .header-right-desktop { display: none; }

  /* Show the compact mobile right cluster */
  .header-right-mobile {
    display: flex;
    margin-left: auto;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
  }
  .market-clock {
    font-size: 10px;
    padding: 4px 8px;
    gap: 5px;
  }
  .market-clock .clock-time   { font-size: 11px; }
  .market-clock .clock-tz     { display: none; }
  .market-clock .clock-status { display: none; }

  /* ── Hamburger button ─────────────────────────────────
     Three horizontal bars + a tiny status-dot overlay in the top-right
     corner so the user still sees scan state at a glance without opening
     the menu. */
  .header-hamburger {
    display: block;            /* override the desktop `display: none` */
    position: relative;
    width:  32px;
    height: 32px;
    min-height: 32px;
    padding: 0;
    box-sizing: border-box;
    border-radius: 7px;
    border: 1px solid var(--border);
    background: var(--bg);
    cursor: pointer;
  }
  .header-hamburger:active { background: rgba(255,255,255,0.06); }
  .header-hamburger.is-open {
    background: var(--surface3, rgba(255,255,255,0.08));
    border-color: var(--accent);
  }
  /* Bars are absolutely positioned so the open/close states can use
     the SAME top coordinate (15px = button center minus half bar
     height: (32-2)/2 = 15) and only differ in rotation. Guarantees
     a perfectly symmetric X - no flex math, no padding fudge. */
  .hamburger-bar {
    position: absolute;
    left:  8px;     /* 8 + 16 (bar) + 8 = 32 */
    right: 8px;
    height: 2px;
    background: var(--text);
    border-radius: 1px;
    transform-origin: 50% 50%;
    transition: top .22s ease, opacity .15s ease, transform .22s ease;
  }
  .hamburger-bar:nth-child(1) { top: 9px;  }
  .hamburger-bar:nth-child(2) { top: 15px; }   /* button vertical center: (32-2)/2 = 15 */
  .hamburger-bar:nth-child(3) { top: 21px; }
  /* Open state: top + bottom bars converge at exactly the same `top`
     and rotate ±45° - symmetric by construction. */
  .header-hamburger.is-open .hamburger-bar:nth-child(1) {
    top: 15px;
    transform: rotate(45deg);
  }
  .header-hamburger.is-open .hamburger-bar:nth-child(2) {
    opacity: 0;
    transform: scaleX(0);
  }
  .header-hamburger.is-open .hamburger-bar:nth-child(3) {
    top: 15px;
    transform: rotate(-45deg);
  }
  .hamburger-status {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    box-shadow: 0 0 0 2px var(--bg);  /* halo to separate from button bg */
  }

  /* ── Hamburger dropdown menu ──────────────────────────
     Anchored to the header, slides down below it. Backdrop catches taps
     outside to close. */
  .header-menu-backdrop {
    /* Cover the whole viewport so a tap anywhere outside the menu
       closes it. Sits BELOW the header (z-index 100) so the hamburger
       button stays on top and can be tapped again to close the menu -
       previously this used `inset: 52px 0 0 0` + z-index 95, which
       broke when a trial banner pushed the header down (the backdrop
       would then cover part of the header, hiding the hamburger). */
    position: fixed;
    inset: 0;
    z-index: 90;
    background: rgba(0,0,0,0.35);
    animation: backdropFade .15s ease;
  }
  .header-menu {
    /* Anchored to the bottom of the <header> element via top: 100%,
       so the dropdown always opens directly below the header bar
       regardless of trial banners or anything else above it. */
    position: absolute;
    top: calc(100% + 4px);
    right: 8px;
    left: 8px;
    z-index: 110;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.45);
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    animation: menuSlide .18s ease;
  }
  @keyframes menuSlide {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  .header-menu-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    min-height: 48px;
    background: transparent;
    border: none;
    border-radius: 8px;
    color: var(--text);
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    text-align: left;
  }
  .header-menu-item:active { background: rgba(255,255,255,0.05); }
  .header-menu-icon {
    font-size: 18px;
    width: 24px;
    text-align: center;
    flex-shrink: 0;
  }
  .header-menu-item-danger { color: var(--red); }
  .header-menu-status {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    margin-top: 4px;
    border-top: 1px solid var(--border);
    color: var(--muted);
    font-size: 12px;
  }
  .header-menu-email {
    padding: 4px 14px 8px;
    color: var(--muted);
    font-size: 12px;
    word-break: break-all;
  }
  .header-menu-name {
    color: var(--text);
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 2px;
  }
  .header-menu-sub {
    color: var(--muted);
    font-size: 11.5px;
  }

  /* ── View tabs: horizontally scrollable with momentum ── */
  .view-tabs {
    padding: 6px 12px;
    gap: 4px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none; /* Firefox */
  }
  .view-tabs::-webkit-scrollbar { display: none; }
  .view-tab {
    padding: 7px 11px;
    font-size: 12px;
    gap: 6px;
    white-space: nowrap;
    flex-shrink: 0;
  }
  .view-tab-icon  { font-size: 13px; }
  .view-tab-badge {
    font-size: 10px;
    padding: 1px 6px;
    min-width: 18px;
  }

  /* ── View content padding ───────────────────────────── */
  .trades-view, .bt-view, .cal-view { padding: 12px; }
}

/* ── Phone-only: respect the OS notch / status bar / nav bar.
   Capacitor / iOS Safari expose safe-area insets via env(). We pad the
   body so content never slides under the status bar at top or the gesture
   bar at bottom. Costs nothing on devices without notches. ───────────── */
@supports (padding: env(safe-area-inset-top)) {
  body {
    /* Left/right insets for landscape notches. The TOP inset is NOT applied
       here: with viewport-fit=cover + `#root { height: 100vh }` + body
       `overflow: hidden`, padding on the body doesn't reliably push the
       fixed-height #root content below the status bar on iOS — the header
       ended up clipped under the notch. Instead each top bar (app header,
       landing header, auth gate) reserves its own env(safe-area-inset-top)
       so the inset is applied exactly once, at the element that sits at the
       very top. padding-bottom is handled by the bottom-nav rules below. */
    padding-left:   env(safe-area-inset-left);
    padding-right:  env(safe-area-inset-right);
    box-sizing: border-box;
  }
}


/* ──────────────────────────────────────────────────────────────────────
   MOBILE BOTTOM NAVIGATION
   Fixed bar at the bottom of the viewport with the primary view
   switcher. Hidden on desktop (>720px) - the old `.view-tabs` strip
   serves that role there. On mobile, `.view-tabs` is hidden and this
   becomes the only top-level nav.

   Layout note: the bottom nav is `position: fixed`, so we add
   bottom padding to `.main` and `aside` at mobile widths so their
   content isn't trapped under the bar.
   ─────────────────────────────────────────────────────────────────── */
.mobile-bottom-nav {
  display: none;          /* desktop default - only flex'd in at mobile @media */
}
@media (max-width: 900px) {
  .mobile-bottom-nav {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 200;
    background: var(--surface);
    border-top: 1px solid var(--border);
    /* Pad bottom for OS gesture bar / home indicator on iOS + modern Android */
    padding-bottom: env(safe-area-inset-bottom, 0);
    box-shadow: 0 -2px 12px rgba(0,0,0,0.18);
  }
  .mobile-bottom-nav-item {
    flex: 1 1 0;
    min-width: 0;
    background: transparent;
    border: none;
    color: var(--muted);
    padding: 6px 2px 8px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    cursor: pointer;
    position: relative;
    transition: color .15s;
    min-height: 56px;     /* Material-style hit target */
  }
  .mobile-bottom-nav-item:active { background: rgba(255,255,255,0.04); }
  .mobile-bottom-nav-item-active { color: var(--accent); }
  .mobile-bottom-nav-item-active::before {
    content: "";
    position: absolute;
    top: 0; left: 20%; right: 20%;
    height: 2px;
    background: var(--accent);
    border-radius: 0 0 2px 2px;
  }
  .mobile-bottom-nav-icon {
    font-size: 18px;
    line-height: 1;
  }
  .mobile-bottom-nav-label {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
  }
  .mobile-bottom-nav-badge {
    position: absolute;
    top: 4px;
    right: 50%;
    transform: translateX(14px);
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--accent);
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
  }

  /* Hide the desktop horizontal tab strip at mobile - bottom nav replaces it. */
  .view-tabs { display: none; }

  /* Make room for the fixed bottom nav so content isn't trapped under it.
     The nav is min-height 56px PLUS env(safe-area-inset-bottom) (the iOS
     home-indicator gap, ~34px on notched iPhones). A flat 64px was shorter
     than the real nav on iOS, so the last ~26px of scrollable content (the
     trades table, watchlist, etc.) hid under the bar. Reserve the nav
     height + safe area + a small buffer. 0 on devices without an inset
     (Android browser, desktop), so nothing changes there. */
  .layout      { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0)); }
}


/* ──────────────────────────────────────────────────────────────────────
   MOBILE SCANNER TOOLBAR + FILTER DRAWER HEADER + BACKDROP
   Sticky top bar inside the Scanner view giving one-tap access to the
   filters drawer and Run Scan, plus the drawer's own close-button row
   and the dim backdrop behind it.
   ─────────────────────────────────────────────────────────────────── */
.mobile-scanner-toolbar  { display: none; }
.aside-drawer-header     { display: none; }
.aside-drawer-backdrop   { display: none; }

@media (max-width: 900px) {
  .mobile-scanner-toolbar {
    display: flex;
    gap: 8px;
    padding: 10px 12px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 50;
  }
  .mobile-toolbar-btn {
    flex: 1 1 0;
    min-height: 44px;
    padding: 10px 12px;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
  }
  .mobile-toolbar-btn:active { background: rgba(255,255,255,0.06); }
  .mobile-toolbar-btn:disabled { opacity: 0.5; cursor: not-allowed; }
  .mobile-toolbar-btn-run {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
  }

  .aside-drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 4px 12px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    background: var(--surface);
    z-index: 1;
  }
  .aside-drawer-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
  }
  .aside-drawer-close {
    background: transparent;
    border: none;
    color: var(--muted);
    font-size: 28px;
    line-height: 1;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    cursor: pointer;
  }
  .aside-drawer-close:active { background: rgba(255,255,255,0.08); color: var(--text); }

  .aside-drawer-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.55);
    z-index: 250;                 /* below aside (300), above content */
    animation: backdropFade .18s ease;
  }
  @keyframes backdropFade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* ── Full-screen modals on mobile ──────────────────────
     Desktop modals are centered overlays (380px wide). On a phone
     a 380px card surrounded by dim space wastes screen and makes
     content cramped. Convert to edge-to-edge full screen with a
     prominent close-X at top right. */
  .modal-backdrop {
    align-items: stretch;        /* let the card fill, not center */
    justify-content: stretch;
    backdrop-filter: none;       /* no blur - saves GPU on phones */
    background: var(--bg);       /* solid bg since card covers it anyway */
  }
  .modal-card,
  .modal-wide,
  .modal-chart-card,
  .modal-compare-card,
  .modal-help-card,
  .modal-trade-card {
    width: 100vw !important;
    max-width: 100vw !important;
    height: 100dvh;              /* dynamic viewport accounts for URL bar */
    max-height: 100dvh !important;
    border-radius: 0;
    border: none;
    padding: 56px 16px calc(16px + env(safe-area-inset-bottom, 0));
    box-shadow: none;
    overflow-y: auto;
  }
  .modal-close-x {
    /* Bigger tap target on mobile */
    width: 44px;
    height: 44px;
    font-size: 30px;
    top: max(10px, env(safe-area-inset-top, 0));
  }
  .modal-title {
    font-size: 17px;
    /* Leave room on the right so the title doesn't sit under the × */
    padding-right: 48px;
  }

  /* ── Tables on mobile: scroll horizontally, pin first column ──
     Tables like scan results / dashboard / journal / backtest have many
     columns. Squishing them at phone width makes everything unreadable.
     Instead, let the table keep its natural column widths and scroll
     horizontally. Pin the first column (Symbol) so the user always knows
     which row they're reading. */
  .table-area,
  .trades-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .table-area table,
  .trades-table-wrap table {
    /* Don't shrink columns - let natural widths dictate. */
    min-width: max-content;
    width: max-content;
    font-size: 12px;
  }
  /* Pin first column (Symbol). The 4px shadow on the right edge gives
     a subtle visual hint that there's more content to scroll to. */
  .table-area thead th:first-child,
  .table-area tbody td:first-child,
  .trades-table-wrap thead th:first-child,
  .trades-table-wrap tbody td:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--bg);
    box-shadow: 4px 0 6px -3px rgba(0, 0, 0, 0.35);
  }
  .table-area thead th:first-child {
    z-index: 11;            /* must beat sticky thead (z-index 10) */
    background: var(--bg);
  }
  /* Tighten cell padding so more fits per scroll. */
  .table-area tbody td,
  .table-area thead th {
    padding: 8px 10px;
    white-space: nowrap;
  }

  /* ── Universal touch-target sizing ───────────────────────
     Apple HIG: 44pt minimum, Material: 48dp. We use 44px as the
     lower bound for any interactive element on mobile.
     Exceptions: small circular swatches / dots that are visually round
     and rely on their natural width=height for shape. The min-height
     rule was stretching .color-swatch from 18×18 into 18×44 ovals. */
  button:not(.color-swatch):not(.mobile-bottom-nav-item):not(.modal-close-x):not(.aside-drawer-close):not(.th-info):not(.header-hamburger):not(.btn-theme):not(.btn-help),
  .btn-preset,
  .btn-export,
  .btn-login,
  .btn-logout,
  .btn-danger,
  .btn-help,
  .btn-theme,
  .btn-stats-open,
  .btn-active,
  .view-tab,
  select {
    min-height: 44px;
  }

  /* ── Chart modal on mobile ───────────────────────────────
     The desktop layout (arrows in side gutters, header inset to align
     with chart) doesn't translate to a phone. Two specific failures:
       • Overlay arrows hide the chart's Y-axis price labels (pad.left
         is 56px - the arrow at left:4px sits right on top of them).
       • The header's flex-wrap put items in awkward asymmetric rows.
     Mobile redesign:
       • Header: flex-wrap centered, no inset, no `flex:1` on the symbol
         block so wrapped rows look balanced.
       • Chart stage: CSS grid with the chart on its own row and the
         arrows in a dedicated row below - never overlap the chart or
         its axis labels.
  */
  .modal-chart-card .chart-modal-title {
    flex-wrap: wrap;
    justify-content: center;       /* centre items in each wrapped row */
    /* Equal padding on both sides so the centered title + toggles sit
       visually in the middle of the modal. Higher-specificity selector
       (`.modal-chart-card .chart-modal-title`) + !important wins over
       the generic `.modal-title { padding-right: 48px }` rule above
       that was leaving padding-left at 0 — that's what was visually
       shifting the row left of center. */
    padding-left:  48px !important;
    padding-right: 48px !important;
    row-gap: 10px;
    column-gap: 10px;
    width: 100%;
    text-align: center;
  }
  .chart-modal-sym {
    flex: initial;                 /* don't stretch - let it shrink/wrap */
    flex-wrap: wrap;
    justify-content: center;
  }

  /* Chart + arrows as a 2-row grid:
       row 1: full-width chart column
       row 2: [prev arrow]  [next arrow]   (centred via justify-self) */
  .chart-stage {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "chart  chart"
      "prev   next";
    row-gap: 10px;
    column-gap: 8px;
    /* Breathing room between the prev/next arrow row and the next
       sibling (alerts bar / news bar / notes bar). Without this the
       arrows sit flush against the alerts bar header — looks crowded. */
    margin-bottom: 16px;
  }
  .chart-stage-inner {
    grid-area: chart;
    width: 100%;
    min-width: 0;
  }
  .chart-nav-arrow {
    /* Cancel desktop's absolute positioning + transforms - these are
       in-flow grid items now. */
    position: static;
    transform: none;
    width: 44px;
    height: 44px;
    background: var(--surface2);
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .chart-nav-arrow-prev { grid-area: prev; justify-self: end;   }
  .chart-nav-arrow-next { grid-area: next; justify-self: start; }
  .chart-nav-arrow:active:not(:disabled) { transform: scale(0.92); }
  .chart-nav-arrow:hover:not(:disabled)  { transform: none; }

  /* ── Upgrade + Welcome-Pro modals on mobile ───────────────
     The two side-by-side cards (prices, feature tiles) don't fit
     comfortably on a phone - stack them vertically and tighten padding. */
  .upgrade-modal-card {
    padding: 56px 18px calc(20px + env(safe-area-inset-bottom, 0)) !important;
  }
  .upgrade-head        { margin-bottom: 22px; }
  .upgrade-prices {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .upgrade-price-card  { padding: 18px 16px; }
  .upgrade-price       { font-size: 28px; }
  .upgrade-features-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .upgrade-feat        { padding: 12px 14px; }
  .upgrade-feat-icon   { font-size: 20px; }
  .upgrade-section-head { font-size: 11px; margin-bottom: 16px; }

  .welcome-pro-card {
    padding: 56px 18px calc(20px + env(safe-area-inset-bottom, 0));
  }
  .welcome-pro-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .welcome-pro-burst { font-size: 48px; }
  .welcome-pro-title { font-size: 20px; }

  .welcome-trial-card {
    padding: 56px 18px calc(20px + env(safe-area-inset-bottom, 0)) !important;
  }
  .welcome-trial-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .welcome-trial-burst { font-size: 44px; }
  .welcome-trial-title { font-size: 20px; }
  .welcome-trial-callout {
    grid-template-columns: 44px 1fr;
    gap: 12px;
    padding: 14px;
  }
  .welcome-trial-callout-icon { font-size: 26px; }

  /* Color swatches: still round, but a bit bigger for fingers. */
  .color-swatch {
    width:  32px !important;
    height: 32px !important;
    min-height: 32px !important;
    border-radius: 50% !important;
    flex: 0 0 auto;
  }

  /* ── Inputs: prevent iOS auto-zoom on focus ────────────
     Safari + WebView zoom in on any <input> with font-size < 16px
     when the user taps it. Setting 16px keeps the layout stable. */
  input,
  textarea,
  select {
    font-size: 16px !important;
  }
  .field input,
  .field select,
  .field textarea {
    min-height: 44px;
    padding: 10px 12px;
  }
  .field textarea { min-height: 88px; }

  /* ── Suppress the default WebView grey flash on tap.
        Visual feedback comes from each component's :active style. */
  * {
    -webkit-tap-highlight-color: transparent;
  }

  /* ── Kill the 300ms double-tap-to-zoom delay on buttons.
        Modern browsers infer this from viewport meta, but explicit is
        safer in a WebView. */
  button,
  a,
  .view-tab,
  .mobile-bottom-nav-item,
  .mobile-toolbar-btn {
    touch-action: manipulation;
  }

  /* ── Disable text selection on chrome (nav, badges, buttons).
        Long-press still works for actual content (table cells, modal
        body, etc.) since we only target chrome classes. */
  .mobile-bottom-nav,
  .mobile-bottom-nav *,
  .view-tabs,
  .view-tabs *,
  header,
  header *,
  .aside-drawer-header,
  .aside-drawer-header * {
    -webkit-user-select: none;
    user-select: none;
  }

  /* ── Stats bar (scanner results + backtest results) ────
     Multiple stat blocks with 28px padding each easily exceed phone
     width. Let the row scroll horizontally with momentum instead of
     pushing the whole page wide. */
  /* Grid (see the ≤720px rule above) — show every KPI instead of a
     horizontal scroll that slices the last one. */
  .stats-bar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
    gap: 12px 10px;
    overflow: visible;
    padding: 10px 12px;
  }
  .stat {
    flex-shrink: 1;
    min-width: 0;
    padding-right: 0;
  }
  .stat + .stat { padding-left: 0; border-left: none; }   /* grid gap handles spacing now */
  .stat-val { font-size: 18px; }

  /* ── View root containers: prevent horizontal page-level overflow.
        Any internal wide element (table, chart, stats row) must scroll
        itself, not push the body sideways. */
  .bt-view,
  .trades-view,
  .cal-view,
  .main {
    overflow-x: hidden;
    max-width: 100vw;
    box-sizing: border-box;
  }

  /* On desktop .main is `overflow: hidden` and only inner scrollers (e.g.
     .table-area) scroll. On mobile the Welcome panel + other tall content
     gets clipped instead - let .main itself scroll vertically so users
     can reach everything down to the bottom-nav line. */
  .main {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Critical: a flex item's default min-height is `auto`, so without this
       `.main` refuses to shrink below its content height, `overflow-y: auto`
       never engages, and tall pages (e.g. the dashboard) are clipped and
       unscrollable on iOS Safari. */
    min-height: 0;
  }
  /* Don't let the welcome panel center-vertically (that combined with
     .main's auto-overflow caused the top of the content to crowd the
     toolbar). Anchor to the top of its scroll area. */
  .welcome {
    justify-content: flex-start;
    padding-top: 28px;
    padding-bottom: 28px;
  }
  /* Stack the rule cards 1-up on mobile so each one is a full-width band
     instead of two cramped columns. */
  .rules-grid {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .rules-grid .rule-card { grid-column: auto !important; }
}

/* ──────────────────────────────────────────────────────────────────────
   LOGIN / FORGOT PASSWORD / RESET PASSWORD - auth gate brand
   The logo above the "SwingMentalist" title in the auth-gate replaces
   the old 📈 emoji placeholder.
   ─────────────────────────────────────────────────────────────────── */
.auth-gate-logo {
  display: block;
  margin: 0 auto 8px;
  width:  120px;
  height: 120px;
  object-fit: contain;
  filter: drop-shadow(0 2px 12px rgba(59, 130, 246, 0.25));
}

/* Google Sign-In button + "or" divider above the email/password form. */
.google-signin-row {
  margin: 14px 0 16px;
}
.google-signin-wrap-note {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--muted);
  margin-bottom: 10px;
  text-align: center;
}
.google-signin-wrap-note a {
  color: var(--accent, #3b82f6);
  text-decoration: none;
}
.google-signin-wrap-note a:hover { text-decoration: underline; }
.google-signin-button {
  display: flex;
  justify-content: center;
  min-height: 44px;       /* matches Google's branded button height */
}
/* Native (Capacitor) variant - Google's HTML branded button is GIS-only,
   so on native we render our own matching the brand guidelines: white
   bg, dark text, multi-color G logo at 18×18, "Continue with Google". */
.google-signin-native-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 10px 16px;
  border-radius: 8px;
  border: 1px solid #dadce0;
  background: #ffffff;
  color: #1f1f1f;
  font-size: 14px;
  font-weight: 600;
  font-family: 'Roboto', 'Segoe UI', system-ui, sans-serif;
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: background .12s, box-shadow .12s, border-color .12s;
}
.google-signin-native-btn:hover  { background: #f8fafc; box-shadow: 0 1px 3px rgba(0,0,0,0.12); }
.google-signin-native-btn:active { background: #eef0f3; }
.google-signin-native-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.google-g-icon { width: 18px; height: 18px; flex-shrink: 0; }
.google-signin-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 0;
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}
.google-signin-divider::before,
.google-signin-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}
@media (max-width: 900px) {
  .auth-gate-logo { width: 96px; height: 96px; }
}
/* Center the form heading ("Sign in", "Create account", etc.) so it
   aligns under the centered logo + wordmark above. The padding-right
   override defeats the mobile rule that reserves 48px for a close-X
   that doesn't exist on the auth-gate (it's a full-screen view, not
   a modal). */
.auth-gate .modal-title {
  text-align: center;
  padding-right: 0;
}


/* ──────────────────────────────────────────────────────────────────────
   ALERTS TAB (Settings → 🔔 Alerts)
   Device list + per-feature preference controls + master switch.
   Single column at any width; the form controls are all simple HTML
   inputs that get the universal field styling above.
   ─────────────────────────────────────────────────────────────────── */

.alerts-tab {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding-top: 6px;
}

.alerts-master {
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.alerts-section {
  border-top: 1px solid var(--border);
  padding-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.alerts-h {
  margin: 0 0 4px 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
}

.alerts-switch {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
  color: var(--muted);
  cursor: pointer;
}
.alerts-switch input { transform: scale(1.1); flex-shrink: 0; }
.alerts-switch strong { color: var(--text); }

.alerts-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12.5px;
  color: var(--muted);
}
.alerts-row label { color: var(--text); font-weight: 600; min-width: 96px; }
.alerts-row input[type="time"],
.alerts-row input[type="number"],
.alerts-row select {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 13px;
}
.alerts-row input[type="range"] { flex: 1; min-width: 140px; }
.alerts-val { font-weight: 700; color: var(--accent); min-width: 60px; }
.alerts-hint { font-size: 11px; color: var(--muted); }

.alerts-checkrow {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-left: 0;
  font-size: 13px;
}
.alerts-checkrow label {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  color: var(--text);
}
.alerts-checkrow input[type="checkbox"] { transform: scale(1.05); }

/* Device list rows */
.alerts-device {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.alerts-device-main { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.alerts-device-kind { font-size: 22px; }
.alerts-device-meta { min-width: 0; }
.alerts-device-label {
  font-size: 13.5px; font-weight: 700; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.alerts-device-sub { font-size: 11px; color: var(--muted); }
.alerts-device-toggle {
  display: flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--muted); cursor: pointer;
  flex-shrink: 0;
}
.alerts-device-remove { font-size: 11.5px; padding: 4px 10px; flex-shrink: 0; }

.alerts-device-actions {
  display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px;
}
.alerts-empty {
  font-size: 12px; color: var(--muted); font-style: italic;
  padding: 8px 0; margin: 0;
}

/* Mobile: stack the device row instead of crowding controls right */
@media (max-width: 900px) {
  .alerts-device { flex-wrap: wrap; }
  .alerts-device-main { flex: 1 1 100%; }
  .alerts-device-toggle { flex: 1; }
  .alerts-row label { min-width: 0; flex: 1 1 100%; }
}


/* ── Scrollbars ─────────────────────────────── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

/* ── Custom Formula Panel ──────────────────────────────────────────
 * Shared between scanner sidebar + backtest form. Looks at home in both.
 * ─────────────────────────────────────────────────────────────── */
.custom-formula-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  margin: 12px 0;
  overflow: hidden;
  /* Container query context - lets the inner layout adapt to the
   * panel's OWN width, not the viewport's. Critical because the panel
   * lives in both the backtest form (wide) and the scanner sidebar
   * (narrow ~280px) and needs to render usable controls in both. */
  container-type: inline-size;
}
.custom-formula-panel.cf-on { border-color: var(--accent); }

/* Narrow container (scanner sidebar): use named grid areas so the label
 * and value badges sit on the top row and the slider gets a clean
 * full-width row below. Replaces an earlier negative-margin hack that
 * looked broken when the row collapsed. */
@container (max-width: 360px) {
  .cf-row {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "lbl    val"
      "slider slider";
    align-items: center;
    column-gap: 8px;
    row-gap: 4px;
    padding: 8px 0;
    border-bottom: 1px dashed var(--border);
  }
  .cf-row:last-of-type { border-bottom: none; }
  .cf-row-lbl {
    grid-area: lbl;
    justify-content: flex-start;
    font-size: 12px;
    min-width: 0;
  }
  .cf-row-val {
    grid-area: val;
    justify-content: flex-end;
  }
  .cf-row input[type="range"] {
    grid-area: slider;
    width: 100%;
    margin: 0;
  }

  .cf-agg {
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
  }
  .cf-agg-lbl { margin-bottom: 2px; }
  .cf-agg-btn { width: 100%; }

  .cf-actions {
    flex-direction: column;
  }
  .cf-actions .cf-btn { width: 100%; }
}

.cf-header {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  cursor: pointer;
  user-select: none;
}
.cf-header:hover { background: var(--surface-2, rgba(255,255,255,0.03)); }
.cf-toggle {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 600; color: var(--text);
  cursor: pointer;
}
.cf-toggle input[type="checkbox"] { transform: scale(1.1); cursor: pointer; }
.cf-status {
  flex: 1;
  font-size: 11.5px; color: var(--muted);
  font-style: italic;
}
.cf-chevron { color: var(--muted); font-size: 12px; }

.cf-body {
  padding: 4px 12px 12px;
  border-top: 1px solid var(--border);
}
.cf-blurb {
  font-size: 11.5px; color: var(--muted);
  line-height: 1.45;
  padding: 8px 0 10px;
}

.cf-row {
  display: grid;
  grid-template-columns: 140px 1fr 70px;
  align-items: center;
  gap: 10px;
  padding: 4px 0;
}
.cf-row.cf-row-disabled { opacity: 0.45; }
.cf-row-lbl {
  display: flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--text);
}
.cf-icon { font-size: 14px; }
.cf-help { color: var(--muted); cursor: help; font-size: 11px; }
.cf-row input[type="range"] { width: 100%; cursor: pointer; }
.cf-row input[type="range"]:disabled { cursor: not-allowed; }
.cf-row-val {
  display: flex; align-items: baseline; justify-content: flex-end; gap: 6px;
  font-size: 11.5px; color: var(--muted);
}
.cf-raw { font-variant-numeric: tabular-nums; color: var(--text); font-weight: 600; }
.cf-pct {
  font-variant-numeric: tabular-nums;
  background: var(--surface-2, rgba(255,255,255,0.04));
  padding: 1px 6px;
  border-radius: 4px;
  min-width: 36px; text-align: center;
}

.cf-agg {
  display: flex; align-items: center; gap: 8px;
  margin-top: 14px; padding-top: 10px;
  border-top: 1px dashed var(--border);
}
.cf-agg-lbl {
  font-size: 12px; color: var(--muted); margin-right: 4px;
  white-space: nowrap;
}
.cf-agg-btn {
  flex: 1;
  display: flex; flex-direction: column; align-items: flex-start;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  color: var(--text);
  font-size: 12px; font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.cf-agg-btn:hover:not(:disabled) { border-color: var(--accent); }
.cf-agg-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.cf-agg-btn.cf-agg-on { border-color: var(--accent); background: rgba(56,160,255,0.08); }
.cf-agg-sub { font-size: 10px; color: var(--muted); font-weight: 400; margin-top: 2px; }

.cf-actions {
  display: flex; gap: 8px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.cf-btn {
  flex: 1;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 12px; font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.cf-btn:hover:not(:disabled) { border-color: var(--accent); }
.cf-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.cf-btn-primary {
  background: var(--accent); color: #fff; border-color: var(--accent);
}
.cf-btn-primary:hover:not(:disabled) { filter: brightness(1.05); }
.cf-btn-ghost { background: transparent; }

.cf-load-list {
  margin-top: 10px;
  background: var(--surface-2, rgba(255,255,255,0.03));
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
}
.cf-load-empty {
  font-size: 12px; color: var(--muted); font-style: italic;
  padding: 8px 4px;
}
.cf-load-item {
  display: flex; align-items: stretch; gap: 4px;
  margin-bottom: 4px;
}
.cf-load-item:last-of-type { margin-bottom: 0; }
.cf-load-apply {
  flex: 1;
  display: flex; align-items: center; justify-content: space-between;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 4px;
  padding: 6px 10px;
  font-size: 12px;
  cursor: pointer;
  text-align: left;
}
.cf-load-apply:hover { border-color: var(--accent); background: rgba(56,160,255,0.06); }
.cf-load-name { font-weight: 600; }
.cf-load-meta { font-size: 10.5px; color: var(--muted); font-style: italic; }
.cf-load-del {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 4px;
  padding: 0 10px;
  font-size: 14px; font-weight: 700;
  cursor: pointer;
}
.cf-load-del:hover { color: var(--neg, #ff5b6e); border-color: var(--neg, #ff5b6e); }
.cf-load-cap {
  font-size: 10.5px; color: var(--muted);
  text-align: right;
  padding-top: 4px;
}

/* Save dialog overlay */
.cf-save-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.5);
  z-index: 9000;
  display: flex; align-items: center; justify-content: center;
}
.cf-save-dialog {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 18px;
  width: min(360px, 90vw);
  box-shadow: 0 12px 32px rgba(0,0,0,0.4);
}
.cf-save-title {
  font-size: 14px; font-weight: 700; color: var(--text);
  margin-bottom: 12px;
}
.cf-save-input {
  width: 100%;
  background: var(--surface-2, rgba(255,255,255,0.03));
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 13px;
  margin-bottom: 8px;
  box-sizing: border-box;
}
.cf-save-input:focus { outline: none; border-color: var(--accent); }
.cf-save-err {
  font-size: 11.5px; color: var(--neg, #ff5b6e);
  margin-bottom: 8px;
}
.cf-save-actions {
  display: flex; gap: 8px; justify-content: flex-end;
}
.cf-save-actions .cf-btn { flex: 0 0 auto; min-width: 80px; }

/* Mobile tweaks - keep sliders usable, condense labels */
@media (max-width: 540px) {
  .cf-row { grid-template-columns: 110px 1fr 62px; gap: 6px; }
  .cf-row-lbl { font-size: 11.5px; }
  .cf-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cf-agg { flex-direction: column; align-items: stretch; gap: 6px; }
  .cf-agg-lbl { margin-bottom: 2px; }
}

/* ── Backtest "vs V4 baseline" comparison stat-bar ────────────────── */
.bt-vs-baseline {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
  padding: 12px;
  margin: 12px 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.bt-vs-row {
  display: flex; flex-direction: column;
  padding: 8px 10px;
  background: var(--surface-2, rgba(255,255,255,0.03));
  border-radius: 6px;
}
.bt-vs-lbl { font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.bt-vs-vals { display: flex; align-items: baseline; gap: 8px; margin-top: 4px; flex-wrap: wrap; }
.bt-vs-yours { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.bt-vs-base { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.bt-vs-delta { font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 1px 6px; border-radius: 4px; }
.bt-vs-delta.pos { background: rgba(56,200,128,0.15); color: var(--pos, #38c880); }
.bt-vs-delta.neg { background: rgba(255,91,110,0.15); color: var(--neg, #ff5b6e); }
.bt-vs-delta.zero { background: var(--surface-3, rgba(255,255,255,0.04)); color: var(--muted); }
.bt-vs-header {
  grid-column: 1 / -1;
  font-size: 12px; font-weight: 700;
  color: var(--text);
  display: flex; align-items: center; justify-content: space-between;
}
.bt-vs-baseline-loading {
  font-size: 11.5px; color: var(--muted); font-style: italic;
}

/* ── Backtest universe chip selector ─────────────────────────────── */
.bt-section-count {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
  font-weight: 400;
  letter-spacing: 0.2px;
}

.bt-uni-grid {
  display: grid;
  /* Auto-fit so the column count tracks what actually fits — 4 wide on
     a desktop, 2 wide on a mid-narrow window, 1 wide on a phone — instead
     of forcing 4 equal columns and silently ellipsising "Russell 2000"
     into "Russell…". Each chip needs ~145 px to show its full label +
     size badge without truncation; below that the next chip wraps. */
  grid-template-columns: repeat(auto-fit, minmax(145px, 1fr));
  gap: 6px;
}

.bt-uni-chip {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 9px;
  padding: 10px 11px;
  cursor: pointer;
  color: var(--text);
  font-family: inherit;
  transition: background .15s ease, border-color .15s ease, transform .08s ease;
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 42px;
  white-space: nowrap;
}
.bt-uni-chip:hover {
  border-color: var(--accent);
  background: rgba(99, 102, 241, 0.04);
}
.bt-uni-chip:active { transform: scale(0.985); }

.bt-uni-chip.bt-uni-on {
  border-color: var(--accent);
  background: rgba(99, 102, 241, 0.12);
  box-shadow: 0 0 0 1px var(--accent) inset;
}

.bt-uni-check {
  width: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 800;
  color: var(--accent, #6366f1);
  flex-shrink: 0;
}
.bt-uni-chip-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1px;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bt-uni-chip-size {
  font-size: 10px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  background: var(--surface-2, rgba(255,255,255,0.04));
  padding: 0 5px;
  border-radius: 3px;
  flex-shrink: 0;
}
.bt-uni-on .bt-uni-chip-size {
  color: var(--accent);
  background: rgba(99, 102, 241, 0.15);
}

@media (max-width: 640px) {
  .bt-uni-grid { grid-template-columns: 1fr 1fr; }
  .bt-uni-chip-label { font-size: 11.5px; }
}
/* At phone widths (~400 px viewport) the 2-column universe grid gives
   each chip ~170 px, which crowds "Russell 2000" + its size badge.
   Stack 1-per-row to match the single-column date / signal fields
   below — keeps the form consistent and chip labels comfortably
   readable. */
@media (max-width: 420px) {
  .bt-uni-grid { grid-template-columns: 1fr; }
}

/* ── Settings modal helpers (used by Trading-tab subsections) ──────── */
.settings-section-divider {
  margin: 22px 0 16px;
  border-top: 1px dashed var(--border);
}
.settings-subhead {
  margin: 0 0 4px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0.1px;
}

.cf-load-active {
  display: inline-block;
  margin-left: 6px;
  font-size: 9.5px;
  font-weight: 700;
  color: var(--accent, #6366f1);
  background: rgba(99, 102, 241, 0.15);
  padding: 1px 6px;
  border-radius: 3px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  vertical-align: middle;
}

/* ── Toast notifications (singleton, top-right) ────────────────────── */
.toast-host {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 100050;       /* above tooltip portal, above modals' backdrop */
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;  /* clicks pass through gaps */
  max-width: min(380px, calc(100vw - 32px));
}

.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  line-height: 1.4;
  font-weight: 500;
  pointer-events: auto;
  cursor: pointer;
  box-shadow:
    0 10px 24px -6px rgba(0,0,0,0.45),
    0 0 0 1px rgba(255,255,255,0.04) inset;
  animation: toast-in .22s ease-out;
}
.toast:hover { filter: brightness(1.05); }

.toast-icon {
  flex-shrink: 0;
  font-size: 14px;
  width: 18px;
  text-align: center;
}
.toast-text {
  flex: 1;
  min-width: 0;
  word-wrap: break-word;
}
.toast-close {
  flex-shrink: 0;
  color: var(--muted);
  font-size: 16px;
  font-weight: 700;
  margin-left: 2px;
}

.toast-info {
  border-color: rgba(99, 102, 241, 0.45);
  background: linear-gradient(180deg, rgba(60, 80, 130, 0.96), rgba(40, 55, 95, 0.96));
}
.toast-info .toast-icon { color: var(--accent, #6366f1); }

.toast-warn {
  border-color: rgba(255, 180, 60, 0.6);
  background: linear-gradient(180deg, rgba(110, 80, 30, 0.96), rgba(90, 65, 25, 0.96));
}
.toast-warn .toast-icon { color: #ffba3c; }

.toast-error {
  border-color: rgba(255, 91, 110, 0.7);
  background: linear-gradient(180deg, rgba(110, 35, 50, 0.96), rgba(90, 30, 45, 0.96));
}
.toast-error .toast-icon { color: #ff8092; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0);    }
}

/* Mobile: full-width chips at top, slight inset */
@media (max-width: 540px) {
  .toast-host {
    top: 12px;
    right: 12px;
    left: 12px;
    max-width: none;
  }
  .toast { font-size: 12.5px; padding: 9px 11px; }
}
