/* Earth XI — Observatory shell.
 *
 * The app chrome: header, icon rail, contextual panel, right readout
 * column, ask bar. Loaded AFTER main.css, which still owns everything
 * this file doesn't replace — modals, inspect panel, toast, hover
 * tooltip, route card, chat panel, timeline, data-insights.
 *
 * Design rules carried from the handoff:
 *   • radius 0 everywhere except circular dots and the avatar
 *   • 1px hairlines; exactly two shadows (ask bar, live-dot glow)
 *   • colour is reserved for DATA — chrome decoration stays monochrome
 *   • no transition longer than 250ms in the chrome; globe motion is
 *     eased by Mapbox, never by CSS
 *
 * The rail and panel are LAYOUT SIBLINGS of the globe stage, not
 * overlays: the map shrinks instead of being covered. #mapContainer
 * moves from position:fixed to absolute inside .ex-stage, and
 * observatory.js calls map.resize() whenever the row geometry changes.
 */

:root {
  --ex-canvas:      #07080a;
  --ex-panel:       #0b0c0e;
  --ex-well:        #0f1113;
  --ex-line:        rgba(255,255,255,.08);
  --ex-line-2:      rgba(255,255,255,.1);
  --ex-line-3:      rgba(255,255,255,.16);
  --ex-line-hover:  rgba(255,255,255,.26);
  --ex-surface-hov: rgba(255,255,255,.035);
  --ex-ink:         #f2f3f5;
  --ex-ink-mid:     rgba(238,241,246,.72);
  --ex-ink-soft:    rgba(238,241,246,.82);
  --ex-ink-dim:     rgba(238,241,246,.45);
  --ex-ink-faint:   rgba(238,241,246,.34);
  --ex-ink-ghost:   rgba(238,241,246,.3);
  --ex-accent:      #34d27e;
  --ex-accent-hov:  #6ee7b7;
  --ex-accent-ink:  #06140c;
  --ex-accent-br:   rgba(52,210,126,.45);
  --ex-accent-fill: rgba(52,210,126,.12);
  --ex-accent-row:  rgba(52,210,126,.09);
  --ex-blue:        #60b5ff;
  --ex-red:         #f87171;
  --ex-violet:      #a78bfa;
  --ex-glass:       rgba(11,12,14,.82);
}

@keyframes exPulse { 0%, 100% { opacity: 1 } 50% { opacity: .3 } }
@keyframes exSweep { 0% { transform: translateX(-100%) } 100% { transform: translateX(300%) } }

/* ── Shell scaffold ─────────────────────────────────────────────── */

body { background: var(--ex-canvas) }

.ex-shell {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  background: var(--ex-canvas); color: var(--ex-ink);
  font-family: var(--font-body); font-size: 14px; line-height: 1.5;
  overflow: hidden; z-index: 5;
}
.ex-row { flex: 1 1 auto; display: flex; min-height: 0; position: relative }

/* The globe stage. #mapContainer is absolutely positioned inside it so
 * Mapbox fills exactly the space left over by the rail and panel. */
.ex-stage { flex: 1 1 auto; position: relative; min-width: 0; background: var(--ex-canvas) }
#mapContainer { position: absolute; inset: 0; z-index: 0 }

/* Shared micro-typography. */
.ex-mono { font-family: var(--font-mono) }
.ex-label {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(238,241,246,.38);
}

/* ── Header ─────────────────────────────────────────────────────── */

.ex-hdr {
  flex: 0 0 auto; height: 52px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 0 14px;
  background: var(--ex-panel); border-bottom: 1px solid var(--ex-line);
  z-index: 20;
}
.ex-hdr-l, .ex-hdr-r { display: flex; align-items: center; min-width: 0 }
.ex-hdr-l { gap: 14px }
.ex-hdr-r { gap: 6px }

.ex-icon-btn {
  width: 30px; height: 30px; display: grid; place-items: center;
  border: 1px solid var(--ex-line-2); background: transparent;
  color: var(--ex-ink-mid); cursor: pointer; padding: 0;
  transition: color .15s, border-color .15s;
}
.ex-icon-btn:hover { color: var(--ex-ink); border-color: rgba(255,255,255,.24) }

.ex-brand { display: flex; align-items: center; gap: 9px; min-width: 0 }
.ex-brand-name {
  font-family: var(--font-display); font-weight: 700; font-size: 14.5px;
  letter-spacing: -.01em; white-space: nowrap; color: var(--ex-ink);
}
.ex-brand-v { font-family: var(--font-mono); font-size: 10px; letter-spacing: .08em; color: rgba(238,241,246,.4) }
.ex-beta {
  font-family: var(--font-mono); font-size: 9px; letter-spacing: .16em;
  padding: 3px 6px; color: var(--ex-violet);
  border: 1px solid rgba(167,139,250,.32); background: rgba(167,139,250,.08);
}
.ex-quota {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .06em;
  padding: 3px 7px; color: rgba(238,241,246,.55); border: 1px solid var(--ex-line-2);
}

.ex-btn {
  display: inline-flex; align-items: center; gap: 7px;
  height: 30px; padding: 0 11px;
  border: 1px solid var(--ex-line-2); background: transparent;
  color: var(--ex-ink-mid); font-family: var(--font-body);
  font-size: 12.5px; font-weight: 500; cursor: pointer;
  transition: color .15s, border-color .15s;
}
.ex-btn:hover { color: var(--ex-ink); border-color: rgba(255,255,255,.24) }
/* Tool buttons latch on while their mode is armed (measure, route). */
.ex-btn.on, .ex-icon-btn.on {
  color: var(--ex-accent); border-color: var(--ex-accent-br);
  background: var(--ex-accent-fill);
}

