:root {
  --bg: #05070d;
  --panel: rgba(14, 20, 34, 0.82);
  --panel-solid: #0e1422;
  --border: rgba(120, 150, 200, 0.18);
  --text: #e6edf7;
  --subtle: #8aa0c0;
  --accent: #38bdf8;
  --accent-dim: rgba(56, 189, 248, 0.15);
  --danger: #ef4444;
  --radius: 12px;
  --shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Display cutout insets. Zero in a browser tab and on anything rectangular;
     non-zero once the app is installed and drawing under the status bar and
     the home indicator, which is what index.html's `viewport-fit=cover` asks
     for. Aliased here so the fallback is written once — `env()` with no
     fallback resolves to nothing (not 0) in a `calc()` on older engines,
     which poisons the whole expression. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

#scene {
  position: fixed;
  inset: 0;
  width: 100vw;
  /* 100vh is the *large* viewport on mobile — the height with the browser
     chrome retracted — so the canvas overflows by the toolbar's height while
     it is showing, and the bottom of the globe sits under it. dvh tracks the
     chrome as it comes and goes. The vh line stays as the fallback for engines
     without dvh; the renderer sizes its own buffer from innerHeight either way
     (scene.js), so the two agree. */
  height: 100vh;
  height: 100dvh;
  display: block;
  cursor: grab;
  touch-action: none;
}
#scene:active { cursor: grabbing; }

