  :root{
    --bg: #0b0d12;
    --bg-vignette: #06070a;
    --dot: #8a4dd1;
    --dot-bright: #b07fff;
    --rim: #8c3dff;
    --pill-bg: rgba(20,23,32,0.92);
    --pill-border: rgba(160,120,200,0.25);
    --pill-text: #e8ebf5;
    --pct-text: #c2aacf;
    --accent: #9b5bff;
    --text-muted: #aab4cf;
    --text-dim: #8a93b0;
    --text-faint: #6b7591;
    --text-faintest: #5c6480;
    --text-closed: #7a5a8f;
    --surface-2: #1c1f29;
    --glow-soft: rgba(140,70,200,0.10);
    --rim-glow-1: rgba(140,60,255,0.16);
    --rim-glow-2: rgba(140,60,255,0.07);
    --dot-key-glow: rgba(176,127,255,0.7);
    --accent-wash: rgba(155,91,255,0.15);
    --accent-wash-strong: rgba(155,91,255,0.22);
    --accent-glow: rgba(155,91,255,0.7);
    --accent-glow-soft: rgba(155,91,255,0.35);
    --track-bg: rgba(170,180,207,0.3);
    --hairline: rgba(160,120,200,0.12);
    --backdrop-scrim: rgba(6,7,10,0.55);
    --menu-shadow: rgba(0,0,0,0.5);
  }
  /* Blue/cream theme, toggled via [Theme] — see globe-core.js's applyTheme(),
     which sets this attribute and also recolors the globe's WebGL materials
     (CSS variables can't reach into the canvas). The blue here approximates
     Polymarket's brand blue. */
  html[data-theme="light"]{
    --bg: #fbf8f0;
    --bg-vignette: #f3eee0;
    --dot: #0a2175;
    --dot-bright: #0a2175;
    --rim: #2f6bff;
    --pill-bg: rgba(255,255,255,0.85);
    --pill-border: rgba(22,82,240,0.25);
    --pill-text: #14213d;
    --pct-text: #2a3b6b;
    --accent: #0040e0;
    --text-muted: #3d4a73;
    --text-dim: #6b7798;
    --text-faint: #8b96b5;
    --text-faintest: #abb4cc;
    --text-closed: #9298b8;
    --surface-2: #eaf0ff;
    --glow-soft: rgba(22,82,240,0.08);
    --rim-glow-1: rgba(22,82,240,0.18);
    --rim-glow-2: rgba(22,82,240,0.08);
    --dot-key-glow: rgba(22,82,240,0.5);
    --accent-wash: rgba(22,82,240,0.12);
    --accent-wash-strong: rgba(22,82,240,0.18);
    --accent-glow: rgba(22,82,240,0.55);
    --accent-glow-soft: rgba(22,82,240,0.28);
    --track-bg: rgba(60,70,100,0.25);
    --hairline: rgba(22,82,240,0.15);
    --backdrop-scrim: rgba(237,230,214,0.65);
    --menu-shadow: rgba(20,30,60,0.18);
  }
  *{ box-sizing: border-box; }
  html, body{
    margin:0; padding:0;
    background: var(--bg);
    color: var(--pill-text);
    font-family: "JetBrains Mono", monospace;
    overflow: hidden;
    width: 100%;
    height: 100%;
  }
  /* Cross-page fade (see page-transition.js): an inline script adds
     'pre-fade' to <html> before first paint so the page starts invisible,
     then the page's own script removes it once ready, fading body in.
     Navigating away does the reverse before the actual page unload. */
  body{ transition: opacity 0.22s ease; }
  html.pre-fade body{ opacity: 0; }
  #stage{
    position: relative;
    width: 100%;
    height: 100vh;
    min-height: 560px;
    background:
      radial-gradient(circle at 50% 42%, var(--glow-soft), transparent 55%),
      var(--bg-vignette);
    display:flex;
    align-items:center;
    justify-content:center;
  }

  /* info.html: globe + text panel as one centered group, instead of the
     main page's filters/METAR/screener/controls (which info.html simply
     doesn't include). */
  #stage.info-stage{
    justify-content: center;
    gap: 72px;
    padding: 0 32px;
  }
  .info-stage #canvas-wrap{
    flex-shrink: 0;
    width: min(86vh, 48vw, 860px);
    height: min(86vh, 48vw, 860px);
  }
  #info-text{
    max-width: 520px;
    color: var(--pill-text);
  }
  #info-text h1{
    font-size: 32px;
    margin: 0 0 20px;
    color: var(--pill-text);
    font-weight: 700;
  }
  #info-text p{
    font-size: 16px;
    line-height: 1.65;
    color: var(--text-muted);
    margin: 0 0 16px;
  }
  #info-text .bottom-link-btn{
    display: inline-block;
    margin-top: 14px;
    font-size: 14px;
  }
  #canvas-wrap{
    position: relative;
    width: min(82vh, 82vw, 760px);
    height: min(82vh, 82vw, 760px);
  }
  canvas{
    display:block;
    width: 100%;
    height: 100%;
  }
  /* Sized to match the sphere's actual on-screen footprint, not the full
     canvas box: with camera at z=3.1, fov=45, radius=1.0, the sphere
     diameter is ~77.9% of the canvas-wrap height. This sits a hair
     outside that edge so the soft falloff reads as a halo, not a gap. */
  .glow-ring{
    position:absolute;
    inset: 10.5%;
    border-radius:50%;
    pointer-events:none;
    box-shadow:
      0 0 36px 6px var(--rim-glow-1),
      0 0 70px 18px var(--rim-glow-2);
  }
  .pill{
    position:absolute;
    transform: translate(-50%, -50%);
    display:flex;
    align-items:center;
    gap:7px;
    padding:6px 12px 6px 6px;
    background: var(--pill-bg);
    border: 1px solid var(--pill-border);
    border-radius: 999px;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    pointer-events:auto;
    backdrop-filter: blur(2px);
    will-change: transform, opacity;
    transition: opacity 0.08s linear;
  }
  .pill .flag{
    width: 22px;
    height: 22px;
    border-radius:50%;
    display:flex;
    align-items:center;
    justify-content:center;
    font-size: 14px;
    background: var(--surface-2);
    overflow:hidden;
    flex-shrink:0;
  }
  .pill .name{
    color: var(--pill-text);
  }

  /* Top-left. The dot-key is a small decorative legend dot, kept right
     next to the [Theme: ...] button instead of stacked below it. */
  #theme-control{
    position:absolute;
    top:18px;
    left:18px;
    z-index:3;
    display:flex;
    align-items:center;
    gap:10px;
  }
  .dot-key{
    width:6px;height:6px;border-radius:50%;
    background:var(--dot-bright);
    display:inline-block;
    box-shadow:0 0 6px 1px var(--dot-key-glow);
  }
  #continent-bar{
    position:absolute;
    top:18px;
    left:50%;
    transform: translateX(-50%);
    display:flex;
    gap:6px;
    z-index: 2;
  }
  .continent-button{
    background: none;
    border: none;
    color: var(--text-muted);
    font-size:12px;
    padding:7px 4px;
    cursor:pointer;
    font-family:inherit;
    transition: color 0.15s;
  }
  .continent-button::before{ content: '['; margin-right:4px; }
  .continent-button::after{ content: ']'; margin-left:4px; }
  .continent-button:hover{
    color: var(--pill-text);
  }
  .continent-button.is-active{
    color: var(--accent);
    font-weight: 700;
  }
  #metar-panel{
    position:absolute;
    top:50%;
    left:18px;
    max-height: calc(100vh - 120px);
    width:230px;
    overflow-y:auto;
    font-size:12px;
    z-index:2;
    opacity:0;
    pointer-events:none;
    transform: translate(-10px, -50%);
    transition: opacity 0.25s ease, transform 0.25s ease;
  }
  #metar-panel.visible{
    opacity:1;
    pointer-events:auto;
    transform: translate(0, -50%);
  }
  #metar-panel.is-swapping{ opacity:0.12; }
  #metar-panel{ scrollbar-width:none; -ms-overflow-style:none; }
  #metar-panel::-webkit-scrollbar{ display:none; }

  .metar-station{ margin-bottom:2px; }
  .metar-row{
    display:grid;
    grid-template-columns: auto 1fr auto auto;
    align-items:center;
    gap:8px;
    padding:6px 4px;
    color: var(--text-muted);
    cursor:pointer;
    white-space:nowrap;
  }
  .metar-row:hover{ color: var(--pill-text); }
  .metar-row .metar-id::before{ content:'['; }
  .metar-row .metar-id::after{ content:']'; }
  .metar-row .metar-id{ color: var(--text-dim); }
  .metar-row .metar-name{ font-weight:700; overflow:hidden; text-overflow:ellipsis; }
  .metar-row .metar-time{ color: var(--text-faint); font-size:11px; text-align:right; }
  .metar-row .metar-temp{ color: var(--dot-bright); text-align:right; }
  .metar-row.is-open .metar-name{ color: var(--pill-text); }
  .metar-row.is-open .metar-id{ color: var(--accent); }
  .metar-row.is-selected .metar-name{ color: var(--accent); font-weight:700; }
  .metar-row.is-selected .metar-id{ color: var(--accent); }

  .metar-detail{
    max-height:0;
    overflow-y:auto;
    padding:0 4px;
    color: var(--text-dim);
    opacity:0;
    transition: max-height 0.25s ease, opacity 0.2s ease, padding 0.25s ease;
  }
  .metar-detail.is-expanded{
    max-height:140px;
    padding:2px 4px 8px 4px;
    opacity:1;
  }
  .metar-detail{ scrollbar-width:none; -ms-overflow-style:none; }
  .metar-detail::-webkit-scrollbar{ display:none; }
  .metar-obs-line{
    display:flex;
    gap:8px;
    padding:3px 0;
    font-size:11px;
  }
  .metar-obs-line .metar-obs-time{ color: var(--text-faint); flex-shrink:0; width:42px; }
  .metar-obs-line .metar-obs-temp{ color: var(--pct-text); flex-shrink:0; width:36px; }
  .metar-obs-line .metar-obs-raw{ color: var(--text-faintest); overflow:hidden; text-overflow:ellipsis; }
  .metar-empty, .metar-loading{ color: var(--text-faintest); padding:6px 4px; font-style:italic; }

  @keyframes panel-fade-in{
    from{ opacity:0; transform: translateY(2px); }
    to{ opacity:1; transform: translateY(0); }
  }
  .metar-loading, .metar-empty,
  .screener-loading, .screener-empty{
    animation: panel-fade-in 0.18s ease;
  }
  .retry-btn{
    background:none;
    border:1px solid var(--pill-border);
    color: var(--accent);
    font-family:inherit;
    font-size:11px;
    padding:3px 8px;
    margin-left:8px;
    border-radius:6px;
    cursor:pointer;
    font-style:normal;
    transition: background 0.15s, color 0.15s;
  }
  .retry-btn:hover{
    background: var(--accent-wash);
    color: var(--pill-text);
  }

  #type-bar{
    position:absolute;
    top:18px;
    right:18px;
    display:flex;
    gap:6px;
    z-index: 2;
  }
  #type-bar .continent-button{
    opacity: 0.25;
    transition: opacity 0.15s, color 0.15s;
  }
  #type-bar .continent-button.is-active{
    opacity: 1;
  }

  #screener-panel{
    position:absolute;
    top:50%;
    right:18px;
    max-height: calc(100vh - 120px);
    width:320px;
    overflow-y:auto;
    font-size:12px;
    z-index:2;
    opacity:0;
    pointer-events:none;
    transform: translate(10px, -50%);
    transition: opacity 0.25s ease, transform 0.25s ease;
  }
  #screener-panel.visible{
    opacity:1;
    pointer-events:auto;
    transform: translate(0, -50%);
  }
  #screener-panel.is-swapping{ opacity:0.12; }
  #screener-panel{ scrollbar-width:none; -ms-overflow-style:none; }
  #screener-panel::-webkit-scrollbar{ display:none; }

  .screener-city{ margin-bottom:6px; }
  .screener-city-header{
    color: var(--text-dim);
    padding:6px 4px 2px 4px;
    display:grid;
    grid-template-columns: 1fr auto auto;
    align-items:center;
    gap:8px;
    white-space:nowrap;
  }
  .screener-col-city{
    display:flex;
    align-items:center;
    gap:4px;
    overflow:hidden;
  }
  .screener-city-header .screener-city-name::before{ content:'['; color: var(--text-dim); }
  .screener-city-header .screener-city-name::after{ content:']'; color: var(--text-dim); }
  .screener-city-header .screener-city-name{ color: var(--text-muted); font-weight:700; overflow:hidden; text-overflow:ellipsis; }
  .screener-city-header:hover .screener-city-name{ color: var(--pill-text); }
  /* Tracks actual expansion state (a day open, click or keyboard) rather
     than just keyboard focus — see toggleEventDetail's is-expanded toggle
     on nameEl. Glow instead of flat color, consistent with the bucket
     highlight's .is-observed treatment, just dialed back since this one's
     visible on every expanded city at once rather than a single bucket. */
  .screener-city-name.is-expanded{ color: var(--accent); text-shadow: 0 0 4px var(--accent-glow-soft); }
  /* Keyboard-cursor position, separate from expansion — same color as
     :hover so arrowing through cities reads the same way mousing over them
     does. The :not(.is-expanded) guard makes expansion win whenever both
     apply (e.g. right after pressing Enter, the cursor is still on the city
     you just expanded) — expanded should always show the accent glow,
     keyboard focus should only show its own color while nothing's open. */
  .screener-city-name.is-selected:not(.is-expanded){ color: var(--pill-text); }

  .screener-city-arrow{
    color: var(--accent);
    cursor:pointer;
    flex-shrink:0;
  }
  .screener-city-arrow:hover{ text-shadow: 0 0 6px var(--accent); }

  .screener-col-days{ display:flex; gap:4px; }
  .screener-col-tte{
    color: var(--text-faintest);
    font-size:11px;
    text-align:right;
    min-width:58px;
  }
  .screener-col-tte.is-closed{ color: var(--text-closed); }
  /* TTE is important to read at a glance; on light theme the faint/faintest
     grays are too pale against cream, so bold + darken it specifically
     there rather than touching the shared --text-faint(est) vars (which
     other, lower-priority elements also use). */
  html[data-theme="light"] .screener-col-tte{ font-weight:700; }
  html[data-theme="light"] .screener-col-tte:not(.is-closed){ color: var(--text-dim); }
  .screener-day-btn{
    background:none;
    border:none;
    color: var(--text-faint);
    font-size:11px;
    padding:2px 2px;
    cursor:pointer;
    font-family:inherit;
  }
  .screener-day-btn:hover{ color: var(--text-muted); }
  .screener-day-btn.is-open{ color: var(--accent); font-weight:700; }
  .screener-day-btn.is-selected{
    background: var(--accent-wash-strong);
    border-radius:3px;
  }

  .screener-event-detail{
    max-height:0;
    /* hidden, not auto — this container itself never scrolls. It's just
       the accordion that clips the title/stats/list during the expand
       animation; only .screener-market-list below scrolls. */
    overflow:hidden;
    padding:0 4px 0 14px;
    opacity:0;
    transition: max-height 0.25s ease, opacity 0.2s ease, padding 0.25s ease;
  }
  .screener-event-detail.is-expanded{
    max-height:220px;
    padding:4px 4px 10px 14px;
    opacity:1;
  }
  /* Cross-fade dip used when switching between days — same is-swapping
     class/mechanism as the METAR/screener panel swaps, just a shallower
     dip since this is a small in-panel content swap, not a full panel. */
  .screener-event-detail.is-expanded.is-swapping{ opacity:0.35; }

  /* The actual scrolling region — just the orderbook rows. The title and
     volume/observed stats live outside this, so they stay put while only
     the orderbook scrolls underneath them. */
  .screener-market-list{
    max-height:160px;
    overflow-y:auto;
    scrollbar-width:none; -ms-overflow-style:none;
  }
  .screener-market-list::-webkit-scrollbar{ display:none; }

  .screener-event-full-title{
    color: var(--pill-text);
    white-space:normal;
    line-height:1.4;
    margin-bottom:4px;
  }
  .screener-event-tte{ color: var(--text-faint); font-size:11px; margin-bottom:2px; }
  .screener-event-tte.is-closed{ color: var(--text-closed); }
  html[data-theme="light"] .screener-event-tte{ font-weight:700; }
  html[data-theme="light"] .screener-event-tte:not(.is-closed){ color: var(--text-dim); }

  .screener-event-stats{
    display:flex;
    justify-content:space-between;
    color: var(--text-dim);
    font-size:11px;
    margin-bottom:6px;
  }

  .screener-market-line{
    display:flex;
    gap:8px;
    padding:3px 0;
    font-size:11px;
    align-items:baseline;
  }
  .screener-market-bucket{ color: var(--pct-text); flex:1; overflow:hidden; text-overflow:ellipsis; }
  .screener-market-bucket.is-observed{ color: var(--accent); text-shadow: 0 0 6px var(--accent-glow); }
  .screener-market-bid{ flex-shrink:0; width:54px; text-align:right; }
  .screener-market-ask{ flex-shrink:0; width:54px; text-align:right; color: var(--text-faint); }
  .screener-market-spread{ flex-shrink:0; width:34px; text-align:right; color: var(--text-faintest); }

  .screener-empty, .screener-loading{ color: var(--text-faintest); padding:6px 4px; font-style:italic; }

  #controls{
    position:absolute;
    bottom:18px;
    left:18px;
    display:flex;
    gap:8px;
  }
  #controls button{
    background: none;
    border: none;
    color: var(--text-muted);
    font-size:12px;
    padding:7px 4px;
    cursor:pointer;
    font-family:inherit;
    transition: color 0.15s;
  }
  #controls button::before{ content: '['; margin-right:4px; }
  #controls button::after{ content: ']'; margin-left:4px; }
  #controls button:hover{
    color: var(--pill-text);
  }
  #controls button.active{
    color: var(--accent);
    font-weight: 700;
  }

  .opacity-control{
    position:relative;
    display:flex;
    align-items:center;
    color: var(--text-muted);
    font-size:12px;
    padding:7px 4px;
    font-family:inherit;
    transition: color 0.15s;
  }
  .opacity-control::before{ content: '['; margin-right:4px; }
  .opacity-control::after{ content: ']'; margin-left:4px; }
  .opacity-control:hover,
  .opacity-control:focus-within{
    color: var(--pill-text);
  }
  .opacity-label{ white-space:nowrap; }
  #opacity-slider{
    -webkit-appearance:none;
    appearance:none;
    width:0;
    height:3px;
    margin:0;
    opacity:0;
    pointer-events:none;
    background: var(--track-bg);
    border-radius:2px;
    outline:none;
    vertical-align:middle;
    transition: width 0.18s ease, opacity 0.18s ease, margin-left 0.18s ease;
  }
  .opacity-control:hover #opacity-slider,
  .opacity-control:focus-within #opacity-slider{
    width:90px;
    opacity:1;
    pointer-events:auto;
    margin-left:8px;
  }
  #opacity-slider::-webkit-slider-thumb{
    -webkit-appearance:none;
    width:10px;
    height:10px;
    border-radius:50%;
    background: var(--accent);
    cursor:pointer;
    box-shadow:0 0 6px 1px var(--accent-glow);
  }
  #opacity-slider::-moz-range-thumb{
    width:10px;
    height:10px;
    border-radius:50%;
    border:none;
    background: var(--accent);
    cursor:pointer;
    box-shadow:0 0 6px 1px var(--accent-glow);
  }
  #opacity-slider::-moz-range-track{
    background: var(--track-bg);
    height:3px;
    border-radius:2px;
  }

  #commands-control{
    position:absolute;
    bottom:18px;
    right:18px;
    z-index:3;
    display:flex;
    align-items:center;
    gap:4px;
  }
  .bottom-link-btn{
    background: none;
    border: none;
    color: var(--text-muted);
    font-size:12px;
    padding:7px 4px;
    cursor:pointer;
    font-family:inherit;
    text-decoration:none;
    transition: color 0.15s;
  }
  .bottom-link-btn::before{ content: '['; margin-right:4px; }
  .bottom-link-btn::after{ content: ']'; margin-left:4px; }
  .bottom-link-btn:hover{ color: var(--pill-text); }
  .bottom-link-btn.active{ color: var(--accent); font-weight: 700; }

  .commands-backdrop{
    position:fixed;
    inset:0;
    z-index:10;
    display:flex;
    align-items:center;
    justify-content:center;
    background: var(--backdrop-scrim);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    animation: commands-fade-in 0.15s ease;
  }
  .commands-backdrop[hidden]{
    display:none;
  }
  @keyframes commands-fade-in{
    from{ opacity:0; }
    to{ opacity:1; }
  }
  .commands-menu{
    width:min(420px, 86vw);
    background: var(--pill-bg);
    border: 1px solid var(--pill-border);
    border-radius: 14px;
    padding: 22px 26px;
    box-shadow: 0 20px 60px var(--menu-shadow);
    animation: commands-pop-in 0.16s ease;
  }
  @keyframes commands-pop-in{
    from{ opacity:0; transform: scale(0.96); }
    to{ opacity:1; transform: scale(1); }
  }
  .commands-title{
    color: var(--pill-text);
    font-size:14px;
    font-weight:700;
    margin-bottom:14px;
    text-transform:uppercase;
    letter-spacing:0.04em;
  }
  .commands-row{
    display:flex;
    justify-content:space-between;
    gap:16px;
    padding:8px 0;
    font-size:13px;
    color: var(--text-muted);
    border-top: 1px solid var(--hairline);
  }
  .commands-row:first-of-type{ border-top:none; }
  .commands-key{
    color: var(--dot-bright);
    flex-shrink:0;
    font-weight:700;
  }