.ex-div { width: 1px; height: 22px; background: var(--ex-line-2); margin: 0 4px }
.ex-status {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
  color: rgba(238,241,246,.5); white-space: nowrap;
}
.ex-status-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--ex-accent);
  box-shadow: 0 0 8px rgba(52,210,126,.8); animation: exPulse 2.4s ease-in-out infinite;
  flex: 0 0 auto;
}
.ex-avatar {
  width: 26px; height: 26px; display: grid; place-items: center;
  border: 1px solid rgba(52,210,126,.4); background: rgba(52,210,126,.1);
  color: var(--ex-accent); font-family: var(--font-mono); font-size: 11px;
  font-weight: 500; cursor: pointer;
}

/* ── Icon rail ──────────────────────────────────────────────────── */

.ex-rail {
  flex: 0 0 auto; width: 58px;
  display: flex; flex-direction: column; align-items: stretch; gap: 2px;
  padding: 8px 0; background: var(--ex-panel);
  border-right: 1px solid var(--ex-line); z-index: 12;
}
.ex-rail-btn {
  position: relative; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px;
  height: 52px; border: none; background: transparent;
  color: var(--ex-ink-dim); cursor: pointer;
  font-family: var(--font-mono); font-size: 8.5px; letter-spacing: .08em;
  text-transform: uppercase; padding: 0;
  transition: color .15s, background-color .15s;
}
.ex-rail-btn:hover { color: var(--ex-ink); background: var(--ex-surface-hov) }
.ex-rail-btn.on { color: var(--ex-accent) }
.ex-rail-btn::before {
  content: ''; position: absolute; left: 0; top: 8px; bottom: 8px;
  width: 2px; background: transparent;
}
.ex-rail-btn.on::before { background: var(--ex-accent) }
.ex-rail-btn svg { width: 17px; height: 17px }
.ex-rail-spacer { flex: 1 }
.ex-rail-btn.ex-rail-help { height: 48px; color: rgba(238,241,246,.4) }
.ex-rail-btn.ex-rail-help svg { width: 16px; height: 16px }

/* ── Contextual panel ───────────────────────────────────────────── */

.ex-panel {
  flex: 0 0 auto; width: 308px;
  display: flex; flex-direction: column;
  background: var(--ex-panel); border-right: 1px solid var(--ex-line);
  overflow: hidden; z-index: 11;
}
/* `.closed` (not a new class) so ui.js's toggleSidebar keeps working. */
.ex-panel.closed { display: none }
/* Only the views scroll. The Active layers footer is a sibling of this
 * region, not a `margin-top:auto` child of it — otherwise a long Data
 * panel pushes it out of sight, which is exactly what it must never do. */
.ex-panel-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden }
.ex-panel-body::-webkit-scrollbar { width: 8px }
.ex-panel-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12) }
.ex-panel-body::-webkit-scrollbar-track { background: transparent }

.ex-panel-hd {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 14px 16px 12px; border-bottom: 1px solid var(--ex-line);
}
.ex-panel-title {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: rgba(238,241,246,.5);
}
.ex-panel-meta { font-family: var(--font-mono); font-size: 10px; color: rgba(238,241,246,.32) }
/* Hidden on desktop and fold, where the hamburger is right there and the
   panel is a column rather than a sheet. Turned on by the phone block. */
.ex-panel-close {
  display: none; place-items: center; width: 32px; height: 32px;
  border: none; background: transparent; padding: 0;
  color: var(--ex-ink-dim); font-size: 14px; cursor: pointer;
  transition: color .15s;
}
.ex-panel-close:hover { color: var(--ex-ink) }

.ex-view { display: none; flex-direction: column }
.ex-view.on { display: flex }

.ex-block { padding: 14px 16px; border-bottom: 1px solid var(--ex-line) }
.ex-block-hd { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px }
.ex-block-src { font-family: var(--font-mono); font-size: 9.5px; color: var(--ex-ink-ghost) }

/* Place search */
.ex-search-row { display: flex; align-items: center; gap: 8px; padding-bottom: 10px }
.ex-well {
  flex: 1; display: flex; align-items: center; gap: 8px; min-width: 0;
  height: 34px; padding: 0 11px;
  border: 1px solid rgba(255,255,255,.12); background: var(--ex-well);
}
.ex-well input {
  flex: 1; min-width: 0; background: transparent; border: none; outline: none;
  font-family: var(--font-body); font-size: 13px; color: var(--ex-ink);
}
.ex-well input::placeholder { color: rgba(238,241,246,.32) }
.ex-go {
  height: 34px; padding: 0 14px; border: 1px solid var(--ex-accent-br);
  background: var(--ex-accent-fill); color: var(--ex-accent);
  font-family: var(--font-body); font-size: 12.5px; font-weight: 500;
  cursor: pointer; transition: background-color .15s;
}
.ex-go:hover { background: rgba(52,210,126,.2) }

.ex-chips { display: flex; flex-wrap: wrap; gap: 6px }
.ex-chip {
  padding: 5px 9px; border: 1px solid var(--ex-line-2); background: transparent;
  color: rgba(238,241,246,.62); font-family: var(--font-mono); font-size: 10px;
  letter-spacing: .04em; cursor: pointer; transition: color .15s, border-color .15s;
}
.ex-chip:hover { color: var(--ex-ink); border-color: var(--ex-line-hover) }

