<script>
  import { screenTickers, fetchCatalysts, analyzeTickers } from '$lib/api.js';
  import SignalBadge from '$lib/SignalBadge.svelte';
  import Spinner from '$lib/Spinner.svelte';

  let input        = $state('');
  let searchOpen   = $state(false);   // collapsed by default
  let loading      = $state(false);
  let loadingCats  = $state(false);
  let error        = $state(null);
  let results      = $state(null);
  let activeTab    = $state({});
  let screenedAt   = $state(null);

  // Auto-load catalysts once on mount
  let _booted = false;
  $effect(() => {
    if (!_booted) { _booted = true; loadCatalysts(); }
  });

  // ── Per-tab LLM Analysis sidebar ────────────────────────────────────────────
  let sidebar = $state({ open: false, loading: false, analysis: null, type: null, error: null });

  async function runTabAnalysis(type) {
    const tickers = (results?.[type] ?? []).map(r => r.asset.ticker);
    if (!tickers.length) return;
    sidebar = { open: true, loading: true, analysis: null, type, error: null };
    try {
      const res = await analyzeTickers(tickers);
      const reason = res.reason === 'no_stories' ? 'No recent news found for these tickers.' : null;
      sidebar = { open: true, loading: false, analysis: res.analysis, type, error: res.analysis ? null : (reason ?? 'Analysis failed — check server logs for details.') };
    } catch (e) {
      sidebar = { open: true, loading: false, analysis: null, type, error: e.message };
    }
  }

  function closeSidebar() {
    sidebar = { ...sidebar, open: false };
  }

  async function screen() {
    error = null;
    loading = true;
    try {
      const tickers = input.split(/[\s,]+/).map(t => t.trim().toUpperCase()).filter(Boolean);
      results = await screenTickers(tickers);
      screenedAt = new Date().toLocaleTimeString();
    } catch (e) {
      error = e.message;
    } finally {
      loading = false;
    }
  }

  // Load catalysts then immediately screen — no extra click needed.
  // LLM analysis (if available) is shown alongside the results.
  async function loadCatalysts() {
    loadingCats = true;
    error = null;
    try {
      const cat = await fetchCatalysts();
      const catInput = cat.tickers.join(', ');
      loading = true;
      results = await screenTickers(cat.tickers);
      screenedAt = new Date().toLocaleTimeString();
      if (!input) input = catInput;
    } catch (e) {
      error = e.message;
    } finally {
      loading = false;
      loadingCats = false;
    }
  }

  const sigOrd = s => ({'✅ Strong Buy':0,'⚡ Momentum':1,'🔄 Neutral':2,'⚠️  Speculation':3,'❌ Avoid':4})[s] ?? 5;
  const sorted = arr => [...(arr ?? [])].sort((a, b) => sigOrd(a.signal) - sigOrd(b.signal));

  const verdictShort = label => {
    if (!label) return '—';
    if (label.includes('High Conviction')) return 'Strong';
    if (label.includes('Speculative'))     return 'Speculative';
    if (label.includes('BUY'))             return 'Buy';
    if (label.includes('Efficient'))       return 'Efficient';
    if (label.includes('Attractive'))      return 'Attractive';
    if (label.includes('Neutral'))         return 'Hold';
    if (label.includes('REJECT'))          return 'Reject';
    if (label.includes('Avoid'))           return 'Avoid';
    return label.replace(/[🟢🟡🔴]/u, '').trim();
  };

  const vClass = label =>
    label?.startsWith('🟢') ? 'green' : label?.startsWith('🟡') ? 'yellow' : 'red';

  const getTab = type => activeTab[type] ?? 'inflated';
  const setTab = (type, tab) => activeTab = { ...activeTab, [type]: tab };

  const ctx = $derived(results?.marketContext ?? null);
  const allAssets = $derived(results
    ? sorted([...results.STOCK, ...results.ETF, ...results.BOND])
    : []);

  const fmtPE = v => v != null ? v + 'x' : '—';
