  /* Self-hosted variable fonts (CSP-compliant: no external font-src).
     Inter v4.1 + JetBrains Mono v2.304, both as variable woff2 — one
     file per family covers every weight we use. The legacy CSS @import
     from fonts.googleapis.com was blocked by the production
     Content-Security-Policy "font-src 'self'" header; this stays inside
     'self'. */
  @font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('/fonts/InterVariable.woff2') format('woff2-variations'),
         url('/fonts/InterVariable.woff2') format('woff2');
  }
  @font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 100 800;
    font-display: swap;
    src: url('/fonts/JetBrainsMono.woff2') format('woff2-variations'),
         url('/fonts/JetBrainsMono.woff2') format('woff2');
  }

  /* ── DARK THEME VARIABLES ── */
  body.dark-theme {
    --holo-cyan: #06b6d4; 
    --holo-cyan-bright: #22d3ee; 
    --holo-purple: #a855f7;
    --holo-purple-light: #c084fc;
    
    --accent-red: #ef4444;
    --accent-green: #10b981;
    --accent-amber: #f59e0b;
    
    --bg-color: #120a2b; 
    --bg-radial: radial-gradient(circle at 50% 50%, rgba(147, 51, 234, 0.4) 0%, transparent 70%);
    
    /* Central Environment */
    --glass-pane-bg: linear-gradient(135deg, rgba(30, 20, 60, 0.6) 0%, rgba(15, 10, 30, 0.8) 100%);
    --glass-edge-bg: rgba(34, 211, 238, 0.1); /* Used for internal dividing lines */

    /* Suspended Cards */
    --card-bg: rgba(60, 30, 100, 0.15); 
    --card-border-top: rgba(34, 211, 238, 0.6);
    --card-border-side: rgba(34, 211, 238, 0.2);
    --card-shadow: 0 20px 40px rgba(0, 0, 0, 0.5); 
    
    /* Directional 3D Card Glass Glow (50% Default via lower opacity) */
    --glow-cyan-def: inset 15px 15px 30px rgba(34, 211, 238, 0.15);
    --glow-purp-def: inset -15px -15px 30px rgba(147, 51, 234, 0.15);
    --glow-cyan-hov: inset 20px 20px 50px rgba(34, 211, 238, 0.35);
    --glow-purp-hov: inset -20px -20px 50px rgba(147, 51, 234, 0.35);

    --text-primary: #f8fafc;
    --text-secondary: #94a3b8;
    --text-muted: #64748b;
    --header-glass: rgba(20, 10, 40, 0.8);
    --nav-bg: rgba(15, 10, 30, 0.95);
    
    --chart-grid: rgba(34, 211, 238, 0.1);
    --chart-tooltip-bg: rgba(20, 10, 40, 0.95);
    --chart-tooltip-border: rgba(34, 211, 238, 0.5);
  }

  /* ── LIGHT THEME VARIABLES ── */
  body.light-theme {
    --holo-cyan: #0891b2; 
    --holo-cyan-bright: #06b6d4; 
    --holo-purple: #7e22ce;
    --holo-purple-light: #9333ea;

    --accent-red: #ea580c;
    --accent-green: #10b981;
    --accent-amber: #d97706;

    /* Light Grey Environment */
    --bg-color: #d1d5db; 
    --bg-radial: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.8) 0%, transparent 80%);

    --glass-pane-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.6) 0%, rgba(240, 245, 255, 0.3) 100%);
    --glass-edge-bg: rgba(255, 255, 255, 0.8);

    --card-bg: rgba(255, 255, 255, 0.2); 
    --card-border-top: rgba(255, 255, 255, 1);
    --card-border-side: rgba(255, 255, 255, 0.6);
    --card-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); 

    /* Maintaining the exact same Cyan/Purple Directional Glass Glow for Light Mode */
    --glow-cyan-def: inset 15px 15px 30px rgba(34, 211, 238, 0.15);
    --glow-purp-def: inset -15px -15px 30px rgba(147, 51, 234, 0.15);
    --glow-cyan-hov: inset 20px 20px 50px rgba(34, 211, 238, 0.35);
    --glow-purp-hov: inset -20px -20px 50px rgba(147, 51, 234, 0.35);

    --text-primary: #0f172a;
    --text-secondary: #475569;
    --text-muted: #94a3b8;
    --header-glass: rgba(255, 255, 255, 0.5);
    --nav-bg: rgba(240, 245, 255, 0.9);
    
    --chart-grid: rgba(147, 51, 234, 0.1);
    --chart-tooltip-bg: rgba(255, 255, 255, 0.95);
    --chart-tooltip-border: rgba(255, 255, 255, 0.8);
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }
  ::-webkit-scrollbar { width: 6px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb { background: rgba(147, 51, 234, 0.3); border-radius: 3px; }

  body {
    background-color: var(--bg-color);
    background-image: var(--bg-radial);
    color: var(--text-primary);
    font-family: 'JetBrains Mono', monospace;
    min-height: 100vh;
    overflow: hidden; 
    display: flex;
    transition: background-color 0.5s ease, background-image 0.5s ease;
  }

  /* ── 1. FRAMELESS BACKGROUND PANE ── */
  .global-glass-pane {
    position: absolute;
    top: 0px; left: 0px; right: 0px; bottom: 0px; 
    
    background: var(--glass-pane-bg);
      
    backdrop-filter: blur(40px);
    -webkit-backdrop-filter: blur(40px);
      
    display: flex;
    flex-direction: column;
    z-index: 10;
    overflow: hidden; 
  }

  /* ── FRAMEWORK TOPOLOGY: Matching production UI layout precisely ── */
  .pane-interior {
    display: flex; flex: 1; overflow: hidden; position: relative; z-index: 10;
  }
  
  /* ── 3. HARDWARE: SIDE NAVIGATION ── */
  .side-frame-nav {
    background: var(--nav-bg);
    border-right: 1px solid var(--glass-edge-bg);
    width: 64px;
    display: flex; flex-direction: column; align-items: center;
    padding: 16px 0; gap: 8px;
    position: relative;
    z-index: 100;
  }
  
  .side-nav-brand {
    width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
    margin-bottom: 12px; text-decoration: none;
  }
  .side-nav-brand img {
    width: 28px; height: 28px; border-radius: 6px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
    /* The v7 pages use /static/logo-144.png — a pre-LANCZOS-resampled
       144×144 derivative of the 381×395 source. At 28px display that's
       a clean 5.1× downscale instead of 14×. image-rendering:
       high-quality nudges Chromium 96+ toward a higher-quality bicubic
       than the default 'auto'. crisp-edges (which we tried before) is
       wrong for photo-style logos — it means nearest-neighbor and
       produces blocky edges on non-pixel-art images. */
    image-rendering: -webkit-optimize-contrast;
    image-rendering: high-quality;
  }
  /* The framed logo (static/logo-framed-144.png) ships with its own
     dark indigo gradient frame baked in, so no light-theme CSS backdrop
     hack is needed anymore — the same image works on both themes. */

  .right-column {
    display: flex; flex-direction: column; flex: 1; overflow: hidden;
  }

  /* ── 2. HARDWARE: TOP HEADER (Right aligned to Nav) ── */
  .top-frame-header {
    background: var(--header-glass);
    border-bottom: 1px solid var(--glass-edge-bg);
    padding: 14px 20px;
    display: flex; justify-content: space-between; align-items: center;
    position: relative;
    z-index: 100; 
  }

  /* ── 4. MAIN CONTENT ── */
  .main-content {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    position: relative;
    z-index: 10; 
  }

  /* Header Specifics */
  .header-left { display: flex; align-items: center; gap: 14px; }
  .logo {
    font-family: 'Poppins', sans-serif;
    font-size: 18px;
    font-weight: 800;
    letter-spacing: -0.5px;
    background: linear-gradient(135deg, var(--holo-cyan-bright), var(--holo-purple-light));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    text-shadow: 0 0 15px rgba(34, 211, 238, 0.2);
    text-decoration: none;
  }
  .version-tag { font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--text-muted); border: 1px solid var(--glass-edge-bg); padding: 4px 8px; border-radius: 6px; }

  /* Which page am I on. The side nav marks the active item with an icon
     tint alone, which is a small target to read and gives no name — on a
     narrow window the header was "cryptAI Oracle  v9.18.29" on every
     page. This chip names it, and is deliberately LOUDER than the
     version tag beside it (accent border and text against that one's
     muted grey) because the page identity is the thing being answered
     and the build number is reference. Sits first, so the header reads
     brand → where → build. */
  .page-tag {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.8px;
    color: var(--holo-cyan-bright);
    border: 1px solid var(--holo-cyan-bright);
    background: var(--glass-edge-bg);
    padding: 4px 10px; border-radius: 999px;
    white-space: nowrap;
    box-shadow: 0 0 10px var(--glass-edge-bg);
  }
  /* Below the header-metrics breakpoint the chip is the only thing
     naming the page, so it keeps its place while the build number —
     reference, not navigation — is what gives way. */
  @media (max-width: 560px) {
    .version-tag { display: none; }
  }

  .header-metrics { display: flex; gap: 20px; align-items: center; }
  .header-metric { display: flex; flex-direction: column; align-items: center; min-width: 80px;}
  .header-metric-label { font-size: 8px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
  .header-metric-value { font-size: 14px; font-weight: 700; line-height: 1.3; text-shadow: 0 0 8px var(--glass-edge-bg); }
  .header-metric-sub { font-size: 9px; line-height: 1.2; color: var(--text-secondary); }

  /* Interactive Buttons */
  .trade-toggle {
    display: flex; align-items: center; gap: 8px; padding: 6px 14px; border-radius: 6px; 
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; 
    background: rgba(239,68,68,0.1); color: var(--accent-red); border: 1px solid rgba(239,68,68,0.25);
    box-shadow: inset 0 0 10px rgba(239,68,68,0.1);
  }
  .trade-toggle .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent-red); box-shadow: 0 0 8px var(--accent-red); }

  .theme-toggle-btn {
    display: flex; align-items: center; gap: 8px; padding: 6px 14px;
    border-radius: 6px; font-size: 10px; font-weight: 700; text-transform: uppercase;
    border: 1px solid var(--holo-purple-light); background: rgba(147, 51, 234, 0.1);
    color: var(--holo-purple-light); cursor: pointer; transition: all 0.3s;
  }
  .theme-toggle-btn:hover { background: var(--holo-purple); color: #fff; }

  /* Icons */
  .side-nav-item {
    width: 44px; height: 44px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    color: var(--text-muted); cursor: pointer; transition: all 0.2s;
    /* Reset user-agent button defaults so the <button id="btnLogout">
       doesn't show as a white pill on macOS Brave/Chrome. */
    background: none; border: none; padding: 0;
    font: inherit;
  }
  .side-nav-item:hover { color: var(--text-primary); background: var(--card-bg); }
  
  /* Matches original active nav state */
  .side-nav-item.active {
    color: #3b82f6; 
    background: rgba(59,130,246,0.15);
    border: 1px solid #3b82f6; 
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1), inset 0 0 10px rgba(59,130,246,0.2);
  }
  .side-nav-item svg { width: 22px; height: 22px; }
  .side-nav-spacer { flex: 1; }

  /* Sign-out button: themed red accent + 3D depth on hover (works in
     both dark and light themes because --accent-red is themed and the
     rgba tints layer cleanly over either background). */
  #btnLogout {
    color: var(--text-muted);
    border: 1px solid transparent;
    transition: all 0.2s;
  }
  #btnLogout:hover {
    color: var(--accent-red);
    background: rgba(239, 68, 68, 0.10);
    border-color: rgba(239, 68, 68, 0.30);
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15), inset 0 0 10px rgba(239, 68, 68, 0.20);
    transform: translateY(-1px);
  }
  #btnLogout:active {
    transform: translateY(0);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.20), inset 0 0 12px rgba(239, 68, 68, 0.30);
  }

  /* Dashboard Core Area */
  .dashboard {
    max-width: 1800px; margin: 0 auto; padding: 18px 18px 80px 18px; width: 100%;
    display: flex; flex-direction: column; gap: 12px;
  }
  
  /* Restored Section Dividers */
  .section-label {
    font-family: 'Inter', sans-serif; font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 1.2px; color: var(--text-muted);
    padding: 14px 0 12px; 
    display: flex;
    align-items: center;
    gap: 16px;
  }
  .section-label::after {
    content: '';
    flex: 1;
    height: 2px;
    background: var(--glass-edge-bg);
    opacity: 0.6;
  }

  .grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 24px; }
  .grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

  /* ── 5. TRUE TRANSLUCENT FLOATING CARDS (Directional Lighting) ── */
  .card {
    background: var(--card-bg); 
    border: 1px solid;
    border-top-color: var(--card-border-top);
    border-left-color: var(--card-border-side);
    border-right-color: var(--card-border-side);
    border-bottom-color: transparent;
    border-radius: 10px;
    padding: 16px;
    
    /* 50% default base directional glow */
    box-shadow: 
      var(--card-shadow),         
      var(--glow-cyan-def), 
      var(--glow-purp-def);           
      
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
  }
  
  .card:hover {
    transform: translateY(-4px); 
    /* 100% intense hover directional glow */
    box-shadow: 
      0 30px 50px rgba(0, 0, 0, 0.6),
      var(--glow-cyan-hov),
      var(--glow-purp-hov);
  }

  .card-title {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px;
    color: var(--text-muted); margin-bottom: 12px;
  }
  
  /* Added specific action buttons from screenshot */
  .btn {
    font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 600; 
    padding: 8px 16px; border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; 
    cursor: pointer; text-transform: uppercase; letter-spacing: 0.5px; 
    background: var(--card-bg); color: var(--text-secondary);
    transition: all 0.2s;
  }
  .btn:hover { background: rgba(255,255,255,0.1); color: var(--text-primary); border: 1px solid rgba(255,255,255,0.3); }

  /* Exchange tab switcher (Portfolio / Kraken / Coinbase) ─────
     Visible only when ≥2 venues are configured. Sits above the
     trading-status grid; selecting a tab refilters the page.
     The bare <button> defaults were leaking through pre-v7.0.2 — this
     block matches the .btn glass aesthetic but adds a persistent
     "active" treatment so the operator can see which view is live. */
  .exchange-tabs {
    display: flex; align-items: center; gap: 8px;
    flex-wrap: wrap;
  }
  .exchange-tabs .tab {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px; font-weight: 600;
    padding: 7px 14px;
    border-radius: 8px;
    border: 1px solid var(--card-border-side);
    background: var(--card-bg);
    color: var(--text-secondary);
    cursor: pointer;
    text-transform: none;
    letter-spacing: 0.3px;
    display: inline-flex; align-items: center; gap: 6px;
    transition: background 0.18s, color 0.18s, border-color 0.18s,
                box-shadow 0.18s;
  }
  .exchange-tabs .tab:hover {
    color: var(--text-primary);
    border-color: rgba(34, 211, 238, 0.4);
    background: rgba(34, 211, 238, 0.05);
  }
  .exchange-tabs .tab.active {
    color: var(--text-primary);
    border-color: var(--holo-cyan-bright, #22d3ee);
    background: rgba(34, 211, 238, 0.10);
    box-shadow: 0 0 0 2px rgba(34, 211, 238, 0.18),
                inset 0 0 12px rgba(34, 211, 238, 0.10);
  }
  .exchange-tabs .mode-badge {
    /* Rendered as a `●` character by JS in pollEngineHealth — color
       comes from inline style. Just constrain the size + alignment so
       the dot doesn't oversize the tab. */
    font-size: 10px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    text-shadow: 0 0 4px currentColor;
  }
  body.light-theme .exchange-tabs .tab { background: rgba(255,255,255,0.4); }
  /* Internal Data Objects */
  .signal-badge {
    display: inline-flex; align-items: center; gap: 10px;
    font-size: 26px; font-weight: 700;
    padding: 8px 16px; border-radius: 8px; margin-bottom: 8px;
    background: rgba(153, 69, 255, 0.15); /* Purple tint from screenshot */
    border: 1px solid rgba(153, 69, 255, 0.3);
    color: #9945ff; /* Match screenshot SOL purple */
    box-shadow: inset 0 0 20px rgba(153, 69, 255, 0.1);
  }
  .asset-dot { width: 12px; height: 12px; border-radius: 50%; background: #9945ff; display: inline-block; box-shadow: 0 0 10px #9945ff; }
  
  .signal-meta { font-size: 10px; color: var(--text-secondary); margin-top: 6px; display: flex; align-items: center; gap: 8px; }
  .signal-meta strong { color: var(--text-primary); }


  .holding-item {
    background: var(--card-bg); 
    border: 1px solid var(--card-border-side);
    border-radius: 6px; padding: 8px 10px;
    display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;
    box-shadow: var(--card-shadow), inset 0 0 10px rgba(255,255,255,0.05);
  }
  .holding-asset { font-weight: 700; font-size: 12px; color: var(--text-primary); }
  .holding-qty { font-size: 10px; color: var(--text-secondary); }
  .holding-val { font-size: 14px; font-weight: 600; color: var(--text-primary); }

  .prot-banner {
    display: flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 6px; margin-bottom: 8px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px;
    background: rgba(6,182,212,0.12); color: var(--accent-cyan); border: 1px solid rgba(6,182,212,0.25);
    box-shadow: inset 0 0 15px rgba(6,182,212,0.15);
  }

  .prot-row {
    padding: 6px 8px; 
    background: var(--card-bg); 
    border: 1px solid var(--card-border-side);
    border-radius: 6px; margin-bottom: 6px;
    box-shadow: var(--card-shadow), inset 0 0 10px rgba(255,255,255,0.05);
  }
  .prot-row-label { font-size: 9px; color: var(--text-muted); text-transform: uppercase; margin-bottom: 3px; display: flex; justify-content: space-between; }
  .prot-row-value { font-size: 14px; font-weight: 700; color: var(--text-primary); text-shadow: 0 0 8px var(--glass-edge-bg); }
  .prot-row-thresh { font-size: 9px; color: var(--text-muted); margin-top: 1px; }
  
  .status-tag {
    font-size: 8px; padding: 2px 6px; border-radius: 3px; display: inline-block;
    background: rgba(34,197,94,0.1); border: 1px solid rgba(34,197,94,0.15); color: var(--accent-green);
  }

  .rank-item {
    padding: 5px 8px; border-radius: 5px; margin-bottom: 4px; font-size: 11px; font-weight: 600;
    border: 1px solid rgba(255,255,255,0.05); 
    background: var(--card-bg); color: var(--text-primary);
  }
  .rank-row { display: flex; align-items: center; gap: 6px; }
  .rank-1 { border: 1px solid var(--card-border-top); box-shadow: inset 0 0 15px rgba(255,255,255,0.1); }
  .rank-num { font-size: 9px; color: var(--text-muted); width: 16px; text-align: center; }
  .rank-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; box-shadow: 0 0 6px currentColor; }
  .rank-name { flex: 1; }
  .rank-score { font-size: 9px; color: var(--text-secondary); min-width: 56px; text-align: right; }

  .chart-container { position: relative; width: 100%; height: 280px; margin-top: 16px; }
  
  .positive { color: var(--accent-green); text-shadow: 0 0 8px rgba(16, 185, 129, 0.2); }
  .negative { color: var(--accent-red); text-shadow: 0 0 8px rgba(239, 68, 68, 0.2); }
  .neutral { color: var(--text-secondary); }

  /* Production Theme Colors mapped. One entry per universe asset plus both
     cash assets — the 4-asset era left LTC/LINK/DOGE/USD undefined, so those
     signals fell through to inherited text colour. */
  .c-sol  { color: #9945ff; }
  .c-btc  { color: #f7931a; }
  .c-eth  { color: #627eea; }
  .c-xrp  { color: #00aae4; }
  .c-ltc  { color: #345d9d; }
  .c-link { color: #2a5ada; }
  .c-doge { color: #c2a633; }
  .c-usdt { color: #26a17b; }
  .c-usd  { color: #85c26f; }


  /* ── v7 INDEX.HTML FILE-SPECIFIC APPENDIX ── */

  /* Bridge: legacy CSS var names referenced by inline styles and scripts
     in the existing page markup. Mapped onto the mockup's glass tokens so
     existing .card/.holding-*/.prot-*/rank-* markup picks up both themes. */
  body.dark-theme {
    --bg-secondary: rgba(255, 255, 255, 0.04);
    --bg-primary: var(--bg-color);
    --accent-cyan: var(--holo-cyan-bright);
    --accent-purple: var(--holo-purple);
    --border: var(--card-border-side);
  }
  body.light-theme {
    --bg-secondary: rgba(0, 0, 0, 0.04);
    --bg-primary: var(--bg-color);
    --accent-cyan: var(--holo-cyan-bright);
    --accent-purple: var(--holo-purple);
    --border: var(--card-border-side);
  }

  /* Trade-toggle state variants (extends mockup's .trade-toggle base) */
  .trade-off { background: rgba(239,68,68,0.1); color: var(--accent-red); border-color: rgba(239,68,68,0.25); box-shadow: inset 0 0 10px rgba(239,68,68,0.1); }
  .trade-off .dot { background: var(--accent-red); box-shadow: 0 0 8px var(--accent-red); }
  .trade-paper { background: rgba(245,158,11,0.1); color: var(--accent-amber); border-color: rgba(245,158,11,0.25); box-shadow: inset 0 0 10px rgba(245,158,11,0.1); }
  .trade-paper .dot { background: var(--accent-amber); box-shadow: 0 0 8px var(--accent-amber); animation: pulse 2s infinite; }
  .trade-live { background: rgba(34,197,94,0.1); color: var(--accent-green); border-color: rgba(34,197,94,0.25); box-shadow: inset 0 0 10px rgba(34,197,94,0.1); }
  .trade-live .dot { background: var(--accent-green); box-shadow: 0 0 8px var(--accent-green); animation: pulse 2s infinite; }
  /* v7.1.7: STANDBY / PARTIAL variants for the header badge so the
     dot colour matches the per-venue tabs. STANDBY = every venue has
     keys but none is armed; PARTIAL = at least one venue is LIVE but
     not all. */
  .trade-standby { background: rgba(245,158,11,0.1); color: var(--accent-amber); border-color: rgba(245,158,11,0.25); box-shadow: inset 0 0 10px rgba(245,158,11,0.1); }
  .trade-standby .dot { background: var(--accent-amber); box-shadow: 0 0 8px var(--accent-amber); }
  .trade-partial { background: rgba(59,130,246,0.1); color: #60a5fa; border-color: rgba(59,130,246,0.25); box-shadow: inset 0 0 10px rgba(59,130,246,0.1); }
  .trade-partial .dot { background: #60a5fa; box-shadow: 0 0 8px #60a5fa; animation: pulse 2s infinite; }
  @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

  /* Signal badge asset variants */
  .signal-prev { font-size: 10px; color: var(--text-secondary); margin-bottom: 4px; }
  .signal-badge.signal-sol  { background: rgba(153,69,255,0.15);  border-color: rgba(153,69,255,0.3);  color: #9945ff; box-shadow: inset 0 0 20px rgba(153,69,255,0.1); }
  .signal-badge.signal-btc  { background: rgba(247,147,26,0.15);  border-color: rgba(247,147,26,0.3);  color: #f7931a; box-shadow: inset 0 0 20px rgba(247,147,26,0.1); }
  .signal-badge.signal-eth  { background: rgba(98,126,234,0.15);  border-color: rgba(98,126,234,0.3);  color: #627eea; box-shadow: inset 0 0 20px rgba(98,126,234,0.1); }
  .signal-badge.signal-xrp  { background: rgba(0,170,228,0.15);   border-color: rgba(0,170,228,0.3);   color: #00aae4; box-shadow: inset 0 0 20px rgba(0,170,228,0.1); }
  .signal-badge.signal-usdt { background: rgba(38,161,123,0.15);  border-color: rgba(38,161,123,0.3);  color: #26a17b; box-shadow: inset 0 0 20px rgba(38,161,123,0.1); }
  /* 7-asset universe + USD cash. Without these four the badge kept the
     generic purple default, so an LTC/LINK/DOGE winner (and every USD-cash
     protection state on Coinbase) rendered in SOL's colour. */
  .signal-badge.signal-ltc  { background: rgba(52,93,157,0.15);   border-color: rgba(52,93,157,0.3);   color: #345d9d; box-shadow: inset 0 0 20px rgba(52,93,157,0.1); }
  .signal-badge.signal-link { background: rgba(42,90,218,0.15);   border-color: rgba(42,90,218,0.3);   color: #2a5ada; box-shadow: inset 0 0 20px rgba(42,90,218,0.1); }
  .signal-badge.signal-doge { background: rgba(194,166,51,0.15);  border-color: rgba(194,166,51,0.3);  color: #c2a633; box-shadow: inset 0 0 20px rgba(194,166,51,0.1); }
  .signal-badge.signal-usd  { background: rgba(133,194,111,0.15); border-color: rgba(133,194,111,0.3); color: #85c26f; box-shadow: inset 0 0 20px rgba(133,194,111,0.1); }
  .signal-badge.signal-sol  .asset-dot { background: #9945ff; box-shadow: 0 0 10px #9945ff; }
  .signal-badge.signal-btc  .asset-dot { background: #f7931a; box-shadow: 0 0 10px #f7931a; }
  .signal-badge.signal-eth  .asset-dot { background: #627eea; box-shadow: 0 0 10px #627eea; }
  .signal-badge.signal-xrp  .asset-dot { background: #00aae4; box-shadow: 0 0 10px #00aae4; }
  .signal-badge.signal-usdt .asset-dot { background: #26a17b; box-shadow: 0 0 10px #26a17b; }
  .signal-badge.signal-ltc  .asset-dot { background: #345d9d; box-shadow: 0 0 10px #345d9d; }
  .signal-badge.signal-link .asset-dot { background: #2a5ada; box-shadow: 0 0 10px #2a5ada; }
  .signal-badge.signal-doge .asset-dot { background: #c2a633; box-shadow: 0 0 10px #c2a633; }
  .signal-badge.signal-usd  .asset-dot { background: #85c26f; box-shadow: 0 0 10px #85c26f; }

  /* Holdings value column */
  .holding-value { font-size: 14px; font-weight: 600; color: var(--text-primary); }

  /* Protection banner and status tag variants */
  .prot-banner.prot-adaptive  { background: rgba(6,182,212,0.12);  color: var(--holo-cyan-bright); border-color: rgba(6,182,212,0.25); box-shadow: inset 0 0 15px rgba(6,182,212,0.15); }
  .prot-banner.prot-triggered { background: rgba(239,68,68,0.12); color: var(--accent-red);       border-color: rgba(239,68,68,0.25); box-shadow: inset 0 0 15px rgba(239,68,68,0.15); }
  .prot-status { font-size: 8px; padding: 2px 6px; border-radius: 3px; display: inline-block; margin-top: 2px; }
  .prot-status-ok   { background: rgba(34,197,94,0.1); color: var(--accent-green); border: 1px solid rgba(34,197,94,0.15); }
  .prot-status-warn { background: rgba(239,68,68,0.1); color: var(--accent-red);   border: 1px solid rgba(239,68,68,0.15); }
  .prot-trigger-display { padding: 5px 8px; border-radius: 4px; margin-top: 6px; font-size: 9px; font-weight: 700; }

  /* Tables and misc text helpers */
  table { width: 100%; border-collapse: collapse; font-family: 'JetBrains Mono', monospace; font-size: 10px; }
  th { text-align: left; padding: 6px; color: var(--text-muted); font-weight: 600; font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px; border-bottom: 1px solid var(--glass-edge-bg); white-space: nowrap; }
  td { padding: 5px 6px; border-bottom: 1px solid rgba(255, 255, 255, 0.05); white-space: nowrap; }
  .mono { font-family: 'JetBrains Mono', monospace; }
  .empty-state { color: var(--text-muted); font-size: 10px; text-align: center; padding: 10px; font-family: 'JetBrains Mono', monospace; }
  .empty-state .icon { font-size: 16px; margin-bottom: 4px; display: block; }

  /* Tags used in signal log */
  .tag { font-family: 'JetBrains Mono', monospace; font-size: 8px; font-weight: 700; padding: 2px 6px; border-radius: 3px; text-transform: uppercase; }
  .tag-ok   { background: rgba(34, 197, 94, 0.15); color: var(--accent-green); }
  .tag-fix1 { background: rgba(239, 68, 68, 0.15); color: var(--accent-red); }
  .tag-fix2 { background: rgba(245, 158, 11, 0.15); color: var(--accent-amber); }

  /* ── SIGNAL INTEGRITY BAR ──
     The ranking signal is computed from a venue-independent price source
     (reconstructed hourly closes in the DB), not from either trading
     venue's candles. When that store goes stale the engine HOLDS the
     previous signal rather than rotating — a state that was previously
     invisible outside the process log. This bar is where the operator
     reads the input path's identity, coverage and freshness. */
  .integrity-bar {
    display: flex; align-items: center; flex-wrap: wrap; gap: 10px 22px;
    padding: 10px 14px; margin-bottom: 12px;
    border-radius: 10px;
    background: var(--card-bg);
    border: 1px solid var(--card-border-side);
    border-top-color: var(--card-border-top);
    box-shadow: var(--card-shadow), inset 0 0 20px rgba(34, 211, 238, 0.06);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    font-family: 'JetBrains Mono', monospace;
  }
  .integrity-state {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.6px; padding: 5px 11px; border-radius: 6px;
    white-space: nowrap;
  }
  .integrity-state .dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: currentColor; box-shadow: 0 0 8px currentColor;
  }
  .integrity-ready    { background: rgba(34,197,94,0.10);  color: var(--accent-green); border: 1px solid rgba(34,197,94,0.25); }
  .integrity-degraded { background: rgba(245,158,11,0.10); color: var(--accent-amber); border: 1px solid rgba(245,158,11,0.25); }
  .integrity-held     { background: rgba(239,68,68,0.10);  color: var(--accent-red);   border: 1px solid rgba(239,68,68,0.25); }
  .integrity-held .dot { animation: pulse 2s infinite; }
  .integrity-legacy   { background: rgba(148,163,184,0.10); color: var(--text-secondary); border: 1px solid rgba(148,163,184,0.25); }

  .integrity-field { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .integrity-field .k {
    font-family: 'Inter', sans-serif; font-size: 8px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.7px; color: var(--text-muted);
  }
  .integrity-field .v { font-size: 11px; font-weight: 600; color: var(--text-primary); }
  .integrity-field .v.warn { color: var(--accent-amber); }
  .integrity-field .v.bad  { color: var(--accent-red); }
  .integrity-spacer { flex: 1; }
  .integrity-link {
    font-size: 9px; color: var(--holo-cyan-bright); text-decoration: none;
    white-space: nowrap;
  }
  .integrity-link:hover { text-decoration: underline; }

  /* Marks a card whose contents are one decision shared by every
     execution venue, so the venue tabs above it do not filter it. */
  .venue-independent {
    font-family: 'Inter', sans-serif; font-size: 7px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.6px;
    padding: 2px 6px; border-radius: 3px; white-space: nowrap;
    background: rgba(34, 211, 238, 0.10); color: var(--holo-cyan-bright);
    border: 1px solid rgba(34, 211, 238, 0.22);
  }

  /* Shown only when two venues recorded different signals for the same
     cycle — impossible once inputs are shared, so it means a legacy row,
     a mid-cutover cycle, or a genuine fault worth investigating. */
  .divergence-banner {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 14px; margin-bottom: 12px; border-radius: 10px;
    font-family: 'JetBrains Mono', monospace; font-size: 11px;
    background: rgba(239, 68, 68, 0.10); color: var(--accent-red);
    border: 1px solid rgba(239, 68, 68, 0.30);
  }
  .divergence-banner strong { color: var(--text-primary); }

  /* Shadow parity: the live engine's signal vs an independently
     recomputed one. Reuses the divergence banner's shape but is
     dismissible, because it must stay up until the operator has
     actually seen it rather than clearing itself on the next
     agreeing signal. */
  .parity-banner {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 14px; margin-bottom: 12px; border-radius: 10px;
    font-family: 'JetBrains Mono', monospace; font-size: 11px;
    background: rgba(239, 68, 68, 0.10); color: var(--accent-red);
    border: 1px solid rgba(239, 68, 68, 0.30);
  }
  .parity-banner strong { color: var(--text-primary); }
  .parity-banner button {
    margin-left: auto; cursor: pointer;
    font-family: 'JetBrains Mono', monospace; font-size: 10px;
    padding: 3px 9px; border-radius: 5px;
    background: rgba(239, 68, 68, 0.14); color: var(--accent-red);
    border: 1px solid rgba(239, 68, 68, 0.34);
  }
  .parity-banner button:hover { background: rgba(239, 68, 68, 0.24); }

  /* ── TRADING STATUS GRID ──
     Two columns, three rows. Signal and Oracle Intelligence are narrow
     read-outs and share the first row; Holdings and Market Protection
     each span both columns because they need the width — Holdings to
     lay its assets out 5-across instead of a tall single column, and
     Protection so the drop sparkline and per-candle pips are legible. */
  .status-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 24px;
    /* stretch, not start: Signal is a short read-out next to a 7-row
       ranking, and letting it collapse left a hole in the row. */
    align-items: stretch;
  }
  .status-grid .span-2 { grid-column: 1 / -1; }
  @media (max-width: 900px) {
    .status-grid { grid-template-columns: 1fr; }
    .status-grid .span-2 { grid-column: auto; }
  }

  /* Holdings assets: 5 across, wrapping to a second row for a 7-asset
     universe plus cash. auto-fit keeps it sane on narrower viewports
     rather than crushing five columns into 300px. */
  .holdings-grid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 8px;
  }
  .holdings-grid .holding-item.is-empty { opacity: 0.42; }
  .holdings-grid .holding-item { margin-bottom: 0; flex-direction: column;
    align-items: flex-start; gap: 3px; }
  .holdings-grid .empty-state { grid-column: 1 / -1; }
  /* Zero-balance tiles are hidden entirely — only held positions render. */

  /* Signal card fills its row. The badge is the card's subject, so it
     centres in the space above the detail lines rather than clinging to
     the top and leaving a hole in the middle. */
  .signal-card { display: flex; flex-direction: column; }
  .signal-card .signal-badge { margin-top: auto; margin-bottom: auto; }
  .signal-card-foot { margin-top: auto; }

  /* Protection state column (banner + min-hold + active trigger). */
  .prot-col { display: flex; flex-direction: column; gap: 8px; }
  .prot-col .prot-banner { margin-bottom: 0; }
  .prot-col .prot-trigger-display { margin-top: auto; }
  @media (max-width: 1400px) { .holdings-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
  @media (max-width: 1100px) { .holdings-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
  @media (max-width: 760px)  { .holdings-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

  /* Scope total lives on the title row now that the card is wide. */
  .holdings-total-inline {
    display: flex; align-items: baseline; gap: 8px; white-space: nowrap;
    font-family: 'JetBrains Mono', monospace;
  }
  .holdings-total-inline .k {
    font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px;
    color: var(--text-muted);
  }
  .holdings-total-inline .v { font-size: 14px; font-weight: 700; color: var(--text-primary); }

  /* Protection rows sit side by side in the wide card. */
  .prot-rows {
    display: grid;
    /* Three explicit tracks: state column, absolute drop, consecutive
       losses. auto-fit left empty phantom tracks at wide viewports. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    align-items: stretch;
  }
  @media (max-width: 1200px) { .prot-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (max-width: 800px)  { .prot-rows { grid-template-columns: 1fr; } }
  .prot-rows .prot-row { margin-bottom: 0; }

  /* Feed behind the price on the Signal card. Amber when the page is
     not quoting the book the signal was computed on. */
  .price-source {
    font-family: 'JetBrains Mono', monospace; font-size: 8px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.4px; white-space: nowrap;
    padding: 2px 6px; border-radius: 3px;
    background: rgba(34, 211, 238, 0.10); color: var(--holo-cyan-bright);
    border: 1px solid rgba(34, 211, 238, 0.22);
  }
  .price-source.degraded {
    background: rgba(245, 158, 11, 0.10); color: var(--accent-amber);
    border-color: rgba(245, 158, 11, 0.28);
  }

  /* ── PER-CARD VENUE SCOPE SELECTOR ──
     Used where a single card is genuinely per-venue (holdings) on a page
     that is otherwise portfolio-level. Deliberately lighter than the
     global .exchange-tabs so it reads as a card control, not page nav. */
  .venue-scope { display: inline-flex; gap: 3px; flex-wrap: wrap; }
  .venue-scope button {
    font-family: 'JetBrains Mono', monospace;
    font-size: 8px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.4px; padding: 3px 7px; border-radius: 4px;
    cursor: pointer; transition: all 0.18s;
    background: transparent; color: var(--text-muted);
    border: 1px solid transparent;
  }
  .venue-scope button:hover { color: var(--text-primary); background: var(--card-bg); }
  .venue-scope button.active {
    color: var(--holo-cyan-bright);
    background: rgba(34, 211, 238, 0.10);
    border-color: rgba(34, 211, 238, 0.30);
  }
  .holdings-total {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-top: 8px; padding-top: 8px;
    border-top: 1px solid var(--glass-edge-bg);
    font-family: 'JetBrains Mono', monospace;
  }
  .holdings-total .k {
    font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px;
    color: var(--text-muted);
  }
  .holdings-total .v { font-size: 14px; font-weight: 700; color: var(--text-primary); }

  /* ── PROTECTION DETAIL ──
     A threshold is only meaningful next to the distance still to run, so
     the card shows progress toward each trigger rather than a bare
     number: a meter for the drop and min-hold, one pip per candle for
     the consecutive-loss streak. */
  .prot-meter {
    height: 4px; border-radius: 3px; margin-top: 5px; overflow: hidden;
    background: rgba(148, 163, 184, 0.18);
  }
  .prot-meter-fill {
    height: 100%; width: 0%; border-radius: 3px;
    background: var(--accent-green);
    transition: width 0.35s ease, background-color 0.35s ease;
  }
  .prot-meter-fill.warn { background: var(--accent-amber); }
  .prot-meter-fill.bad  { background: var(--accent-red); }

  .prot-pips { display: flex; gap: 3px; margin-top: 5px; flex-wrap: wrap; }
  .prot-pip {
    flex: 1 1 0; min-width: 8px; height: 14px; border-radius: 3px;
    display: flex; align-items: center; justify-content: center;
    font-family: 'JetBrains Mono', monospace; font-size: 7px; font-weight: 700;
    background: rgba(148, 163, 184, 0.15); color: var(--text-muted);
    border: 1px solid transparent;
  }
  .prot-pip.loss {
    background: rgba(239, 68, 68, 0.18); color: var(--accent-red);
    border-color: rgba(239, 68, 68, 0.35);
  }

  .prot-spark {
    display: flex; align-items: flex-end; gap: 2px;
    height: 22px; margin-top: 6px;
  }
  .prot-spark .bar {
    flex: 1 1 0; min-width: 2px; border-radius: 1px;
    background: var(--accent-red); opacity: 0.75;
  }
  .prot-spark .bar.ok { background: var(--accent-green); }

  /* ── PER-VENUE EXECUTION PANELS ── */
  .exec-venue-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
    gap: 10px;
  }
  .exec-venue {
    border: 1px solid var(--card-border-side); border-radius: 8px;
    padding: 10px 12px; background: var(--bg-secondary);
  }
  .exec-venue-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; margin-bottom: 8px;
  }
  .exec-venue-name {
    font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700;
    display: inline-flex; align-items: center; gap: 6px; text-transform: capitalize;
  }
  .exec-venue-name .dot {
    width: 7px; height: 7px; border-radius: 50%; background: currentColor;
    box-shadow: 0 0 6px currentColor;
  }
  .exec-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
  .exec-kpi {
    border: 1px solid var(--card-border-side); border-radius: 6px;
    padding: 6px 8px; text-align: center;
  }
  .exec-kpi .k {
    font-family: 'Inter', sans-serif; font-size: 7px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-muted);
  }
  .exec-kpi .v {
    font-family: 'JetBrains Mono', monospace; font-size: 15px; font-weight: 700;
    color: var(--holo-cyan-bright); line-height: 1.3;
  }
  .exec-kpi .s {
    font-family: 'JetBrains Mono', monospace; font-size: 8px; color: var(--text-muted);
  }

  .exec-chain {
    margin-top: 8px; border-radius: 6px; padding: 8px 10px;
    border: 1px solid var(--card-border-side);
    background: var(--card-bg);
  }
  .exec-chain.buy  { border-left: 3px solid var(--holo-cyan-bright); }
  .exec-chain.sell { border-left: 3px solid var(--accent-amber); }
  .exec-chain-head {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 700;
    margin-bottom: 6px;
  }
  .exec-chain-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
    gap: 6px 8px; margin-bottom: 6px;
  }
  .exec-chain-grid .k {
    font-family: 'Inter', sans-serif; font-size: 7px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted);
    display: block;
  }
  .exec-chain-grid .v {
    font-family: 'JetBrains Mono', monospace; font-size: 12px; font-weight: 700;
    color: var(--text-primary);
  }
  .exec-bar {
    height: 4px; border-radius: 3px; overflow: hidden; margin-top: 3px;
    background: rgba(148, 163, 184, 0.18);
  }
  .exec-bar > span {
    display: block; height: 100%; width: 0%; border-radius: 3px;
    transition: width 0.35s ease;
  }
  .exec-steps {
    font-family: 'JetBrains Mono', monospace; font-size: 8px;
    color: var(--text-muted); margin-top: 6px; line-height: 1.7;
    word-break: break-word;
  }
  .exec-steps .now  { color: var(--holo-cyan-bright); font-weight: 700; }
  .exec-steps .past { color: var(--accent-green); }
  .exec-tag {
    font-family: 'JetBrains Mono', monospace; font-size: 7px; font-weight: 700;
    padding: 1px 5px; border-radius: 3px; text-transform: uppercase;
    letter-spacing: 0.4px;
  }

  /* Footer line */
  .footer { font-family: 'JetBrains Mono', monospace; font-size: 9px; color: var(--text-muted); text-align: center; padding: 16px 0; margin-top: 8px; }

  /* Header metric color helpers (reinforce mockup neutral/positive/negative) */
  .header-metric-value.positive, .header-metric-sub.positive { color: var(--accent-green); }
  .header-metric-value.negative, .header-metric-sub.negative { color: var(--accent-red); }
  .header-metric-value.neutral,  .header-metric-sub.neutral  { color: var(--text-secondary); }

  /* Responsive shrink for narrow viewports */
  @media (max-width: 1200px) {
    .grid4 { grid-template-columns: 1fr 1fr; }
    .grid2 { grid-template-columns: 1fr; }
  }
  @media (max-width: 768px) {
    .grid4, .grid2 { grid-template-columns: 1fr; }
    .header-metrics { gap: 10px; }
    .header-metric-value { font-size: 11px; }
  }