/* Basemap swatches */
.ex-basemap { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px }
.ex-bm {
  display: flex; flex-direction: column; gap: 6px; padding: 0;
  border: none; background: transparent; cursor: pointer; text-align: center;
}
.ex-bm-sw { display: block; height: 34px; border: 1px solid rgba(255,255,255,.12) }
.ex-bm-cap {
  font-family: var(--font-mono); font-size: 8.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ex-ink-dim);
}
.ex-bm.on .ex-bm-sw { border-color: var(--ex-accent) }
.ex-bm.on .ex-bm-cap { color: var(--ex-accent) }

/* Toggle rows — reuses the existing .tw switch, restyled square. */
.ex-toggles { padding: 6px 0 10px }
.ex-toggles .ex-label { padding: 10px 16px 6px }
.ex-trow {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 9px 16px; transition: background-color .15s;
}
.ex-trow:hover { background: rgba(255,255,255,.03) }
.ex-trow > .tl { font-size: 13px; color: var(--ex-ink-soft); cursor: default }
/* The switch is main.css's `.tw` — same element, same onclick, restyled
 * square. main.css fills `.tw.on` solid green and slides the knob with a
 * translateX, so both have to be neutralised explicitly or the knob
 * lands outside the (wider) new track. */
.ex-shell .tw {
  position: relative; flex: 0 0 auto; width: 34px; height: 18px;
  border: 1px solid var(--ex-line-3); background: rgba(255,255,255,.05);
  border-radius: 0; box-shadow: none; cursor: pointer;
  transition: border-color .15s, background-color .15s;
}
.ex-shell .tw::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 12px; height: 12px; border-radius: 0; transform: none;
  background: var(--ex-ink-dim); transition: left .15s, background-color .15s;
}
.ex-shell .tw.on {
  border-color: rgba(52,210,126,.6); background: rgba(52,210,126,.22); box-shadow: none;
}
.ex-shell .tw.on::after { left: 18px; transform: none; background: var(--ex-accent) }

/* Data / feed rows */
.ex-rows { display: flex; flex-direction: column; gap: 4px }
.ex-datarow {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: 1px solid var(--ex-line-2); background: transparent;
  color: var(--ex-ink-mid); font-family: var(--font-body); font-size: 12.5px;
  text-align: left; cursor: pointer; transition: color .15s, border-color .15s, background-color .15s;
}
.ex-datarow:hover { border-color: var(--ex-line-hover) }
.ex-datarow.on {
  border-color: rgba(52,210,126,.5); background: var(--ex-accent-row); color: var(--ex-ink);
}
.ex-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50% }
.ex-datarow-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.ex-tag { font-family: var(--font-mono); font-size: 9.5px; color: var(--ex-ink-faint) }

/* Segmented control (feed time window, ask-bar mode) */
.ex-seg { display: flex; border: 1px solid rgba(255,255,255,.14) }
.ex-seg button {
  flex: 1; height: 26px; padding: 0 10px; border: none; background: transparent;
  color: var(--ex-ink-dim); font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: .06em; cursor: pointer; transition: color .15s, background-color .15s;
}
.ex-seg button.on, .ex-seg button.active {
  background: var(--ex-accent-fill); color: var(--ex-accent);
}

/* Tools / marks rows */
.ex-listrow {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 11px 16px; border: none; background: transparent;
  color: var(--ex-ink-soft); font-family: var(--font-body); font-size: 13px;
  text-align: left; cursor: pointer; transition: color .15s, background-color .15s;
}
.ex-listrow:hover { color: var(--ex-ink); background: rgba(255,255,255,.03) }
.ex-kbd { font-family: var(--font-mono); font-size: 10px; color: var(--ex-ink-faint); flex: 0 0 auto }
.ex-wide {
  width: 100%; padding: 10px; border: 1px solid var(--ex-line-3); background: transparent;
  color: var(--ex-ink-soft); font-family: var(--font-body); font-size: 12.5px;
  cursor: pointer; transition: color .15s, border-color .15s;
}
.ex-wide:hover { color: var(--ex-accent); border-color: var(--ex-accent) }
.ex-note {
  font-family: var(--font-mono); font-size: 10.5px; line-height: 1.6;
  color: var(--ex-ink-ghost); padding: 12px 16px;
}

/* Active layers footer — pinned to the panel bottom, visible from
 * every view so the user never loses track of what's rendered. */
.ex-active {
  flex: 0 0 auto; max-height: 38vh; overflow-y: auto;
  border-top: 1px solid var(--ex-line); padding: 12px 16px; background: var(--ex-panel);
}
.ex-active::-webkit-scrollbar { width: 8px }
.ex-active::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12) }
.ex-active-hd { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px }
.ex-clear {
  border: none; background: transparent; padding: 0;
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ex-accent); cursor: pointer; transition: color .15s;
}
.ex-clear:hover { color: var(--ex-accent-hov) }

/* Layer cards come from layers.js (.lw/.lh/.ldot/.ln/.lm/.lt2/.ldel).
 * Squared down to the footer's row spec rather than re-rendered, so the
 * drag-reorder, expand and visibility handlers keep working untouched. */