</script>

<div class="page">

  <!-- ── Toolbar ──────────────────────────────────────────────────── -->
  <div class="toolbar">
    <div class="toolbar-top">
      <button onclick={loadCatalysts} disabled={loading || loadingCats} class="btn-catalyst">
        {#if loadingCats}<Spinner size="sm" />{:else}📰 Today Market{/if}
      </button>
      <button
        onclick={() => searchOpen = !searchOpen}
        class="btn-search-toggle"
        title="Screen custom tickers"
      >
        🔍 {searchOpen ? 'Hide search' : 'Search tickers'}
      </button>
      {#if screenedAt}
        <span class="screened-at">Last screened {screenedAt}</span>
      {/if}
    </div>

    {#if searchOpen}
      <div class="search-row">
        <input
          bind:value={input}
          placeholder="AAPL, MSFT, VOO …"
          onkeydown={e => e.key === 'Enter' && screen()}
        />
        <button onclick={screen} disabled={loading || loadingCats} class="btn-screen">
          {#if loading}<Spinner size="sm" />{:else}Screen{/if}
        </button>
      </div>
    {/if}
  </div>

  {#if error}
    <div class="error-banner">⚠ {error}</div>
  {/if}

  {#if loading || loadingCats}
    <div class="loading-area">
      <Spinner size="lg" label={loadingCats ? 'Fetching news catalysts…' : loading ? `Screening tickers…` : ''} />
    </div>
  {/if}

  {#if ctx}
    <!-- ── Market Context Strip ────────────────────────────────────── -->
    <div class="ctx-strip">
      <div class="ctx-chip">
        <span class="ctx-label">10Y</span>
        <span class="ctx-val">{ctx.riskFreeRate?.toFixed(2)}%</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">VIX</span>
        <span class="ctx-val">{ctx.vixLevel?.toFixed(1)}</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">S&P</span>
        <span class="ctx-val">{ctx.sp500Price?.toLocaleString()}</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">S&P P/E</span>
        <span class="ctx-val">{fmtPE(ctx.benchmarks?.marketPE?.toFixed(1))}</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">Tech P/E</span>
        <span class="ctx-val">{fmtPE(ctx.benchmarks?.techPE?.toFixed(1))}</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">REIT Yld</span>
        <span class="ctx-val">{ctx.benchmarks?.reitYield?.toFixed(2)}%</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">IG Sprd</span>
        <span class="ctx-val">{ctx.benchmarks?.igSpread?.toFixed(2)}%</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">Rates</span>
        <span class="ctx-val ctx-regime" data-regime={ctx.rateRegime}>{ctx.rateRegime}</span>
      </div>
      <div class="ctx-chip">
        <span class="ctx-label">Vol</span>
        <span class="ctx-val ctx-regime" data-regime={ctx.volatilityRegime}>{ctx.volatilityRegime}</span>
      </div>
    </div>

    <!-- ── Signal Summary ─────────────────────────────────────────── -->
    <section class="section">
      <div class="section-header">
        <h2>Signal Summary</h2>
        <span class="count">{allAssets.length} assets</span>
      </div>
      <div class="table-wrap">
        <table>
          <thead>
            <tr>
              <th class="col-ticker">Ticker</th>
              <th>Type</th>
              <th>Signal</th>
              <th>Mkt-Adjusted</th>
              <th>Fundamental</th>
            </tr>
          </thead>
          <tbody>
            {#each allAssets as r}
              <tr>
                <td class="ticker">{r.asset.ticker}</td>
                <td><span class="tag">{r.asset.type}</span></td>
                <td><SignalBadge signal={r.signal} /></td>
                <td>
                  <span class="verdict-pill {vClass(r.inflated.label)}">
                    {verdictShort(r.inflated.label)}
                  </span>
                </td>
                <td>
                  <span class="verdict-pill {vClass(r.fundamental.label)}">
                    {verdictShort(r.fundamental.label)}
                  </span>
                </td>
              </tr>
            {/each}
          </tbody>
        </table>
      </div>
    </section>

    <!-- ── Detail Sections ────────────────────────────────────────── -->
    {#each ['STOCK', 'ETF', 'BOND'] as type}
      {#if results[type]?.length}
        {@const count = results[type].length}
        <section class="section">
          <div class="section-header">
            <h2>{type}S</h2>
            <span class="count">{count}</span>
            <div class="mode-tabs">
              <button
                class:active={getTab(type) === 'inflated'}
                onclick={() => setTab(type, 'inflated')}
              >Mkt-Adjusted</button>
              <button
                class:active={getTab(type) === 'fundamental'}
                onclick={() => setTab(type, 'fundamental')}
              >Graham</button>
            </div>
            <button
              class="btn-analyze"
              onclick={() => runTabAnalysis(type)}
              disabled={sidebar.loading && sidebar.type === type}
              title="AI analysis of news for these tickers"
            >
              {#if sidebar.loading && sidebar.type === type}
                <Spinner size="sm" />
              {:else}
                ✦ Analyze
              {/if}
            </button>
          </div>

          <div class="table-wrap">
            <table>
              <thead>
                <tr>
                  <th class="col-ticker">Ticker</th>
                  <th>Price</th>
                  <th>Verdict</th>
                  <th>Score</th>
                  {#if type === 'STOCK'}
                    <th>Sector</th>
                    <th>P/E</th><th>PEG</th><th>ROE%</th>
                    <th>OpMgn%</th><th>FCF%</th><th>D/E</th>
                    <th>Flags</th>
                  {:else if type === 'ETF'}
                    <th>Expense</th><th>Yield</th><th>AUM</th><th>5Y Ret</th>
                  {:else}
                    <th>YTM</th><th>Duration</th><th>Rating</th>
                  {/if}
                </tr>
              </thead>
              <tbody>
                {#each sorted(results[type]) as r}
                  {@const mode = getTab(type)}
                  {@const m = r.asset.displayMetrics ?? {}}
                  {@const v = r[mode]}
                  <tr class="data-row" data-signal={sigOrd(r.signal)}>
                    <td class="ticker">{r.asset.ticker}</td>
                    <td class="num">{m.Price ?? '—'}</td>
                    <td>
                      <span class="verdict-pill {vClass(v.label)}">
                        {verdictShort(v.label)}
                      </span>
                    </td>
                    <td class="score-cell" title={v.scoreSummary}>{v.scoreSummary}</td>
                    {#if type === 'STOCK'}
                      <td><span class="tag sm">{m.Sector ?? '—'}</span></td>
                      <td class="num">{m['P/E'] ?? '—'}</td>
                      <td class="num">{m['PEG'] ?? '—'}</td>
                      <td class="num">{m['ROE%'] ?? '—'}</td>
                      <td class="num">{m['OpMgn%'] ?? '—'}</td>
                      <td class="num">{m['FCF Yld%'] ?? '—'}</td>
                      <td class="num">{m['D/E'] ?? '—'}</td>
                      <td class="flags">
                        {#each v.audit?.riskFlags ?? [] as flag}
                          <span class="flag">⚠ {flag}</span>
                        {/each}
                      </td>
                    {:else if type === 'ETF'}
                      <td class="num">{m['Exp Ratio%'] ?? '—'}</td>
                      <td class="num">{m['Yield%'] ?? '—'}</td>
                      <td class="num">{m['AUM'] ?? '—'}</td>
                      <td class="num">{m['5Y Return%'] ?? '—'}</td>
                    {:else}
                      <td class="num">{m['YTM%'] ?? '—'}</td>
                      <td class="num">{m['Duration'] ?? '—'}</td>
                      <td class="num">{m['Rating'] ?? '—'}</td>
                    {/if}
                  </tr>
                {/each}
              </tbody>
            </table>
          </div>
        </section>
      {/if}
    {/each}

    {#if results.ERROR?.length}
      <section class="section">
        <h2>Failed <span class="count">{results.ERROR.length}</span></h2>
        <div class="error-list">
          {#each results.ERROR as e}
            <div class="error-item"><span class="ticker">{e.ticker}</span> {e.message}</div>
          {/each}
        </div>
      </section>
    {/if}
  {/if}
</div>

<!-- ── LLM Analysis Sidebar ─────────────────────────────────────────────── -->
{#if sidebar.open}
  <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
  <div class="sidebar-backdrop" onclick={closeSidebar}></div>
  <aside class="sidebar">
    <div class="sidebar-header">
      <div class="sidebar-title">
        <span>🤖 LLM Analysis</span>
        {#if sidebar.type}<span class="sidebar-type">{sidebar.type}S</span>{/if}
      </div>
      <button class="sidebar-close" onclick={closeSidebar}>✕</button>
    </div>

    <div class="sidebar-body">
      {#if sidebar.loading}
        <div class="sidebar-loading">
          <Spinner size="lg" label="Analyzing tickers…" />
        </div>
      {:else if sidebar.error}
        <div class="sidebar-error">{sidebar.error}</div>
      {:else if sidebar.analysis}
        {@const a = sidebar.analysis}
        <div class="sb-sentiment-row">
          <span class="sentiment-pill" data-sentiment={a.sentiment}>{a.sentiment}</span>
        </div>
        <p class="sb-summary">{a.summary}</p>

        <h3 class="sb-sub">Affected Industries</h3>
        <div class="sb-list">
          {#each a.affectedIndustries ?? [] as ind}
            <div class="sb-item">
              <span class="sb-name">{ind.name}</span>
              <span class="sb-reason">{ind.reason}</span>
            </div>
          {/each}
        </div>

        <h3 class="sb-sub">Related Tickers to Watch</h3>
        <div class="sb-list">
          {#each a.relatedTickers ?? [] as rt}
            <div class="sb-item">
              <span class="sb-name ticker">{rt.ticker}</span>
              <span class="sb-reason">{rt.reason}</span>
            </div>
          {/each}
        </div>
      {/if}
    </div>
  </aside>
{/if}

<style>
  /* ── Page ──────────────────────────────────────────────────────── */
  .page { max-width: 1400px; padding-bottom: 60px; }

  /* ── Toolbar ────────────────────────────────────────────────────── */
  .toolbar { margin-bottom: 20px; display: flex; flex-direction: column; gap: 10px; }

  .toolbar-top {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .search-row {
    display: flex;
    gap: 8px;
    align-items: center;
  }

  input {
    flex: 1;
    min-width: 0;
    background: #1e293b;
    border: 1px solid #2d3f55;
    border-radius: 8px;
    color: #e2e8f0;
    padding: 10px 14px;
    font-size: 13px;
    font-family: 'SF Mono', 'Fira Code', monospace;
    letter-spacing: 0.02em;
    outline: none;
    transition: border-color 0.15s;
  }
  input:focus { border-color: #3b82f6; box-shadow: 0 0 0 2px #3b82f620; }

  button {
    padding: 10px 18px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    border: none;
    white-space: nowrap;
    transition: background 0.15s, opacity 0.15s;
  }
  button:disabled { opacity: 0.45; cursor: default; }

  /* Primary catalyst button */
  .btn-catalyst {
    background: #2563eb;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 10px 20px;
  }
  .btn-catalyst:hover:not(:disabled) { background: #1d4ed8; }

  /* Secondary search toggle */
  .btn-search-toggle {
    background: #1e293b;
    color: #64748b;
    border: 1px solid #2d3f55;
    font-size: 12px;
    padding: 8px 14px;
  }
  .btn-search-toggle:hover { background: #263347; color: #94a3b8; }

  /* Screen button inside the expanded search row */
  .btn-screen {
    background: #1e3a5f;
    color: #60a5fa;
    border: 1px solid #1e3a5f;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 80px;
  }
  .btn-screen:hover:not(:disabled) { background: #163356; }

  .screened-at {
    margin-left: auto;
    font-size: 11px;
    color: #475569;
  }

  .loading-area {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 80px 0;
  }

  .error-banner {
    background: #450a0a55;
    border: 1px solid #7f1d1d;
    border-radius: 8px;
    color: #f87171;
    padding: 10px 14px;
    margin-bottom: 16px;
    font-size: 13px;
  }

  /* ── Market Context Strip ───────────────────────────────────────── */
  .ctx-strip {
    display: flex;
    gap: 1px;
    background: #1e293b;
    border: 1px solid #1e293b;
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 20px;
  }

  .ctx-chip {
    flex: 1;
    min-width: 70px;
    background: #0f1117;
    padding: 10px 14px;
    display: flex;
    flex-direction: column;
    gap: 3px;
  }

  .ctx-label {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #475569;
  }

  .ctx-val {
    font-size: 15px;
    font-weight: 700;
    color: #f1f5f9;
    font-variant-numeric: tabular-nums;
  }

  .ctx-regime[data-regime="HIGH"]   { color: #f87171; }
  .ctx-regime[data-regime="NORMAL"] { color: #94a3b8; }
  .ctx-regime[data-regime="LOW"]    { color: #4ade80; }

  /* ── Section ────────────────────────────────────────────────────── */
  .section {
    background: #0d1117;
    border: 1px solid #1e293b;
    border-radius: 10px;
    margin-bottom: 16px;
    overflow: hidden;
  }

  .section-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 18px 12px;
    border-bottom: 1px solid #1e293b;
    background: #111827;
  }

  h2 {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #64748b;
    margin: 0;
  }

  .count {
    font-size: 10px;
    font-weight: 600;
    color: #334155;
    background: #1e293b;
    padding: 2px 7px;
    border-radius: 20px;
  }

  /* ── Mode Tabs ──────────────────────────────────────────────────── */
  .mode-tabs {
    display: flex;
    gap: 4px;
    margin-left: auto;
  }

  .mode-tabs button {
    background: transparent;
    color: #475569;
    border: 1px solid #1e293b;
    font-size: 11px;
    padding: 4px 12px;
    border-radius: 6px;
  }
  .mode-tabs button.active {
    background: #1e3a5f;
    color: #60a5fa;
    border-color: #1e3a5f;
  }

  /* ── Table ──────────────────────────────────────────────────────── */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  table { width: max-content; min-width: 100%; border-collapse: collapse; }

  thead th {
    text-align: left;
    padding: 8px 14px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: #334155;
    border-bottom: 1px solid #1e293b;
    white-space: nowrap;
    background: #111827;
  }

  tbody tr { border-bottom: 1px solid #161f2e; }
  tbody tr:hover { background: #131c2b; }

  tbody td {
    padding: 10px 14px;
    vertical-align: middle;
    white-space: nowrap;
    font-size: 13px;
  }

  /* Sticky ticker column */
  .col-ticker,
  tbody td:first-child {
    position: sticky;
    left: 0;
    background: inherit;
    z-index: 1;
  }
  thead .col-ticker { background: #111827; }
  tbody td:first-child { background: #0d1117; }
  tbody tr:hover td:first-child { background: #131c2b; }

  .ticker {
    font-weight: 700;
    font-size: 13px;
    color: #f1f5f9;
    letter-spacing: 0.02em;
  }

  .num {
    color: #64748b;
    font-variant-numeric: tabular-nums;
    font-size: 12px;
  }

  /* Score cell: truncates gate failure text, shown in full via title tooltip */
  .score-cell {
    color: #64748b;
    font-size: 11px;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* ── Verdict Pill ───────────────────────────────────────────────── */
  .verdict-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.02em;
  }
  .verdict-pill.green  { background: #14532d33; color: #4ade80; }
  .verdict-pill.yellow { background: #71350033; color: #facc15; }
  .verdict-pill.red    { background: #450a0a33; color: #f87171; }

  /* ── Tags ───────────────────────────────────────────────────────── */
  .tag {
    display: inline-block;
    background: #1e293b;
    color: #64748b;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .tag.sm { font-size: 10px; padding: 1px 6px; }

  /* ── Risk Flags ─────────────────────────────────────────────────── */
  .flags { display: flex; flex-direction: column; gap: 2px; }
  .flag  { color: #fb923c; font-size: 11px; }

  /* ── Errors ─────────────────────────────────────────────────────── */
  .error-list { padding: 12px 18px; display: flex; flex-direction: column; gap: 6px; }
  .error-item { color: #64748b; font-size: 12px; }
  .error-item .ticker { color: #f87171; font-weight: 700; margin-right: 8px; }

  /* ── Analyze button ─────────────────────────────────────────────── */
  .btn-analyze {
    background: transparent;
    color: #7c93b0;
    border: 1px solid #1e293b;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    padding: 4px 12px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-left: 8px;
    white-space: nowrap;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
  }
  .btn-analyze:hover:not(:disabled) {
    background: #0f2240;
    color: #93c5fd;
    border-color: #1e3a5f;
  }
  .btn-analyze:disabled { opacity: 0.4; cursor: default; }

  /* ── LLM Sidebar ────────────────────────────────────────────────── */
  .sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: #00000055;
    z-index: 100;
  }

  .sidebar {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 380px;
    background: #0d1117;
    border-left: 1px solid #1e3a5f;
    z-index: 101;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .sidebar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 18px;
    border-bottom: 1px solid #1e293b;
    background: #0d1e30;
    flex-shrink: 0;
  }

  .sidebar-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 700;
    color: #e2e8f0;
  }

  .sidebar-type {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    background: #1e3a5f;
    color: #60a5fa;
    padding: 2px 8px;
    border-radius: 20px;
  }

  .sidebar-close {
    background: none;
    border: none;
    color: #475569;
    font-size: 14px;
    padding: 4px 8px;
    cursor: pointer;
    border-radius: 4px;
  }
  .sidebar-close:hover { color: #94a3b8; background: #1e293b; }

  .sidebar-body {
    flex: 1;
    overflow-y: auto;
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

  .sidebar-loading {
    display: flex;
    justify-content: center;
    align-items: center;
    flex: 1;
    padding: 60px 0;
  }

  .sidebar-error {
    color: #f87171;
    background: #450a0a33;
    border-radius: 8px;
    padding: 12px 14px;
    font-size: 13px;
  }

  .sb-sentiment-row { display: flex; align-items: center; gap: 8px; }

  .sb-summary {
    font-size: 13px;
    color: #94a3b8;
    line-height: 1.6;
    border-left: 3px solid #1e3a5f;
    padding-left: 12px;
    margin: 0;
  }

  .sb-sub {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #475569;
    margin: 0;
  }

  .sb-list { display: flex; flex-direction: column; gap: 8px; }

  .sb-item {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px;
    background: #111827;
    border-radius: 6px;
    border: 1px solid #1e293b;
  }

  .sb-name {
    font-size: 12px;
    font-weight: 600;
    color: #e2e8f0;
  }

  .sb-reason {
    font-size: 11px;
    color: #64748b;
    line-height: 1.4;
  }


  /* ── Sidebar sentiment pill ─────────────────────────────────────── */
  .sentiment-pill {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    padding: 3px 10px;
    border-radius: 20px;
  }
  .sentiment-pill[data-sentiment="BULLISH"]  { background: #14532d33; color: #4ade80; }
  .sentiment-pill[data-sentiment="BEARISH"]  { background: #450a0a33; color: #f87171; }
  .sentiment-pill[data-sentiment="NEUTRAL"]  { background: #1e293b;   color: #94a3b8; }
</style>