/* ---------- Loading overlay ---------- */
.overlay {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: radial-gradient(circle at 50% 40%, #0a1020, #05070d 70%);
  z-index: 50;
  transition: opacity 0.6s ease;
}
.overlay.gone { opacity: 0; pointer-events: none; }
.loader-card { text-align: center; }
.loader-card h1 {
  margin: 18px 0 6px;
  font-size: 2.4rem;
  letter-spacing: 0.35em;
  font-weight: 700;
}
.loader-card p { color: var(--subtle); margin: 0; font-size: 0.9rem; }
.spinner {
  width: 46px; height: 46px;
  margin: 0 auto;
  border: 3px solid rgba(56, 189, 248, 0.2);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Panels ---------- */
.panel {
  position: fixed;
  background: var(--panel);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  z-index: 20;
  width: 268px;
  max-height: calc(100vh - 132px);
  max-height: calc(100dvh - 132px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Landscape on a notched phone is wider than the 720px mobile breakpoint, so it
   gets this desktop layout *and* a non-zero side inset — the one combination
   where the horizontal insets matter. */
#panel-left { top: calc(64px + var(--safe-top)); left: calc(16px + var(--safe-left)); }
#panel-right { top: calc(64px + var(--safe-top)); right: calc(16px + var(--safe-right)); }

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.panel-header h2 {
  margin: 0;
  font-size: 0.82rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--subtle);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#sel-name { color: var(--text); letter-spacing: 0.04em; text-transform: none; font-size: 0.95rem; }
.collapse-btn {
  background: transparent;
  border: none;
  color: var(--subtle);
  font-size: 1.1rem;
  cursor: pointer;
  line-height: 1;
  padding: 2px 6px;
  border-radius: 6px;
}
.collapse-btn:hover { background: rgba(255,255,255,0.06); color: var(--text); }
.collapse-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Collapse and close sit together on the selection panel; the header itself is
   space-between, so they need their own group to stay adjacent. */
.panel-header-actions { display: flex; align-items: center; gap: 2px; flex: none; }

.panel-body { padding: 12px 14px; overflow-y: auto; }
.panel.collapsed .panel-body,
.panel.collapsed .panel-section { display: none; }
/* The reentry watch list is force-shown in reentry mode by a more specific,
   id-bearing rule (body.mode-reentry #reentry-section), so the generic collapse
   rule above can't hide it. Override with matching specificity. The sky panel
   is force-shown the same way and needs the same override. */
.panel.collapsed #reentry-section,
.panel.collapsed #sky-section { display: none; }

.panel-section {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
}

/* ---------- Layer toggles ---------- */
.layer {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: 8px;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s;
}
.layer:hover { background: rgba(255,255,255,0.04); }
.layer input { display: none; }
.layer .swatch {
  width: 11px; height: 11px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 0 8px currentColor;
}
.layer .lname { flex: 1; font-size: 0.86rem; }
.layer .lcount { font-size: 0.72rem; color: var(--subtle); font-variant-numeric: tabular-nums; }
.layer.off { opacity: 0.4; }
.layer.off .swatch { box-shadow: none; }

/* ---------- Buttons & fields ---------- */
.wide-btn {
  width: 100%;
  padding: 9px;
  margin-bottom: 8px;
  background: var(--accent-dim);
  border: 1px solid rgba(56, 189, 248, 0.35);
  color: var(--accent);
  border-radius: 8px;
  font-size: 0.82rem;
  cursor: pointer;
  transition: background 0.15s;
}
.wide-btn:last-child { margin-bottom: 0; }
.wide-btn:hover { background: rgba(56, 189, 248, 0.25); }
.wide-btn.ghost { background: transparent; border-color: var(--border); color: var(--subtle); }
.wide-btn.ghost:hover { background: rgba(255,255,255,0.05); color: var(--text); }
.wide-btn:disabled { opacity: 0.5; cursor: default; }

.field-label {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--subtle);
  margin-bottom: 6px;
}
#search {
  width: 100%;
  padding: 8px 10px;
  background: rgba(0,0,0,0.3);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 0.85rem;
}
#search:focus { outline: none; border-color: var(--accent); }

/* ---------- Search suggestions ----------
   Lives at the end of <body>, not inside the panel: the panel clips its
   overflow and its backdrop-filter would trap a fixed-position child. Placed
   and sized from the input's rect by main.js. */
.search-results {
  position: fixed;
  z-index: 60; /* above both panels (20) and the timebar */
  margin: 0;
  padding: 4px;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--panel-solid);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
}
.search-results.hidden { display: none; }
.search-opt {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 9px 10px;
  border-radius: 6px;
  font-size: 0.82rem;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  /* Stops a tap being treated as the start of a scroll/selection gesture. */
  touch-action: manipulation;
}
.search-opt:hover,
.search-opt.active { background: var(--accent-dim); color: var(--accent); }
.search-opt-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* A match that only exists in the catalogue — choosing it opens its record
   rather than selecting something in 3D, so the row says so up front. */
.search-opt-meta { flex: none; font-size: 0.68rem; color: var(--subtle); }
.search-note { padding: 9px 10px; font-size: 0.78rem; color: var(--subtle); }

/* ---------- Readout ---------- */
.readout { margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.readout > div { min-width: 0; }
.readout dt { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--subtle); }
.readout dd { margin: 2px 0 0; font-size: 0.92rem; font-variant-numeric: tabular-nums; }
.checks {
  margin-top: 14px;
  display: grid;
  gap: 8px;
  border-top: 1px solid var(--border);
  padding-top: 12px;
}
.checks label { font-size: 0.84rem; display: flex; align-items: center; gap: 8px; cursor: pointer; }
.checks input { accent-color: var(--accent); }

/* ---------- Top bar ---------- */
#topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  /* Grows by the status-bar inset rather than being pushed down by it, so the
     gradient still reaches the top of the screen and the controls sit below
     the clock and notch instead of under them. */
  height: calc(48px + var(--safe-top));
  padding-top: var(--safe-top);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-left: calc(18px + var(--safe-left));
  padding-right: calc(18px + var(--safe-right));
  background: linear-gradient(to bottom, rgba(5,7,13,0.85), rgba(5,7,13,0));
  z-index: 15;
  pointer-events: none;
}
.brand { display: flex; align-items: center; gap: 10px; pointer-events: auto; }
.brand strong { letter-spacing: 0.3em; font-size: 0.95rem; }
.brand .subtle { color: var(--subtle); font-size: 0.78rem; }
.brand .dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px var(--accent);
  animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: 0.35; } }