.ex-active .lw {
  margin: 0 0 4px; border: 1px solid var(--ex-line);
  background: rgba(255,255,255,.02); border-radius: 0; box-shadow: none;
}
.ex-active .lw:last-child { margin-bottom: 0 }
.ex-active .lh { padding: 8px 9px; gap: 8px; border-radius: 0 }
.ex-active .ldot { width: 7px; height: 7px; flex: 0 0 auto }
.ex-active .ln { font-size: 12px; font-weight: 400; color: var(--ex-ink) }
.ex-active .lm { font-family: var(--font-mono); font-size: 9.5px; color: rgba(238,241,246,.42) }
.ex-active .ldel { color: var(--ex-ink-faint); border-radius: 0 }
.ex-active .ldel:hover { color: #ef4444; background: transparent }
.ex-active .lord { display: none }        /* reorder by drag, not arrows */
/* Per-layer visibility switch — same squaring as .tw above. */
.ex-active .lt2 {
  width: 28px; height: 15px; border-radius: 0; box-shadow: none;
  border: 1px solid var(--ex-line-3); background: rgba(255,255,255,.05);
}
.ex-active .lt2::after {
  top: 1px; left: 1px; width: 11px; height: 11px;
  border-radius: 0; transform: none; background: var(--ex-ink-dim);
}
.ex-active .lt2.on {
  border-color: rgba(52,210,126,.6); background: rgba(52,210,126,.22); box-shadow: none;
}
.ex-active .lt2.on::after { left: 14px; transform: none; background: var(--ex-accent) }
.ex-active .ll-master .ln {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(238,241,246,.5); font-weight: 400;
}
.ex-active .nol {
  font-family: var(--font-mono); font-size: 10.5px; color: var(--ex-ink-ghost);
  font-style: normal; padding: 0;
}
.ex-active .ll-master .lm { color: rgba(238,241,246,.34) }

/* ── Right readout column ───────────────────────────────────────── */

.ex-readout {
  position: absolute; top: 14px; right: 14px; width: 210px;
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none; z-index: 8;
}
body.chat-open .ex-readout,
body.insights-open .ex-readout { display: none }

.ex-card {
  border: 1px solid var(--ex-line-2); background: var(--ex-glass);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  padding: 10px 12px;
}
.ex-card-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px }
.ex-card-l {
  font-family: var(--font-mono); font-size: 9px; letter-spacing: .16em;
  text-transform: uppercase; color: rgba(238,241,246,.42);
}
.ex-card-v {
  font-family: var(--font-display); font-size: 24px; font-weight: 600;
  letter-spacing: -.03em; line-height: 1.15;
}
.ex-card-s { font-family: var(--font-mono); font-size: 9px; color: var(--ex-ink-faint) }
.ex-card-hd { display: flex; align-items: baseline; justify-content: space-between; gap: 8px }
.ex-card-v.ex-peak {
  font-size: 18px; letter-spacing: -.02em; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ex-red);
}
.ex-legend-rows { display: flex; flex-direction: column; gap: 6px; margin-top: 8px }
.ex-legend-row {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 10px; color: rgba(238,241,246,.7);
}
.ex-legend-sw { width: 8px; height: 8px; flex: 0 0 auto }
.ex-legend-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis }
.ex-legend-src { color: rgba(238,241,246,.38) }
.ex-coords {
  font-family: var(--font-mono); font-size: 10px; line-height: 1.7;
  color: rgba(238,241,246,.58);
}
.ex-coords div { display: flex; justify-content: space-between }
.ex-coords span:first-child { color: var(--ex-ink-faint) }

/* ── Scale + attribution ────────────────────────────────────────── */

.ex-scale {
  position: absolute; left: 14px; bottom: 14px;
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .06em;
  color: rgba(238,241,246,.4); pointer-events: none; z-index: 8;
}
.ex-scale-pill {
  display: inline-flex; align-items: center; gap: 7px; padding: 5px 9px;
  border: 1px solid var(--ex-line-2); background: rgba(11,12,14,.8);
}
.ex-scale-bar { display: inline-block; width: 34px; height: 5px; border: 1px solid currentColor; border-top: none }

/* ── Ask bar ────────────────────────────────────────────────────── */

.ex-ask {
  position: absolute; left: 0; right: 0; bottom: 18px;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 0 24px; z-index: 9; pointer-events: none;
}
.ex-ask > * { pointer-events: auto }

.ex-sug { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; max-width: 840px }
.ex-sug.hidden { display: none }
.ex-sug button {
  padding: 7px 12px; border: 1px solid rgba(255,255,255,.12);
  background: rgba(11,12,14,.85); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  color: var(--ex-ink-mid); font-family: var(--font-body); font-size: 12px;
  white-space: nowrap; cursor: pointer; transition: color .15s, border-color .15s;
}
.ex-sug button:hover { color: var(--ex-ink); border-color: var(--ex-accent) }

.ex-bar {
  width: 100%; max-width: 840px;
  border: 1px solid rgba(255,255,255,.14); background: rgba(11,12,14,.9);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 24px 60px -30px rgba(0,0,0,.9);
}
/* flex-wrap + a flex-basis floor on the input: with the inspect and
 * insights columns both open the input drops to its own line instead
 * of collapsing to nothing. Keep both properties together. */
.ex-bar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 11px 12px }
.ex-badge {
  flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center;
  border: 1px solid var(--ex-accent-br); background: var(--ex-accent-fill); color: var(--ex-accent);
}
.ex-engine {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px;
  height: 28px; padding: 0 10px; border: 1px solid rgba(255,255,255,.14);
  background: transparent; color: rgba(238,241,246,.8);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .04em;
  cursor: pointer; transition: color .15s, border-color .15s;
}
.ex-engine:hover { color: var(--ex-ink); border-color: rgba(255,255,255,.3) }
.ex-engine-glyph { color: var(--ex-violet) }
.ex-engine-caret { color: rgba(238,241,246,.4) }

.ex-mode { flex: 0 0 auto }
.ex-mode button {
  height: 26px; padding: 0 10px; font-size: 10px; letter-spacing: .1em;
  text-transform: uppercase;
}

#pi.ex-input {
  flex: 1 1 180px; min-width: 180px; order: 9; height: 28px;
  background: transparent; border: none; outline: none; box-shadow: none;
  font-family: var(--font-body); font-size: 14px; color: var(--ex-ink); padding: 0;
}
#pi.ex-input::placeholder { color: rgba(238,241,246,.32) }

/* order 9/10 keeps the input between the mode control and the trailing
 * buttons while still letting it wrap to its own line first when the
 * inspect and insights columns squeeze the bar. */
.ex-sugtog {
  flex: 0 0 auto; order: 10; height: 28px; padding: 0 10px;
  border: 1px solid rgba(255,255,255,.14); background: transparent;
  color: rgba(238,241,246,.6); font-family: var(--font-mono); font-size: 10px;
  letter-spacing: .1em; text-transform: uppercase; cursor: pointer;
  transition: color .15s, border-color .15s;
}
.ex-sugtog:hover { color: var(--ex-ink); border-color: rgba(255,255,255,.3) }

#go.ex-send {
  flex: 0 0 auto; order: 10; width: 32px; height: 28px; display: grid; place-items: center;
  border: 1px solid var(--ex-accent); background: var(--ex-accent);
  color: var(--ex-accent-ink); font-size: 14px; cursor: pointer; padding: 0;
  border-radius: 0; transition: background-color .15s, border-color .15s;
}
#go.ex-send:hover { background: var(--ex-accent-hov); border-color: var(--ex-accent-hov) }
#go.ex-send:disabled { opacity: .5; cursor: default }

/* Foot: helper line / trace / receipt — one at a time. */
.ex-foot { border-top: 1px solid var(--ex-line) }
.ex-foot.hidden { display: none }
.ex-help-line {
  padding: 8px 14px; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; font-family: var(--font-mono); font-size: 10px; letter-spacing: .06em;
  color: rgba(238,241,246,.36);
}
.ex-trace { position: relative; overflow: hidden }
.ex-trace::before {
  content: ''; position: absolute; top: 0; left: 0; width: 30%; height: 1px;
  background: linear-gradient(90deg, transparent, var(--ex-accent), transparent);
  animation: exSweep 1.4s linear infinite;
}
/* Rows are additive and never replace each other, so the region scrolls
 * rather than dropping the earliest step. ~6 rows before it scrolls: the
 * card's height changes, its bottom anchor does not. */
.ex-trace-rows {
  padding: 10px 14px; display: flex; flex-direction: column; gap: 5px;
  max-height: 132px; overflow-y: auto;
}
.ex-trace-rows::-webkit-scrollbar { width: 6px }
.ex-trace-rows::-webkit-scrollbar-thumb { background: rgba(255,255,255,.12) }
.ex-trace-row {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--font-mono); font-size: 10.5px; color: rgba(238,241,246,.5);
}
.ex-trace-row:last-child { color: rgba(238,241,246,.9) }
.ex-trace-dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(52,210,126,.4); flex: 0 0 auto }
.ex-trace-row:last-child .ex-trace-dot { background: var(--ex-accent) }
.ex-trace-text { flex: 1; min-width: 0 }
.ex-trace-ms { color: var(--ex-ink-ghost) }

/* Amber = the app didn't get what it asked for and worked around it.
 * These keep their colour after they stop being the live row — dimming a
 * warning into the background is what the toast effectively did. */