.stats { display: flex; gap: 8px; pointer-events: auto; }
.pill {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 11px;
  font-size: 0.74rem;
  color: var(--subtle);
  font-variant-numeric: tabular-nums;
  backdrop-filter: blur(8px);
}
#stat-sats { color: var(--text); }

/* ---------- Time bar ---------- */
#timebar {
  position: fixed;
  bottom: calc(16px + var(--safe-bottom));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 14px;
  background: var(--panel);
  backdrop-filter: blur(14px);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: var(--shadow);
  z-index: 20;
}
.tbtn {
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  padding: 6px 11px;
  font-size: 0.78rem;
  cursor: pointer;
  min-width: 40px;
  transition: background 0.15s;
}
.tbtn:hover { background: rgba(255,255,255,0.14); }
.speed { display: flex; align-items: center; gap: 8px; }
.speed .field-label { margin: 0; }
.speed-btns { display: flex; gap: 4px; }
.skip { display: flex; align-items: center; gap: 8px; }
.skip .field-label { margin: 0; }
.skip-btns { display: flex; gap: 4px; }
/* Thin separators around the skip group so the three control clusters read
   as distinct in the single time-bar pill. */
.skip { padding: 0 12px; border-left: 1px solid var(--border); border-right: 1px solid var(--border); }
.sbtn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--subtle);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 0.74rem;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.sbtn.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
.clock {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  min-width: 168px;
  font-variant-numeric: tabular-nums;
}
#clock-utc { font-size: 0.85rem; }
.clock .subtle { font-size: 0.72rem; }

/* ---------- Toast ---------- */
.toast {
  position: fixed;
  bottom: 78px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(120, 24, 24, 0.92);
  border: 1px solid var(--danger);
  color: #fff;
  padding: 10px 16px;
  border-radius: 10px;
  font-size: 0.84rem;
  max-width: 520px;
  z-index: 40;
  box-shadow: var(--shadow);
}

.hidden { display: none !important; }