.ex-trace-row.is-warn, .ex-trace-row.is-warn:last-child { color: rgba(251,191,36,.92) }
.ex-trace-row.is-warn .ex-trace-dot,
.ex-trace-row.is-warn:last-child .ex-trace-dot { background: #f59e0b }
/* Red is reserved for a query that failed outright. */
.ex-trace-row.is-error, .ex-trace-row.is-error:last-child { color: rgba(248,113,113,.95) }
.ex-trace-row.is-error .ex-trace-dot,
.ex-trace-row.is-error:last-child .ex-trace-dot { background: #ef4444 }

.ex-receipt { padding: 11px 14px; display: flex; align-items: flex-start; gap: 10px }
.ex-receipt-dot {
  flex: 0 0 auto; margin-top: 3px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--ex-accent);
}
.ex-receipt-body { flex: 1; min-width: 0 }
.ex-receipt-line { display: block; font-size: 13px; color: rgba(238,241,246,.9) }
.ex-receipt-meta {
  display: block; font-family: var(--font-mono); font-size: 10px;
  letter-spacing: .05em; color: rgba(238,241,246,.38); margin-top: 4px;
}
.ex-receipt-btn {
  flex: 0 0 auto; padding: 5px 9px; border: 1px solid var(--ex-accent-br);
  background: rgba(52,210,126,.1); color: var(--ex-accent);
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .12em;
  text-transform: uppercase; cursor: pointer; transition: background-color .15s;
}
.ex-receipt-btn:hover { background: rgba(52,210,126,.2) }
.ex-receipt-x {
  flex: 0 0 auto; border: none; background: transparent; padding: 0 2px;
  color: rgba(238,241,246,.4); font-size: 12px; cursor: pointer; transition: color .15s;
}
.ex-receipt-x:hover { color: var(--ex-ink) }

/* ── Overrides for retained main.css components ─────────────────── */

/* The old fixed sidebar, stat block and dock shells are replaced. Their
 * inner controls live on inside the new panel / readout / ask bar, so
 * only the outer chrome is neutralised. */
.sts, .hdr { display: none !important }
/* Mobile scrim behind the panel — ui.js adds .show below 768px. */
.sb-overlay {
  position: absolute; inset: 0; z-index: 14; background: rgba(4,5,7,.6);
  display: none;
}
.sb-overlay.show { display: block }
.dk {
  position: static; left: auto; right: auto; bottom: auto;
  transform: none; width: auto; max-width: none; padding: 0;
  background: transparent; border: none; box-shadow: none; display: contents;
}

/* Panels that used to offset themselves against the old fixed sidebar
 * now sit inside a flex row that already reserves the space. */
/* The inspect card becomes a column between the panel and the globe —
 * a layout sibling, so it never covers the point it is describing.
 * main.css positions it fixed with top/right/bottom, all of which have
 * to be cleared or `position:relative` just offsets it. */
.ex-row > .ins {
  position: relative; inset: auto; flex: 0 0 auto;
  width: 288px; max-width: 24vw; z-index: 7;
  border: none; border-right: 1px solid var(--ex-line-2); border-radius: 0;
  box-shadow: none; background: var(--ex-panel); padding: 14px 16px;
  animation: none;
}
body.insights-open .ex-row > .ins { right: auto }

/* Inspect internals. app.js fills these nodes in a fixed order —
 * value, name, detail, rows, fly, nearby — so the title is promoted with
 * flex `order` rather than by rewriting the renderer. Accent is reserved
 * for state and data here too: the old teal heading and saturated green
 * pill both go. */
.ex-row > .ins .sh {
  display: flex; align-items: center; gap: 7px;
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ex-accent);
  padding: 0 0 11px; margin: 0 0 11px; border-bottom: 1px solid var(--ex-line);
  order: 0;
}
.ex-row > .ins .sh::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: var(--ex-accent); animation: exPulse 2.4s ease-in-out infinite;
}
.ex-row > .ins .ins-n {          /* name → the title */
  order: 1; font-family: var(--font-display); font-weight: 600; font-size: 19px;
  line-height: 1.18; letter-spacing: -.025em; color: var(--ex-ink); margin: 0 0 10px;
}
.ex-row > .ins .ins-v {          /* headline value → a spec row */
  order: 2; font-family: var(--font-mono); font-size: 11.5px; font-weight: 400;
  color: var(--ex-accent); margin: 0; padding: 7px 0;
  border-top: 1px solid var(--ex-line); border-bottom: 1px solid var(--ex-line);
}
.ex-row > .ins .ins-d {
  order: 3; font-size: 12px; color: rgba(238,241,246,.58);
  padding: 8px 0 0; margin: 0 0 12px;
}
.ex-row > .ins #iR { order: 4 }
.ex-row > .ins .ins-fly {
  order: 5; display: flex; align-items: center; justify-content: space-between;
  height: 36px; padding: 0 12px; margin: 4px 0 0;
  border: 1px solid rgba(52,210,126,.5); border-radius: 0;
  background: var(--ex-accent-fill); color: var(--ex-accent);
  font-family: var(--font-body); font-size: 12.5px; font-weight: 500;
  box-shadow: none; transition: background-color .15s, border-color .15s;
}
.ex-row > .ins .ins-fly:hover { background: rgba(52,210,126,.2); border-color: var(--ex-accent) }
.ex-row > .ins > div:last-child { order: 6 }   /* Nearby block */
.ex-row > .ins .ins-c { top: 12px; right: 14px; padding: 2px 6px; border-radius: 0 }
.ex-row > .ins .ins-handle { display: none }
.route-info { left: 12px }

/* Timeline sits above the ask bar when a temporal layer is loaded. */
.tll { margin-bottom: 10px }

/* ── Responsive ─────────────────────────────────────────────────── */
/*
 * Five viewport classes from the handoff. The prototype measures the
 * viewport in JS because inline styles can't carry media queries; here
 * they are the media queries they were always meant to be, so nothing
 * has to re-measure on resize.
 *
 *   desktop  ≥1180px                          rail · panel · inspect · globe · insights, all in flow
 *   compact  820–1179px, aspect <0.86 / >1.5  narrower panel + side columns
 *   fold     2 viewport segments (≥620px),    two leaves: controls left, globe right
 *            or 820–1179px, aspect 0.86–1.5
 *   phone    <820px                           single column: globe → sheet → bottom tab bar
 *   cover    <420px and <560px tall           phone, minus suggestions and engine/mode
 *
 * The handoff states aspect as height/width; CSS `aspect-ratio` is
 * width/height, so every threshold here is its reciprocal:
 *   h/w > 0.86  ⟺  w/h < 50/43      h/w < 1.5  ⟺  w/h > 2/3
 *
 * Order is load-bearing. Later blocks win at equal specificity, and the
 * class precedence is not the same as the width order: a FOLDED device
 * is `fold` at any width ≥620px, including widths that would otherwise
 * be `phone`. So the segment queries come last.
 */

/* ── compact ─────────────────────────────────────────────────────── */

@media (min-width: 820px) and (max-width: 1179px) and (max-aspect-ratio: 2/3),
       (min-width: 820px) and (max-width: 1179px) and (min-aspect-ratio: 50/43) {
  .ex-panel { width: 284px }
  .ex-row > .ins { width: min(272px, 26vw); max-width: none }
  .ex-readout { width: 186px }
}

/* ── phone ───────────────────────────────────────────────────────── */