/* ---------- Mode switch ---------- */
.modeswitch {
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  pointer-events: auto;
  backdrop-filter: blur(8px);
}
.modeswitch button {
  background: transparent;
  border: none;
  color: var(--subtle);
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  padding: 5px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.modeswitch button:hover { color: var(--text); }
.modeswitch button.active { background: var(--accent-dim); color: var(--accent); }
#mode-reentry.active { background: rgba(255, 77, 77, 0.16); color: #ff7a7a; }
#mode-sky.active { background: rgba(140, 130, 255, 0.18); color: #b9b2ff; }

/* Mode-scoped panel sections: show only what belongs to the active mode. */
#reentry-section, #sky-section { display: none; }
body.mode-reentry #layers,
body.mode-reentry #tracker-actions { display: none; }
body.mode-reentry #reentry-section { display: block; }
body.mode-sky #layers,
body.mode-sky #tracker-actions { display: none; }
body.mode-sky #sky-section { display: block; }

/* ---------- Sky panel ---------- */
.sky-note {
  margin: 0 0 12px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}
.sky-look {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 12px;
}
.sky-look dt {
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.sky-look dd {
  margin: 2px 0 0;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.sky-legend {
  display: grid;
  gap: 6px;
  margin-bottom: 12px;
  font-size: 11px;
  color: var(--muted);
}
.sky-legend span { display: flex; align-items: center; gap: 7px; }
.sky-legend .dot-star,
.sky-legend .dot-body,
.sky-legend .dot-sat,
.sky-legend .dot-sat-dim {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
}
.sky-legend .dot-star { background: #ffffff; }
.sky-legend .dot-body { background: #ffd24a; }
.sky-legend .dot-sat { background: #38f5c8; }
.sky-legend .dot-sat-dim { background: #38f5c8; opacity: 0.32; }
.sky-check {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
}
.sky-check input { accent-color: var(--accent); cursor: pointer; }
.sky-sensor-note { margin-top: 10px; }
#sky-compass.active { background: var(--accent-dim); color: var(--accent); }

/* ---------- Reentry list ---------- */
.reentry-note {
  margin: 0 0 12px;
  font-size: 0.76rem;
  line-height: 1.45;
  color: var(--subtle);
}
.reentry-note strong { color: #ff9a9a; font-weight: 600; }
.reentry-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin: 12px 0 8px;
  font-size: 0.72rem;
  color: var(--subtle);
}
.reentry-legend span { display: inline-flex; align-items: center; gap: 6px; }
.reentry-legend .dot-red {
  width: 9px; height: 9px; border-radius: 50%;
  background: #ff4d4d; box-shadow: 0 0 8px #ff4d4d;
}
.reentry-legend .ring-red {
  width: 10px; height: 10px; border-radius: 50%;
  border: 2px solid #ff9a9a;
}
.reentry-list-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 6px;
  font-size: 0.74rem;
}
#reentry-count { color: var(--text); font-variant-numeric: tabular-nums; }
.reentry-list-head .subtle { font-size: 0.68rem; }
.reentry-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 46vh;
  overflow-y: auto;
}
.reentry-list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 8px;
  border-radius: 8px;
  cursor: pointer;
  border-left: 2px solid transparent;
  transition: background 0.15s;
}
.reentry-list li:hover { background: rgba(255,255,255,0.05); }
.reentry-list li.selected {
  background: rgba(255, 77, 77, 0.12);
  border-left-color: #ff4d4d;
}
.reentry-list .re-name {
  flex: 1;
  min-width: 0;
  font-size: 0.82rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.reentry-list .re-eta {
  font-size: 0.76rem;
  color: #ff9a9a;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.reentry-list li.imminent .re-eta { color: #ff5a5a; font-weight: 600; }
.reentry-list li.beyond .re-eta,
.reentry-list li.decayed .re-eta { color: var(--subtle); }
.reentry-empty { color: var(--subtle); font-size: 0.8rem; padding: 6px 2px; }

/* ---------- Reentry info (right panel) ---------- */
.reentry-info {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.reentry-status {
  font-size: 0.78rem;
  font-weight: 600;
  color: #ff7a7a;
  margin-bottom: 10px;
  letter-spacing: 0.02em;
}
.reentry-info .readout { gap: 10px 12px; }
#re-jump { margin-top: 12px; }
.re-past {
  margin: 10px 0 0;
  padding: 8px 10px;
  font-size: 0.74rem;
  line-height: 1.45;
  color: #ffd0d0;
  background: rgba(255, 77, 77, 0.12);
  border: 1px solid rgba(255, 77, 77, 0.4);
  border-radius: 8px;
}
.re-hint {
  margin: 10px 0 0;
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--subtle);
}

/* ---------- External info links ---------- */
.sel-links {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.links-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.links-row a {
  font-size: 0.76rem;
  color: var(--accent);
  text-decoration: none;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  transition: background 0.15s, border-color 0.15s;
}
.links-row a:hover { background: var(--accent-dim); border-color: var(--accent); }

/* ---------- Mobile ---------- */
/* ---------- Mobile: panels become bottom sheets ----------
   Measured on a 412x839 phone, the two floating cards plus the timebar and
   topbar covered 87% of the viewport — almost none of the thing the app exists
   to show was visible. Both panels now dock to the bottom, collapsed to their
   header by default, and only one expands at a time (openSheet in main.js).
   The existing `.panel.collapsed` rule already hides the body and sections, so
   a collapsed panel *is* the sheet handle; no second mechanism was needed. */
@media (max-width: 720px) {
  :root {
    --timebar-h: 54px;
    --sheet-peek: 58px;  /* grabber + header: what a collapsed sheet occupies */
    --sheet-gap: 8px;
    /* What the docked timebar actually occupies at the bottom of the screen:
       its own height plus the home-indicator inset it pads itself out by. The
       sheets stack against this rather than --timebar-h, or on a gesture-nav
       phone the lowest sheet handle hides behind the indicator. */
    --timebar-dock: calc(var(--timebar-h) + var(--safe-bottom));
  }

  /* Addressed by id, not `.panel`: the desktop rules `#panel-left { top: 64px }`
     and `#panel-right { top: 64px }` are id selectors, so a class rule here
     loses to them and the sheets stay stretched from the topbar to the
     bottom — full height, which is the opposite of the point. */
  #panel-left,
  #panel-right {
    top: auto;
    left: calc(8px + var(--safe-left));
    right: calc(8px + var(--safe-right));
    width: auto;
    max-height: var(--sheet-max);
    bottom: calc(var(--timebar-dock) + var(--sheet-gap));
    border-radius: 14px;
    transition: bottom 0.2s ease;
  }
  /* The selection sheet owns the bottom slot and the layers/sky sheet stacks
     above it, so both handles stay reachable while something is selected. */
  body.has-selection #panel-left {
    bottom: calc(var(--timebar-dock) + var(--sheet-peek) + var(--sheet-gap) * 2);
  }
  /* An expanded sheet would otherwise grow straight over the other panel's
     handle, so switching sheets would mean collapsing one before the other
     became tappable. Instead the collapsed handle rides on top of the open
     sheet and stays a single tap away. `--sheet-max` is the sheet height the
     lift is measured against, so the two cannot drift apart. */
  #panel-left,
  #panel-right { --sheet-max: 62vh; }
  body.sheet-expanded #panel-left.collapsed {
    bottom: calc(var(--sheet-max) + var(--timebar-dock) + var(--sheet-gap) * 2);
  }
  .panel.collapsed { z-index: 25; }   /* handles stay above an open sheet */
  .panel:not(.collapsed) { z-index: 24; }

  /* Standard bottom-sheet grabber, so the header reads as draggable/tappable. */
  .panel::before {
    content: '';
    display: block;
    flex: none;
    width: 36px;
    height: 4px;
    margin: 8px auto 2px;
    border-radius: 2px;
    background: var(--border);
  }
  .panel-header { cursor: pointer; padding: 8px 14px 12px; }

  /* --- Topbar: 616px of content in a 412px viewport before this --- */
  /* Longhand, not the `padding: 0 10px` shorthand this replaced: the shorthand
     resets padding-top to 0, which silently undoes the status-bar inset — on
     phones, the only devices that have one. */
  #topbar {
    gap: 8px;
    padding-left: calc(10px + var(--safe-left));
    padding-right: calc(10px + var(--safe-right));
  }
  .brand { display: none; }          /* the mode tabs identify the app */
  .modeswitch button { padding: 5px 10px; font-size: 0.78rem; white-space: nowrap; }
  #stat-fps, #stat-source { display: none; }
  .pill-label { display: none; }     /* "⚙ Location" -> "⚙" */
  /* Without this the count wraps to two lines and the pill grows a second row. */
  .pill { white-space: nowrap; }

  /* --- Timebar: full-width dock rather than a floating pill --- */
  #timebar {
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: none;
    transform: none;
    /* Content keeps --timebar-h; the inset is added as padding underneath, so
       the controls stay clear of the home indicator while the bar's background
       still runs to the bottom edge of the screen. */
    height: var(--timebar-dock);
    padding: 0 calc(10px + var(--safe-right)) var(--safe-bottom) calc(10px + var(--safe-left));
    gap: 10px;
    border-radius: 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    overflow-x: auto;
    overscroll-behavior-x: contain;
  }
  /* Play, NOW and the clock are pinned to the front so they are always in
     view; the skip and speed clusters scroll off to the right. Reordering in
     flex rather than the DOM keeps one source of truth for the markup. */
  #timebar > * { flex: none; }
  #btn-play { order: -3; }
  #btn-now { order: -2; }
  /* Tightened so more of the skip cluster is reachable before scrolling. */
  .clock { order: -1; min-width: 0; white-space: nowrap; }
  #clock-utc { font-size: 0.74rem; }
  .clock .subtle { font-size: 0.66rem; }
  .skip .field-label, .speed .field-label { display: none; }
}

/* ---------- Catalogue enrichment (selection panel) ---------- */
.sel-enrich { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.enrich-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; gap: 8px; }
#enrich-readout { margin-bottom: 8px; }
.enrich-sources { margin: 8px 0 0; font-size: 0.68rem; color: var(--subtle); }

/* Brightness badge */
.badge {
  display: inline-flex; align-items: center;
  padding: 3px 9px; border-radius: 999px;
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.02em;
  border: 1px solid transparent; white-space: nowrap;
}
.badge.tiny { padding: 1px 7px; font-size: 0.62rem; }
.bright-naked-eye  { background: rgba(250, 204, 21, 0.18); color: #facc15; border-color: rgba(250, 204, 21, 0.35); }
.bright-dark-sky   { background: rgba(163, 230, 53, 0.16); color: #a3e635; border-color: rgba(163, 230, 53, 0.30); }
.bright-binoculars { background: var(--accent-dim); color: var(--accent); border-color: rgba(56, 189, 248, 0.30); }
.bright-telescope  { background: rgba(148, 163, 184, 0.16); color: #94a3b8; border-color: rgba(148, 163, 184, 0.28); }
/* Estimated (per-constellation) magnitudes: dashed border signals "not measured". */
.badge-est { border-style: dashed; }

/* ---------- Objects with no element set ----------
   Deliberately neutral, not a warning colour: an object whose elements are not
   published (USA 224) or which is not in Earth orbit at all (the deep-space
   probes) is a normal catalogue entry, not an error state. */
.data-status { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.badge.no-elements {
  background: rgba(148, 163, 184, 0.16); color: #cbd5e1;
  border-color: rgba(148, 163, 184, 0.32);
}
.data-status-note { margin: 0 0 10px; font-size: 0.78rem; line-height: 1.45; color: var(--subtle); }
.approx-orbit { margin-bottom: 10px; }

/* Catalogue tab active state */
#mode-catalogue.active { background: rgba(52, 211, 153, 0.16); color: #34d399; }

/* ---------- Catalogue overlay ---------- */
.catalogue {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: rgba(3, 5, 10, 0.72);
  backdrop-filter: blur(4px);
  /* The 64px top clears the topbar, which itself grows by the status-bar
     inset — so this has to grow by the same amount or the catalogue slides
     under the mode tabs. */
  padding:
    calc(64px + var(--safe-top))
    calc(16px + var(--safe-right))
    calc(16px + var(--safe-bottom))
    calc(16px + var(--safe-left));
}
.cat-panel {
  width: min(980px, 100%); height: min(80vh, 760px);
  display: flex; flex-direction: column;
  background: var(--panel-solid);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow: hidden;
}
.cat-header {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--border);
}
.cat-header h2 { margin: 0; font-size: 1rem; }
.cat-header #cat-count { flex: 1; font-size: 0.8rem; }
.cat-filters {
  display: flex; gap: 8px; padding: 12px 16px;
  border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
.cat-filters input, .cat-filters select {
  padding: 8px 10px; background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border); border-radius: 8px; color: var(--text);
  font-size: 0.85rem;
}
.cat-filters input { flex: 1; min-width: 180px; }
.cat-body { flex: 1; display: grid; grid-template-columns: 1.2fr 1fr; min-height: 0; }
.cat-list {
  list-style: none; margin: 0; padding: 6px;
  overflow-y: auto; border-right: 1px solid var(--border);
}
.cat-row {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 4px 10px; padding: 8px 10px; border-radius: 8px; cursor: pointer;
}
.cat-row:hover { background: rgba(255, 255, 255, 0.05); }
.cat-row.active { background: var(--accent-dim); }
.cat-name { font-size: 0.9rem; grid-column: 1; }
.cat-meta { grid-column: 1; font-size: 0.72rem; color: var(--subtle); font-variant-numeric: tabular-nums; }
.cat-row .badge { grid-column: 2; grid-row: 1 / span 2; }
.cat-detail { padding: 16px; overflow-y: auto; }
.cat-detail h3 { margin: 0 0 10px; font-size: 1rem; }
.cat-detail-empty { margin-top: 24px; text-align: center; }
.cat-detail-actions { margin-top: 14px; }
.cat-foot { padding: 10px 16px; border-top: 1px solid var(--border); font-size: 0.72rem; }

@media (max-width: 720px) {
  .cat-body { grid-template-columns: 1fr; }
  .cat-detail { border-top: 1px solid var(--border); }
}

/* ---------- Location pill button + Settings modal ---------- */
.pill-btn { cursor: pointer; font: inherit; font-size: 0.72rem; }
.pill-btn:hover { border-color: var(--accent); color: var(--accent); }

.modal-overlay {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: rgba(3, 5, 10, 0.72); backdrop-filter: blur(4px);
  padding:
    calc(16px + var(--safe-top))
    calc(16px + var(--safe-right))
    calc(16px + var(--safe-bottom))
    calc(16px + var(--safe-left));
}
.modal-panel {
  width: min(420px, 100%);
  background: var(--panel-solid); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
}
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--border);
}
.modal-header h2 { margin: 0; font-size: 1rem; }
.modal-body { padding: 16px; }
.modal-body p { margin: 0 0 14px; line-height: 1.45; font-size: 0.82rem; }
.settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px; }
.settings-grid input {
  display: block; width: 100%; margin-top: 4px; padding: 8px 10px;
  background: rgba(255,255,255,0.04); border: 1px solid var(--border);
  border-radius: 8px; color: var(--text); font-size: 0.9rem;
}
.settings-actions { display: flex; gap: 8px; margin-top: 10px; }
.settings-actions .wide-btn { margin: 0; }
#set-status { margin: 12px 0 0; min-height: 1em; }

/* ---------- Visibility section (selection panel) ---------- */
.sel-visibility { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.vis-prompt p { margin: 6px 0 10px; font-size: 0.8rem; line-height: 1.4; }
.vis-visible { background: rgba(52, 211, 153, 0.18); color: #34d399; border-color: rgba(52, 211, 153, 0.35); }
.vis-shadow  { background: rgba(129, 140, 248, 0.16); color: #a5b4fc; border-color: rgba(129, 140, 248, 0.30); }
.vis-day     { background: rgba(250, 204, 21, 0.16); color: #facc15; border-color: rgba(250, 204, 21, 0.30); }
/* Twilight sits between "visible" green and "daylight" yellow, as does its hue. */
.vis-twilight { background: rgba(251, 146, 60, 0.16); color: #fb923c; border-color: rgba(251, 146, 60, 0.30); }
.vis-below   { background: rgba(148, 163, 184, 0.16); color: #94a3b8; border-color: rgba(148, 163, 184, 0.28); }

/* ---------- Visible-pass predictions (selection panel) ---------- */
.sel-passes { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.passes-list { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 6px; }
.pass-row {
  display: flex; flex-direction: column; gap: 2px;
  padding: 6px 9px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.03); border: 1px solid var(--border);
}
.pass-when { font-size: 0.86rem; font-variant-numeric: tabular-nums; }
.pass-meta { font-size: 0.72rem; color: var(--subtle); font-variant-numeric: tabular-nums; }
.passes-note { margin: 8px 0 0; font-size: 0.68rem; line-height: 1.4; }