@media (max-width: 819px) {
  /* Stage first, sheet under it, tab bar last — stacked in flow, so
     nothing overlaps and the map is never covered by its own controls. */
  .ex-row { flex-direction: column }
  .ex-stage { order: 1; flex: 1 1 auto; min-height: 170px }

  .ex-panel {
    order: 2; position: static; flex: 0 1 auto;
    width: 100%; max-height: min(46vh, 360px);
    border-right: none; border-top: 1px solid rgba(255,255,255,.12);
  }

  /* Rail → bottom tab bar. The 2px active marker moves from the left
     edge to the top edge, which is the edge that now reads as "current". */
  .ex-rail {
    order: 3; position: static; flex: 0 0 auto;
    width: 100%; flex-direction: row; align-items: stretch;
    gap: 0; padding: 0; height: auto;
    border-right: none; border-top: 1px solid var(--ex-line-2);
  }
  .ex-rail-btn { flex: 1 1 0; height: 58px; font-size: 9px; letter-spacing: .06em }
  .ex-rail-btn::before { left: 14%; right: 14%; top: 0; bottom: auto; width: auto; height: 2px }
  .ex-rail-spacer, .ex-rail-help { display: none }

  /* The panel is in flow now, so the scrim would dim the map for nothing. */
  .sb-overlay { display: none !important }

  /* Sheets clear the tab bar rather than sitting under it. */
  .ex-row > .ins {
    position: absolute; left: 8px; right: 8px; bottom: 67px; top: auto;
    width: auto; max-width: none; max-height: 66%; z-index: 9;
    border: 1px solid rgba(255,255,255,.14); border-right: none;
    background: rgba(11,12,14,.96);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    overflow-y: auto;
  }
  .data-insights.open { top: 0; left: 0; right: 0; bottom: 59px; width: auto; border-radius: 0 }

  /* Readouts become one horizontal strip at the top of the map. Legend,
     coordinates, scale and attribution are desktop/fold only — on a phone
     they cost more of the map than they return. */
  .ex-readout {
    top: 8px; left: 8px; right: 8px; width: auto;
    flex-direction: row; gap: 6px; overflow: hidden;
  }
  .ex-card-pair { display: flex; gap: 6px; flex: 1 1 auto; min-width: 0 }
  .ex-card-pair > .ex-card { flex: 1 1 0; min-width: 0 }
  .ex-card-v { font-size: 20px }
  .ex-readout > .ex-card { flex: 1 1 0; min-width: 0 }
  .ex-readout > .ex-coords, .ex-readout > #exLegend { display: none }
  .ex-scale { display: none }

  .ex-ask { left: 0; right: 0; bottom: 8px; padding: 0 8px; align-items: stretch; gap: 8px }
  .ex-bar { max-width: none }
  /* The helper line wraps to three lines at this width and eats a third
     of the visible map. The mode note is redundant anyway — FAST/DEEP is
     right above it — so keep the sentence and drop the echo. */
  .ex-help-line { padding: 8px 12px; font-size: 9.5px }
  #exModeNote { display: none }
  .ex-sug {
    max-width: none; flex-wrap: nowrap; justify-content: flex-start;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .ex-sug::-webkit-scrollbar { display: none }

  /* Header keeps ONLY hamburger + brand + BETA + avatar. Version, quota,
     Measure / Route / Snapshot / Chat / Feedback all have a home in the
     Tools panel, and none of them survives the width. The brand cluster
     truncates instead of colliding. */
  .ex-hdr { gap: 8px; padding: 0 10px }
  .ex-brand-v, #quota-badge,
  #mBtn, #routeBtn, #fbBtn, #chatBtn,
  .ex-hdr-r > .ex-btn, .ex-hdr-r > .ex-icon-btn:not(#auth-btn),
  .ex-hdr-r > .ex-div { display: none }

  /* main.css has its own ≤480px block from the pre-shell layout. Two of
     its rules still land on live controls and fight this one: it hides
     the engine label outright and squeezes the prompt row to 2px padding.
     The new design keeps the engine chip labelled on phone — only `cover`
     drops it — so re-assert both here, where the later stylesheet wins. */
  .ai-pick-label { display: inline }
  .ex-bar-row.pm-r { gap: 10px; padding: 11px 12px }
  .ex-brand { min-width: 0; overflow: hidden }
  .ex-brand-name { overflow: hidden; text-overflow: ellipsis }
  .ex-status { display: none }

  .ex-panel-close { display: grid }
}

/* ── cover (folded-shut outer screen) ────────────────────────────── */

@media (max-width: 419px) and (max-height: 559px) {
  .ex-stage { min-height: 200px }
  .ex-panel { max-height: min(58vh, 420px) }
  /* One map, one input, one readout strip. The suggestion rail and the
     engine / mode controls do not fit and are not worth the room. */
  .ex-sug, .ex-sugtog, .ex-engine, .ex-mode { display: none }
  .ex-rail-btn { font-size: 8px }
}

/* ── fold (book-style, two viewport segments) ────────────────────── */
/*
 * Last, so a folded device wins over the width-based classes above. The
 * hinge is a layout boundary, never a place to put a control: panels take
 * the left leaf, the globe the right, and both sheets open INSIDE the
 * globe leaf. The row gap is the real segment gutter when the browser
 * exposes it.
 */

@media (min-width: 820px) and (max-width: 1179px) and (min-aspect-ratio: 2/3) and (max-aspect-ratio: 50/43),
       (min-width: 620px) and (horizontal-viewport-segments: 2),
       (min-width: 620px) and (vertical-viewport-segments: 2),
       (min-width: 620px) and (spanning: single-fold-vertical),
       (min-width: 620px) and (spanning: single-fold-horizontal) {
  .ex-row {
    flex-direction: row;
    column-gap: env(viewport-segment-left 1 0, 0px);
  }
  .ex-panel {
    order: 0; position: static; flex: 1 1 300px; max-width: 44%;
    width: auto; max-height: none;
    border-right: 1px solid var(--ex-line); border-top: none;
  }
  .ex-stage { order: 0; flex: 1 1 52%; min-height: 0 }

  .ex-rail {
    order: -1; position: static; width: 58px; height: auto;
    flex-direction: column; gap: 2px; padding: 8px 0;
    border-right: 1px solid var(--ex-line); border-top: none;
  }
  .ex-rail-btn { flex: 0 0 auto; height: 52px; font-size: 8.5px; letter-spacing: .08em }
  .ex-rail-btn::before { left: 0; right: auto; top: 8px; bottom: 8px; width: 2px; height: auto }
  .ex-rail-spacer { display: block }
  .ex-rail-help { display: flex }

  /* Sheets open within the globe leaf — never across the hinge. */
  .ex-row > .ins {
    position: absolute; left: 8px; top: 8px; bottom: 8px; right: auto;
    width: min(300px, 42%); max-width: none; max-height: none; z-index: 9;
    border: 1px solid rgba(255,255,255,.12); border-right: none;
    background: var(--ex-glass);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  }
  .data-insights.open { top: 0; right: 0; bottom: 0; left: auto; width: min(420px, 58%) }

  .ex-readout {
    top: 10px; right: 10px; left: auto; width: 186px;
    flex-direction: column; gap: 6px;
    max-height: calc(100% - 150px);
  }
  .ex-readout > .ex-coords, .ex-readout > #exLegend { display: flex }
  .ex-readout > .ex-coords { display: block }
  .ex-card-pair { display: grid; grid-template-columns: 1fr 1fr }
  .ex-scale { display: flex }
  .ex-status { display: flex }

  .ex-ask { align-items: center; padding: 0 16px; bottom: 18px }
  .ex-bar { max-width: 620px }
  .ex-sug { max-width: 620px; flex-wrap: wrap; justify-content: center; overflow: visible }
  .ex-panel-close { display: none }
}

/* ── Touch targets ──────────────────────────────────────────────── */
/*
 * Applied to phone, cover AND fold. The prototype's layout() only sets
 * these under its `mobile` flag (phone + cover), but the handoff prose
 * says phone/cover/fold — and prose is right here: a folded-open phone
 * is still a phone in a hand, and 26px controls on it are a miss.
 *
 * Desktop and compact keep the tighter 26–36px sizes. These are per
 * class, not global.
 */
@media (max-width: 819px),
       (min-width: 820px) and (max-width: 1179px) and (min-aspect-ratio: 2/3) and (max-aspect-ratio: 50/43),
       (min-width: 620px) and (horizontal-viewport-segments: 2),
       (min-width: 620px) and (vertical-viewport-segments: 2),
       (min-width: 620px) and (spanning: single-fold-vertical),
       (min-width: 620px) and (spanning: single-fold-horizontal) {
/* ── Touch targets ─────────────────────────────────────────────── */
/* Everything a finger lands on clears 44px. Desktop keeps its tighter
   26–36px sizes — these are per class, not global. */
.ex-icon-btn { width: 44px; height: 44px }
.ex-btn { height: 44px; padding: 0 14px }
#pi.ex-input {
  flex: 1 1 140px; min-width: 120px; height: 44px;
  /* 16px is not a style choice: iOS Safari zooms the page on focus for
     anything smaller, and the map never comes back cleanly. */
  font-size: 16px;
}
#go.ex-send { width: 52px; height: 44px; font-size: 17px }
.ex-engine { height: 44px; padding: 0 13px; font-size: 12px }
.ex-mode button, .ex-seg button { height: 44px; padding: 0 15px; font-size: 11px }
.ex-sugtog { height: 44px; padding: 0 14px }
.ex-sug button { min-height: 44px; padding: 12px 14px; font-size: 13px }
.ex-badge { width: 44px; height: 44px }
.ex-chip { min-height: 44px; padding: 0 14px; display: inline-flex; align-items: center }
.ex-datarow { min-height: 48px; padding: 10px 12px }
.ex-listrow { min-height: 48px }
.ex-trow { min-height: 44px; padding: 11px 16px }
.ex-well { height: 46px }
/* The input has to fill its shell, or the real tap target is the 18px
   text box and the surrounding 46px is dead space that looks tappable. */
.ex-well input { height: 100%; font-size: 16px }
#pi.ex-input, .ex-well input, input[type="text"], input[type="search"] { font-size: 16px }
.ex-panel-close { width: 44px; height: 44px }
.ex-go { height: 46px; padding: 0 18px }
.ex-wide { min-height: 48px }
.ex-clear { min-height: 44px; display: inline-flex; align-items: center }
.ex-receipt-btn, .ex-receipt-x { min-height: 44px; min-width: 44px }
.ex-bm-sw { height: 44px }
.ex-active .lh { padding: 12px 10px; min-height: 52px }
.ex-active .ldel { min-width: 44px; min-height: 44px }
.ex-row > .ins .ins-fly { height: 48px; font-size: 15px }
.ex-row > .ins .ins-c { min-width: 44px; min-height: 44px }

/* The switch grows to a 52×30 track — still unmistakably a switch, not a
   slab — and the rest of the 44px target comes from a transparent
   ::before that extends past it. Padding on the control itself was the
   obvious move and the wrong one: the knob is positioned against the
   padding box, so it landed outside the track. */
.ex-shell .tw {
  position: relative; box-sizing: border-box;
  width: 52px; height: 30px; padding: 0;
}
.ex-shell .tw::before {
  content: ''; position: absolute; left: -4px; right: -4px;
  top: -7px; bottom: -7px;
}
.ex-shell .tw::after { top: 3px; left: 3px; width: 22px; height: 22px }
.ex-shell .tw.on::after { left: 27px }
}
