/* OrbitSmith MMX — page styles.
 *
 * Baseline: the public OrbitSmith Solar System explorer
 * (https://orbitsmith.net/solar-system?lang=ja, retrieved 2026-10-22 11:31:41Z;
 * research copy docs/redesign-v2/solar-system-public.css, receipt in
 * docs/redesign-v2/public-source-receipts.json). Rules marked [public] are copied
 * from that file (tokens, header, language menu, control groups, buttons, panel,
 * story, rail, modal, reduced motion). MMX rules below them use the same tokens.
 *
 * Type, exactly the faces the public page requests (no other weights are used,
 * so nothing is synthesised): IBM Plex Mono 400/500/600 for UI and numbers,
 * Noto Sans JP 400/500/600 for Japanese text, Orbitron 500/600/700 for the logo
 * and short Latin headings.
 *
 * Deliberate deviations from the public phone rules: controls keep a 44 px
 * minimum and at least 9-10 px text on phones (the public page shrinks some to
 * 40 px and 6-7 px).
 */

/* ------------------------------------------------------------ [public] tokens */
:root {
  color-scheme: dark;
  --cyan: #00e5ff;
  --bg: #000;
  --panel: rgba(4, 8, 16, 0.92);
  --panel-soft: rgba(4, 8, 16, 0.72);
  --border: rgba(255, 255, 255, 0.1);
  --border-strong: rgba(0, 229, 255, 0.34);
  --text: #e8eaef;
  --sub: rgba(255, 255, 255, 0.66);
  --muted: rgba(255, 255, 255, 0.52);
  --nav-h: 52px;
  --rail-h: 94px;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --radius: 8px;
  font-family: "IBM Plex Mono", "Noto Sans JP", monospace;
  background: var(--bg);
  color: var(--text);
  /* MMX additions, same palette */
  --warn: #ffc107;              /* public .source-mini.degraded */
  --model: #b9a6ff;             /* public lavender, used for teaching models */
  --space: #010409;             /* map background (contrast-checked paths) */
  --prose: "Noto Sans JP", "IBM Plex Mono", sans-serif;
  --mono: "IBM Plex Mono", "Noto Sans JP", monospace;
  --head: Orbitron, "Noto Sans JP", sans-serif;
  --gap: 14px;
  --panel-w: min(400px, 36vw);
  --sheet-h: 0px;
  --canvas-top: 0px;            /* phones (portrait, short landscape): the control rows get their own band above the map */
  --scene-right: calc(var(--panel-w) + 2 * var(--gap));
  --scene-bottom: calc(var(--rail-h) + var(--safe-bottom));
}

/* ------------------------------------------------------------- [public] base */
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; min-height: 100%; background: var(--bg); color: var(--text); }
html { -webkit-tap-highlight-color: rgba(0, 229, 255, 0.16); }
body {
  font-family: "IBM Plex Mono", "Noto Sans JP", monospace;
  font-size: 12px;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
button, select, a { font: inherit; }
button, select { color: inherit; }
button { border: 0; }
a { color: inherit; }
button, a, select { touch-action: manipulation; }

.skip-link {
  position: fixed;
  z-index: 1000;
  left: 12px;
  top: -80px;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 14px;
  background: #fff;
  color: #000;
  text-decoration: none;
  border-radius: 6px;
}
.skip-link:focus-visible { top: 8px; }

:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
  border-radius: 4px;
}

/* MMX base additions: no synthesised bold, no stray margins, inputs inherit. */
h1, h2, h3, h4, p, ul, ol, dl, dd, figure { margin: 0; }
h1, h2, h3, h4, strong, b, th, summary { font-weight: 600; }
button { background: transparent; cursor: pointer; }
button:disabled { cursor: not-allowed; }
input, select, textarea { font-family: inherit; font-size: inherit; }
ruby rt { font-size: 0.55em; color: var(--sub); }
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ----------------------------------------------------------- [public] header */
/* The public Solar System .topbar rules, on the MMX class of <header class="nav mmx-header">. The
   element itself is a .nav shell, as GS Planner's header is, so the shared navigation scripts treat
   it as one: links inline above 860 px, MENU drawer at 860 px and below. They would keep a .topbar
   shell's links in MENU up to 1800 px. */
.mmx-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  width: 100%;
  min-width: 0;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  background: rgba(0, 0, 0, 0.94);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  overflow: visible;
}
.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 44px;
  text-decoration: none;
}
.logo-text {
  font-family: Orbitron, sans-serif;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 3px;
  color: #fff;
  white-space: nowrap;
}
.logo-text span { color: var(--cyan); }
.tool-title {
  flex: 0 0 auto;
  padding-left: 14px;
  border-left: 1px solid rgba(255, 255, 255, 0.12);
  font-family: Orbitron, sans-serif;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 2px;
  color: var(--cyan);
  white-space: nowrap;
}
.nav-links {
  min-width: 0;
  flex: 1 1 0;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.nav-links::-webkit-scrollbar { display: none; }
.nav-link {
  position: relative;
  z-index: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-width: 44px;
  min-height: 44px;
  font-size: 9px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
  white-space: nowrap;
  padding: 0 7px;
  transition: color 0.2s, border-color 0.2s, background-color 0.2s;
}
.nav-link::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 12px 0;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 4px;
  pointer-events: none;
}
.nav-link:hover { color: var(--cyan); }
.nav-link:hover::before { border-color: rgba(0, 229, 255, 0.3); }
.topbar-flex { display: none; }
.lang-selector {
  position: relative;
  flex: 0 0 auto;
}
.lang-current {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  min-height: 0;
  height: 26px;
  padding: 4px 10px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.05);
  color: rgba(255, 255, 255, 0.4);
  font-size: 10px;
  letter-spacing: 1px;
  cursor: pointer;
  white-space: nowrap;
}
.lang-current::after { content: "\25be"; margin-left: 2px; font-size: 8px; }
.lang-current:hover { color: rgba(255, 255, 255, 0.6); border-color: rgba(255, 255, 255, 0.15); }
.lang-current[aria-expanded="true"] {
  color: var(--cyan);
  border-color: rgba(0, 229, 255, 0.28);
  background: rgba(0, 229, 255, 0.06);
}
.lang-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 200;
  display: none;
  min-width: 120px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  background: rgba(10, 14, 22, 0.97);
}
.lang-dropdown.open { display: block; }
.lang-option {
  display: block;
  width: 100%;
  min-width: 0;
  min-height: 0;
  padding: 7px 14px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: rgba(255, 255, 255, 0.5);
  font-size: 11px;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.lang-option:hover { background: rgba(0, 229, 255, 0.08); color: var(--cyan); }
.lang-option.active { color: var(--cyan); }

/* MMX accessibility additions to the shared header. The shared nav files stay
   byte-identical and inject their styles after this file, so these selectors
   carry an extra class or id to win. Drawn controls keep the public look; the
   26 px MENU and language buttons get transparent 44 px pointer areas that stay
   inside the header (padding box 13.5-37.5 in the 52 px header -> 4-48; 9.5-33.5
   in the 44 px phone header -> 0-44), the logo stretches to the header, menu
   rows and language options are 44 px tall. */
.mmx-header .logo { position: relative; align-self: stretch; }
.mmx-header .logo::before { content: ""; position: absolute; left: 0; right: 0; top: 0; bottom: -1px; }
.mmx-header .lang-selector { display: flex; align-items: center; }
.mmx-header .lang-current { position: relative; }
.mmx-header .lang-current::before { content: ""; position: absolute; left: 0; right: 0; }
.mmx-header .nav-toggle::after, .mmx-header .lang-current::before { top: -9.5px; bottom: -10.5px; }
.mmx-header .os-category-nav .nav-menu a { min-height: 44px; display: flex; align-items: center; }
/* The shared .nav drawer is placed for GS Planner's 52 / 44 px header (top 52 px, 44 px at 600 px and
   below). Here it starts at this header's own height (44 px from 620 px down) and without the inline
   links' 8 px margin, so it spans 10 px to 10 px of the screen as on GS Planner. */
@media (max-width: 860px) {
  header.mmx-header > .nav-links.os-category-nav { top: var(--nav-h); margin-left: 0; }
}
#langDropdown .lang-option { min-height: 44px !important; }

/* ----------------------------------------------------------- app shell [public] */
#main-content {
  position: fixed;
  inset: var(--nav-h) 0 0;
  overflow: hidden;
}
#main-content:focus { outline: none; }
.scene-shell { position: absolute; inset: 0; background: #000; }

/* The map: everything left of the context panel and above the rail (on portrait phones
   and short landscape also below the control band). The renderer fits Earth and MMX to
   this real box. */
.canvas-wrap {
  position: absolute;
  z-index: 1;
  left: 0;
  top: var(--canvas-top);
  right: var(--scene-right);
  bottom: var(--scene-bottom);
  overflow: hidden;
  background: var(--space);
}
.layer { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* Fixed full-screen app: the map takes every touch (as #spaceCanvas on the public page). */
#overlayCanvas { touch-action: none; cursor: grab; -webkit-user-select: none; user-select: none; }
#overlayCanvas:active { cursor: grabbing; }
#overlayCanvas:focus-visible { outline-offset: -3px; }
.scene-shell.is-plan .canvas-wrap .layer { filter: saturate(0.55) brightness(0.72); }

/* Everything drawn over the map lives in one layer that lets drags through. */
.scene-overlay {
  position: absolute;
  z-index: 20;
  top: var(--gap);
  left: var(--gap);
  right: calc(var(--scene-right) + var(--gap));
  bottom: calc(var(--scene-bottom) + var(--gap));
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 8px;
  pointer-events: none;
}
.scene-top, .scene-bottom { display: flex; gap: 8px; min-width: 0; }
/* The top column takes the map height left above the bottom row; panels opened in it
   (time, view tools) shrink and scroll inside that height instead of spilling over. */
.scene-top { flex: 1 1 auto; min-height: 0; flex-direction: column; align-items: flex-start; }
.scene-top > * { flex: 0 0 auto; }
.scene-top > .time-panel, .scene-top > .view-tools.open, .scene-top > .scene-tags { flex: 0 1 auto; min-height: 0; }
.scene-bottom { align-items: flex-end; }
.scene-overlay button, .scene-overlay input, .scene-overlay select, .scene-overlay a,
.top-controls, .time-panel, .view-tools, .ring-note { pointer-events: auto; }

/* ----------------------------------------------------- [public] top controls */
.top-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  flex-wrap: wrap;
}
.control-group {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 3px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.76);
}
.control-btn {
  min-width: 44px;
  min-height: 44px;
  padding: 0 10px;
  border-radius: 6px;
  background: transparent;
  color: var(--sub);
  font-size: 10px;
  letter-spacing: 0.08em;
  cursor: pointer;
  white-space: nowrap;
}
.control-btn:hover { color: #fff; }
.control-btn.active {
  color: #001014;
  background: var(--cyan);
  font-weight: 600;
}
.control-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.guide-trigger {
  min-height: 44px;
  padding-inline: 12px;
  border: 1px solid rgba(0, 229, 255, 0.22);
  background: rgba(0, 229, 255, 0.06);
  color: rgba(255, 255, 255, 0.78);
}
.time-select {
  min-height: 44px;
  border: 0;
  border-left: 1px solid var(--border);
  padding: 0 26px 0 10px;
  background: #03060a;
  color: var(--sub);
  font-size: 10px;
}
.date-readout {
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 0 11px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: rgba(0, 0, 0, 0.76);
  color: rgba(255, 255, 255, 0.65);
  font-size: 10px;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
}

/* MMX: the readout is a button inside the time group (opens the time panel). */
.time-controls-group .date-readout {
  gap: 8px;
  border: 0;
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  border-radius: 0;
  background: transparent;
  cursor: pointer;
}
/* The playback speed sits right after PLAY, as in the public time controls, so it can be changed
   while playing. It keeps its whole label; the readout gives way (it truncates). */
.time-controls-group .time-select { flex: none; min-width: 44px; }
.date-readout[aria-expanded="true"], .guide-trigger[aria-expanded="true"] { color: var(--cyan); }
.readout-mode { color: var(--warn); }
.readout-mode.is-now { color: var(--cyan); }
.readout-time { white-space: nowrap; }
.mode-switch .control-btn { min-width: 64px; }
.view-tools-btn { display: none; }
.icon-btn { padding: 0; font-size: 18px; letter-spacing: 0; }

/* ----------------------------------------------------- [public] buttons, notes */
.primary-btn, .secondary-btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 17px;
  border-radius: 8px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-decoration: none;
  cursor: pointer;
}
.primary-btn { background: var(--cyan); color: #001014; }
.primary-btn:hover { background: #64f1ff; }
.secondary-btn {
  border: 1px solid var(--border);
  background: rgba(0, 0, 0, 0.54);
  color: var(--text);
}
.secondary-btn:hover { border-color: var(--border-strong); }
.primary-btn:disabled, .secondary-btn:disabled { opacity: 0.4; }
.panel-close {
  width: 44px;
  height: 44px;
  flex: 0 0 auto;
  border-radius: 8px;
  background: transparent;
  color: var(--sub);
  font-size: 20px;
  cursor: pointer;
}
.panel-close:hover { color: #fff; background: rgba(255, 255, 255, 0.05); }
.source-button {
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.78);
  color: var(--sub);
  font-size: 9px;
  letter-spacing: 0.08em;
  cursor: pointer;
}
.source-button:hover { color: #fff; border-color: var(--border-strong); }

/* ---------------------------------------------------------- MMX scene overlays */
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.panel-title { color: #fff; font-family: var(--prose); font-size: 13px; font-weight: 600; line-height: 1.4; }
.panel-note { color: var(--sub); font-family: var(--prose); font-size: 11px; line-height: 1.6; }

.time-panel, .view-tools.open {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: rgba(4, 8, 16, 0.94);
  box-shadow: 0 22px 70px rgba(0, 0, 0, 0.58);
}
.time-panel {
  display: grid;
  gap: 8px;
  width: min(440px, 100%);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 8px 12px 12px 14px;
}
#timeSlider { width: 100%; min-height: 44px; accent-color: var(--cyan); background: transparent; cursor: pointer; }
.range-ends { display: flex; justify-content: space-between; gap: 8px; color: var(--muted); font-size: 9px; letter-spacing: 0.04em; }
.range-caption { font-family: var(--prose); text-align: center; }
.step-row { display: flex; flex-wrap: wrap; gap: 6px; }
.step-row .secondary-btn { padding: 0 10px; font-variant-numeric: tabular-nums; }
.date-entry { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; color: var(--sub); font-size: 10px; }
.date-entry input {
  min-height: 44px;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #03060a;
  color: var(--text);
  font-size: 12px;
}
.form-error { width: 100%; color: var(--warn); font-family: var(--prose); font-size: 11px; }
.form-error:empty, .status-line:empty { display: none; }
/* The time panel's own speed choice is shown only where PLAY has no room for one beside it
   (narrow short landscape, below); everywhere else the one beside PLAY is the only one. */
.speed-row { display: none; align-items: center; gap: 8px; color: var(--sub); font-size: 10px; }
.speed-row .time-select { border: 1px solid var(--border); border-radius: 8px; }
.status-line { color: var(--sub); font-family: var(--prose); font-size: 11px; line-height: 1.6; }

/* Map labels, in the look of the public .scale-note. */
.scene-tags { display: grid; gap: 6px; justify-items: start; align-content: start; max-width: min(560px, 100%); overflow: hidden; pointer-events: none; }
/* The same map facts docked at the top of the panel / sheet where the map is small
   (portrait phones, short landscape): there they never cover a plotted body. */
.map-line { display: none; }
.map-line .tag-line, .map-line .stage-tag, .map-line .fresh { padding: 3px 8px; }
/* The collapsed phone sheet shows them as one short flow beside MMX (portrait rules), at
   the 9 px phone label size, so the worst case still fits two lines next to the toggle. */
.map-brief { display: none; }
.map-brief .brief {
  padding: 1px 4px;
  border: 1px solid rgba(255, 193, 7, 0.45);
  border-radius: 4px;
  color: var(--warn);
  font-family: var(--prose);
  font-size: 9px;
  line-height: 1.5;
  white-space: nowrap;
}
.map-brief .brief.is-pred { color: var(--cyan); border-color: rgba(0, 229, 255, 0.5); }
.map-brief .brief.is-nodata, .map-brief .brief.is-plan { border-style: dashed; }
.map-brief .brief.is-stage { color: #fff; border-color: rgba(255, 255, 255, 0.28); }
.map-brief .brief-time { color: rgba(255, 255, 255, 0.85); font-size: 9px; line-height: 1.5; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tag-line, .stage-tag, .fresh, .limit-note, .gesture-hint, .ring-note {
  margin: 0;
  padding: 6px 10px;
  border: 1px solid rgba(0, 229, 255, 0.15);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.72);
  color: rgba(255, 255, 255, 0.78);
  font-size: 10px;
  line-height: 1.55;
  letter-spacing: 0.04em;
}
.tag-line { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.tag-time { font-variant-numeric: tabular-nums; }
.stage-tag { font-family: var(--prose); color: #fff; border-color: rgba(255, 255, 255, 0.28); }
.stage-tag.is-plan { color: var(--warn); border-color: rgba(255, 193, 7, 0.45); border-style: dashed; }
.fresh, .limit-note { color: var(--warn); font-family: var(--prose); border-color: rgba(255, 193, 7, 0.35); }
.gesture-hint { color: var(--sub); font-family: var(--prose); }
.gesture-hint:empty { display: none; }
.ring-note { display: flex; align-items: center; gap: 10px; font-family: var(--prose); }

.kind {
  display: inline-block;
  padding: 2px 7px;
  border: 1px solid;
  border-radius: 4px;
  font-size: 10px;
  line-height: 1.5;
  letter-spacing: 0.04em;
}
.kind-pred { color: var(--cyan); border-color: rgba(0, 229, 255, 0.5); }
.kind-nodata { color: var(--warn); border-color: rgba(255, 193, 7, 0.55); border-style: dashed; }
.kind-model { color: var(--model); border-color: rgba(185, 166, 255, 0.55); border-style: dotted; }
.kind-photo { color: var(--text); border: 3px double rgba(232, 234, 239, 0.5); padding: 0 6px; }
.kind-plan { color: var(--sub); border-color: rgba(255, 255, 255, 0.3); border-style: dashed; }
.kind-official { color: #fff; border-color: rgba(255, 255, 255, 0.45); }
.kind-official::before { content: "✓ "; color: var(--cyan); }
.kind-asof { color: var(--sub); border-color: rgba(255, 255, 255, 0.3); }   /* when this page last checked */
.kind-line { color: var(--sub); }

.view-tools { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.size-flag {
  min-height: 44px;
  padding: 0 12px;
  border: 1px dashed rgba(255, 193, 7, 0.6);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.78);
  color: var(--warn);
  font-family: var(--prose);
  font-size: 10px;
}
.size-flag.is-true { border-style: solid; border-color: rgba(232, 234, 239, 0.5); color: var(--text); }
/* Wide layouts: the view tools sit at the lower right of the map, above SOURCE / LIMITS. */
.scene-overlay > .scene-top > .view-tools { position: absolute; right: 0; bottom: 52px; }

.space-msg {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(92%, 420px);
  display: grid;
  justify-items: center;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid rgba(255, 193, 7, 0.45);
  border-radius: 12px;
  background: rgba(4, 8, 16, 0.94);
  font-family: var(--prose);
  font-size: 13px;
  line-height: 1.6;
  text-align: center;
}
.space-msg-sub { color: var(--sub); font-size: 12px; }
.space-msg-sub:empty { display: none; }

.scene-bottom .source-button { margin-left: auto; }

/* ------------------------------------------------------------ stage figure */
.stage-figure { display: grid; gap: 8px; }
.figure-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.figure-title { color: #fff; font-family: var(--prose); font-size: 13px; font-weight: 600; }
.figure-body svg { display: block; width: 100%; height: auto; max-height: 240px; }
.figure-body svg text { font-family: var(--prose); }
.figure-body .fig-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.figure-caption, .figure-data { color: var(--sub); font-family: var(--prose); font-size: 11px; line-height: 1.6; }
.figure-data a { color: var(--cyan); }
.fig-photo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; align-items: start; }
.fig-photo img { width: 100%; height: auto; display: block; border-radius: 6px; border: 1px solid var(--border); background: #000; }
.fig-compare { display: grid; gap: 6px; }
.fig-compare p { padding: 6px 8px; border-left: 2px solid var(--cyan); background: rgba(255, 255, 255, 0.035); font-family: var(--prose); font-size: 11px; line-height: 1.55; }
.fig-compare p.is-sand { border-left-style: dashed; border-left-color: var(--model); }
.fig-compare b { display: block; color: var(--cyan); font-weight: 500; font-size: 10px; }
.fig-compare p.is-sand b { color: var(--model); }
/* The related Phobos Lab page (same-origin; see mmx-links.js and the rules at the end). */
.lab-link { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 4px 0 10px; padding: 0; }
.lab-link .secondary-btn { font-family: var(--prose); letter-spacing: 0.04em; }
.lab-note { flex: 1 1 14em; min-width: 0; color: var(--sub); font-family: var(--prose); font-size: 11px; line-height: 1.5; }

/* ------------------------------------------------------------- signal panel */
.signal-panel { display: grid; gap: 8px; }
.signal-sim { line-height: 1.4; }
.signal-track svg { display: block; width: 100%; height: 70px; }
.signal-track text { font-family: var(--prose); font-size: 10px; }
.signal-schematic { color: var(--muted); font-family: var(--prose); font-size: 10px; }
.signal-modes { flex-wrap: wrap; justify-self: start; }
.signal-modes .control-btn[aria-pressed="true"] { color: #001014; background: var(--cyan); font-weight: 600; }
/* One row per number: the label, then its value on the same line when both fit (otherwise the value
   moves under it whole), so no label or value is squeezed into a narrow column. */
.signal-numbers { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; }
.signal-numbers > div { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; padding: 6px 8px; border: 1px solid rgba(255, 255, 255, 0.07); border-radius: 8px; background: rgba(255, 255, 255, 0.025); }
.signal-numbers dt { flex: 1 1 12em; min-width: 0; color: var(--muted); font-family: var(--prose); font-size: 10px; line-height: 1.4; }
.signal-numbers dd { flex: 0 1 auto; min-width: 0; color: #fff; font-size: 13px; font-weight: 500; font-variant-numeric: tabular-nums; }
.signal-kind { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.signal-progress { color: var(--sub); font-size: 10px; font-variant-numeric: tabular-nums; }
.signal-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.signal-note, .signal-basis, .signal-fact { color: var(--sub); font-family: var(--prose); font-size: 11px; line-height: 1.6; text-wrap: pretty; }
.signal-warn { color: var(--warn); }
.signal-fact { color: rgba(255, 255, 255, 0.82); }

/* --------------------------------------------------- context panel [public] */
.context-panel {
  position: absolute;
  z-index: 30;
  top: var(--gap);
  right: var(--gap);
  bottom: calc(var(--rail-h) + var(--gap) + var(--safe-bottom));
  width: var(--panel-w);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px 20px 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.48);
}
.ctx-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.ctx-title {
  color: #fff;
  font-family: Orbitron, "Noto Sans JP", sans-serif;
  font-size: clamp(26px, 2.6vw, 38px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0.04em;
}
.ctx-sub { margin-top: 4px; color: rgba(255, 255, 255, 0.74); font-family: var(--prose); font-size: 13px; line-height: 1.6; }
.sheet-toggle {
  display: none;
  min-height: 44px;
  min-width: 44px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.54);
  color: var(--sub);
  font-size: 10px;
  letter-spacing: 0.08em;
}
.sheet-toggle[aria-expanded="true"] { color: var(--cyan); border-color: var(--border-strong); }
.ctx-sources { display: none; }   /* short landscape: SOURCE / LIMITS sits here instead of over the map */

.clock-banner {
  display: grid;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid rgba(255, 193, 7, 0.45);
  border-radius: 8px;
  background: rgba(255, 193, 7, 0.06);
  font-family: var(--prose);
  font-size: 13px;
  line-height: 1.6;
}
.clock-device { color: var(--sub); font-size: 11px; }
.clock-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.clock-short, .clock-more { display: none; }       /* collapsed phone sheet only */
.clock-banner.is-compact { padding: 6px 10px; font-size: 12px; line-height: 1.5; }
.clock-banner.is-compact .clock-device, .clock-banner.is-compact .clock-actions { display: none; }

.ctx-status { display: grid; gap: 10px; }
.met-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.met-label { color: var(--cyan); font-family: var(--prose); font-size: 11px; letter-spacing: 0.08em; }
.met-value {
  color: #fff;
  font-family: "IBM Plex Mono", monospace;
  font-size: clamp(22px, 2.2vw, 30px);
  font-weight: 600;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.met-value small { margin: 0 0.3em 0 0.1em; color: var(--sub); font-size: 0.5em; font-weight: 500; }
.status-grid { display: grid; gap: 8px; }
.fact-callout {
  margin: 0;
  padding: 11px 13px;
  border-left: 2px solid var(--cyan);
  background: rgba(255, 255, 255, 0.035);
}
.fact-label {
  display: block;
  margin-bottom: 6px;
  color: var(--cyan);
  font-family: var(--prose);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
}
.fact-text { color: rgba(255, 255, 255, 0.92); font-family: var(--prose); font-size: 14px; font-weight: 500; line-height: 1.55; overflow-wrap: anywhere; text-wrap: pretty; }
.next-card { border-left-style: dashed; border-left-color: rgba(255, 255, 255, 0.45); }
.next-card .fact-label { color: var(--sub); }
.card-tag { margin-top: 4px; color: var(--cyan); font-size: 10px; letter-spacing: 0.04em; }
.card-tag::before { content: "✓ "; }
.card-tag.no-check::before, .card-tag.plan-tag::before { content: ""; }
.card-tag.plan-tag { color: var(--sub); }
.card-tag:empty { display: none; }
.card-note { margin-top: 6px; color: var(--warn); font-family: var(--prose); font-size: 11px; line-height: 1.55; }

.position-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.position-numbers { display: flex; flex-wrap: wrap; gap: 4px 14px; min-width: 0; }
.metric { display: grid; gap: 1px; }
.metric-label { color: var(--muted); font-family: var(--prose); font-size: 10px; }
.metric-value { color: #fff; font-size: 15px; font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.metric-value small { color: var(--sub); font-size: 0.7em; }
.metric-value.is-none { color: var(--warn); font-family: var(--prose); font-size: 12px; }
.metric-at { color: var(--muted); font-size: 10px; line-height: 1.5; }
.metric-at:empty { display: none; }
.signal-open { flex: 0 0 auto; padding: 0 12px; font-family: var(--prose); letter-spacing: 0.04em; }
.signal-open[aria-expanded="true"] { border-color: var(--border-strong); color: var(--cyan); }
.signal-open-note { color: var(--warn); font-family: var(--prose); font-size: 11px; }

.ctx-story { display: grid; gap: 0; }
/* A long "reference" note takes its own line and the previous/next buttons move under it, instead
   of the note being squeezed into a narrow column beside them. */
.journey-meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 12px; min-height: 22px; }
.journey-progress { color: var(--cyan); font-size: 10px; letter-spacing: 0.13em; font-variant-numeric: tabular-nums; }
.journey-exit {
  min-height: 44px;
  padding: 0 10px;
  background: transparent;
  color: var(--sub);
  font-size: 9px;
  letter-spacing: 0.08em;
  cursor: pointer;
}
.journey-exit:hover { color: #fff; }
.journey-exit:disabled { opacity: 0.35; }
.story-nav { display: inline-flex; gap: 2px; }
.journey-title {
  margin: 8px 0 6px;
  color: #fff;
  font-family: Orbitron, "Noto Sans JP", sans-serif;
  font-size: clamp(18px, 1.8vw, 24px);
  font-weight: 600;
  line-height: 1.3;
}
.journey-title:focus { outline: none; }
.journey-title:focus-visible { outline: 2px solid #fff; }
.story-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.story-badges:empty { display: none; }
.story-section {
  padding: 11px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}
.story-section:last-of-type { border-bottom: 0; }
.story-label {
  display: block;
  margin-bottom: 6px;
  color: var(--cyan);
  font-family: "IBM Plex Mono", "Noto Sans JP", monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.story-text { color: rgba(255, 255, 255, 0.82); font-family: var(--prose); font-size: 13px; line-height: 1.75; text-wrap: pretty; }
.source-mini { margin-top: 10px; color: rgba(255, 255, 255, 0.55); font-size: 10px; line-height: 1.6; }
.source-mini a, .more-copy a, .modal a { color: var(--cyan); overflow-wrap: anywhere; }
/* The radio panel and the teaching figures always sit in the context panel / sheet:
   nothing floats over the map, so Earth, MMX and the radio bead stay visible. */
.context-panel .stage-figure, .context-panel .signal-panel {
  margin: 6px 0 4px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.02);
  box-shadow: none;
}
.context-panel > * { flex-shrink: 0; }

.more-details { margin-top: 2px; }
.more-toggle {
  width: 100%;
  min-height: 44px;
  border-top: 1px solid var(--border);
  background: transparent;
  color: var(--sub);
  font-size: 10px;
  letter-spacing: 0.08em;
  cursor: pointer;
}
.more-toggle:hover, .more-toggle[aria-expanded="true"] { color: #fff; }
.more-copy {
  display: grid;
  gap: 8px;
  padding: 8px 2px 16px;
  color: rgba(255, 255, 255, 0.76);
  font-family: var(--prose);
  font-size: 12px;
  line-height: 1.75;
}
.more-copy h3 { margin-top: 6px; color: #fff; font-size: 12px; }
.detail-list { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.detail-list li { padding-left: 10px; border-left: 2px solid rgba(255, 255, 255, 0.14); }

/* ---------------------------------------------------------- rail [public] */
.body-rail {
  position: absolute;
  z-index: 36;
  left: 0;
  right: 0;
  bottom: 0;
  height: calc(var(--rail-h) + var(--safe-bottom));
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 9px 12px calc(9px + var(--safe-bottom));
  overflow-x: auto;
  overflow-y: hidden;
  background: rgba(0, 0, 0, 0.9);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.body-rail::-webkit-scrollbar { display: none; }
.milestones { display: flex; gap: 8px; margin: 0; padding: 0; list-style: none; }
.milestones li { flex: 0 0 auto; }
.body-chip {
  flex: 0 0 auto;
  min-width: 104px;
  min-height: 72px;
  display: grid;
  grid-template-columns: 18px 1fr;
  align-items: center;
  gap: 8px;
  padding: 8px 11px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: rgba(255, 255, 255, 0.48);
  cursor: pointer;
  text-align: left;
}
.body-chip:hover { color: #fff; background: rgba(255, 255, 255, 0.04); }
.body-chip.active {
  color: #fff;
  border-color: rgba(0, 229, 255, 0.54);
  background: rgba(0, 229, 255, 0.09);
}
.chip-dot {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 10px rgba(0, 229, 255, 0.55);
}
.chip-name { font-size: 10px; line-height: 1.35; letter-spacing: 0.04em; }
/* MMX chip content: date line, name, marker. Planned: hollow dashed dot. */
.body-chip.is-plan .chip-dot { background: transparent; border: 2px dashed rgba(255, 255, 255, 0.55); box-shadow: none; }
.chip-text { display: grid; gap: 2px; min-width: 0; }
.chip-date { color: var(--muted); font-size: 9px; letter-spacing: 0.04em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.body-chip:not(.is-plan) .chip-date { color: rgba(0, 229, 255, 0.85); }
.chip-name { font-family: var(--prose); font-size: 11px; white-space: nowrap; }
.chip-marker { justify-self: start; padding: 0 5px; border-radius: 3px; background: var(--cyan); color: #001014; font-size: 9px; font-weight: 600; line-height: 1.6; }
.chip-marker.is-next { background: transparent; color: var(--cyan); border: 1px solid rgba(0, 229, 255, 0.5); font-weight: 500; }
.chip-marker:empty { display: none; }

/* --------------------------------------------------------- dialogs [public] */
dialog.modal {
  width: min(760px, calc(100vw - 24px));
  max-height: min(760px, calc(100dvh - 40px));
  margin: auto;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  background: #050810;
  color: var(--text);
  box-shadow: 0 30px 100px rgba(0, 0, 0, 0.72);
}
dialog.modal:not([open]) { display: none; }
dialog.modal[open] { display: flex; flex-direction: column; }
dialog.modal::backdrop { background: rgba(0, 0, 0, 0.62); }
dialog.modal-wide { width: min(1080px, calc(100vw - 24px)); }
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 8px 8px 20px; border-bottom: 1px solid var(--border); }
.modal-head h2 { color: #fff; font-family: var(--head); font-size: 18px; font-weight: 600; line-height: 1.35; }
.modal-body { display: grid; gap: 10px; align-content: start; padding: 14px 20px 22px; overflow-y: auto; overscroll-behavior: contain; }
.modal p, .modal li { color: rgba(255, 255, 255, 0.72); font-family: var(--prose); font-size: 13px; line-height: 1.8; }
.modal h3 { margin-top: 8px; color: #fff; font-family: var(--prose); font-size: 13px; }
.source-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.source-list a { display: flex; align-items: center; min-height: 44px; }
.about-fig { max-width: 320px; }
.about-fig img { width: 100%; height: auto; display: block; border-radius: 8px; border: 1px solid var(--border); background: #0c1a2c; }
.about-fig figcaption { color: var(--sub); font-family: var(--prose); font-size: 11px; margin-top: 4px; }
.foot-small { color: var(--muted); }

/* Photo observation (2008 ESA photo, real pixels, page-only notes). */
.sand-layout { grid-template-columns: minmax(0, 1fr); }
.photo-col, .notes-col { display: grid; gap: 8px; align-content: start; min-width: 0; }
.photo-wrap { position: relative; height: clamp(220px, 46vh, 460px); border: 1px solid var(--border); border-radius: 8px; background: #000; overflow: hidden; }
/* Whole photo: a vertical swipe scrolls the sheet. Zoomed in: the photo pans. */
#photoCanvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: pan-y; cursor: grab; }
.photo-wrap.is-zoomed #photoCanvas { touch-action: none; }
.photo-status { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 8px 12px; border-radius: 8px; background: rgba(0, 0, 0, 0.8); }
.photo-prompt { color: #fff !important; font-weight: 500; }
.roi-row, .photo-ctl { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.roi-row.control-group { justify-self: start; }
.roi-row .control-btn[aria-pressed="true"] { color: #001014; background: var(--cyan); font-weight: 600; }
.photo-ctl .primary-btn { margin-left: auto; }
.photo-failed { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 12px; border: 1px solid rgba(255, 193, 7, 0.45); border-radius: 8px; }
.notes-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.notes-board { display: grid; gap: 8px; }
.note-col { min-height: 56px; padding: 8px; border: 1px dashed rgba(255, 255, 255, 0.18); border-radius: 8px; }
.note-col.is-drop { border-color: var(--cyan); }
.note-col h4 { margin-bottom: 6px; color: var(--sub); font-family: var(--prose); font-size: 11px; }
.note-card { display: grid; gap: 6px; padding: 8px; border: 1px solid var(--border); border-radius: 8px; background: rgba(255, 255, 255, 0.03); }
.note-card + .note-card { margin-top: 6px; }
.note-card.is-selected { border-color: var(--cyan); }
.note-top { display: flex; gap: 8px; align-items: flex-start; }
.note-thumb { flex: 0 0 88px; height: 66px; border-radius: 6px; background-color: #000; background-repeat: no-repeat; border: 1px solid var(--border); }
.note-chips, .note-moves { display: flex; flex-wrap: wrap; gap: 4px; }
.chip { min-height: 44px; padding: 0 10px; border: 1px solid var(--border); border-radius: 22px; background: transparent; color: var(--sub); font-family: var(--prose); font-size: 11px; }
.chip[aria-pressed="true"] { border-color: var(--cyan); color: var(--cyan); }
.note-text { width: 100%; min-height: 44px; padding: 0 8px; border: 1px solid var(--border); border-radius: 8px; background: #03060a; color: var(--text); font-family: var(--prose); font-size: 13px; }
.note-moves .secondary-btn { padding: 0 8px; font-family: var(--prose); letter-spacing: 0.02em; }
.note-hint { padding: 8px 10px; border-left: 3px solid var(--cyan); background: rgba(0, 229, 255, 0.05); }
.sample-box { display: grid; gap: 8px; padding: 10px; border: 1px solid var(--border); border-radius: 8px; }
.more summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; color: var(--cyan); font-family: var(--prose); font-weight: 500; }
@media (min-width: 900px) { .sand-layout { grid-template-columns: minmax(0, 3fr) minmax(300px, 2fr); } }

/* ------------------------------------------------------------- [public] media */
@media (max-width: 900px) {
  :root { --rail-h: 60px; }
  .mmx-header { gap: 10px; padding: 0 10px; }
  .logo-text { font-size: 12px; letter-spacing: 2px; }
  .nav-links { gap: 9px; }
  .nav-link { font-size: 8px; }
  .body-rail { align-items: center; gap: 4px; padding: 5px 6px calc(5px + var(--safe-bottom)); }
  .body-chip { min-width: 96px; min-height: 48px; padding: 4px 8px; grid-template-columns: 12px 1fr; gap: 6px; }
  .chip-dot { width: 12px; height: 12px; }
  .chip-marker { padding: 0 4px; font-size: 8px; line-height: 1.3; }   /* いま / 次 stay visible on phones */
}

@media (max-width: 620px) {
  :root { --nav-h: 44px; }
  .mmx-header { height: var(--nav-h); gap: 10px; padding: 0 10px; }
  .logo svg { width: 22px; height: 22px; }
  .logo-text { font-size: 12px; letter-spacing: 2px; }
  .tool-title { display: none; }
  .nav-links { gap: 6px; }
  .nav-link { padding: 0 5px; font-size: 7px; letter-spacing: 1px; }
  .lang-current { width: auto; max-width: 64px; height: 26px; padding-inline: 6px; font-size: 8px; }
  /* MMX: in the 44 px header the logo stretches to the 43 px content box; its
     ::before adds the border row, so its pointer area is exactly 0-44. */
  .mmx-header .logo { min-height: 0; }
}

/* MMX: the page name stays in the same 44 px header on phones (the public rule above hides the
   tool title), so MMX is still named while the sheet scrolls. Not below 360 px: there it would
   crowd MENU and the language button (occupancy in docs/redesign-v2/mobile-feedback-pass.md).
   If real glyphs are wider than estimated, the title is cut first; nothing else moves. */
@media (min-width: 360px) and (max-width: 620px) {
  .mmx-header .tool-title { display: block; flex: 0 1 auto; min-width: 0; overflow: hidden; padding-left: 10px; }
}

/* Short or narrow maps: view tools collapse behind VIEW / 見方 (opens below the controls). */
@media (max-width: 720px), (max-height: 559px) {
  .view-tools-btn { display: inline-flex; align-items: center; }
  .scene-overlay > .scene-top > .view-tools { position: static; }
  .view-tools:not(.open) { display: none; }
  /* Shrinks to the room left in the map column and scrolls inside it (a focused
     button scrolls into view); nothing spills over the map. */
  .view-tools.open { align-items: flex-start; padding: 8px; overflow-y: auto; overscroll-behavior: contain; }
  .view-tools .control-group { flex-wrap: wrap; }
}

/* Portrait phones: the context becomes a bottom sheet under the map, in the public
   split style. The two control rows get their own band above the map (control band rules
   below), and the position type, time, milestone and freshness move into the sheet (a
   short flow in its header while collapsed, the full .map-line when expanded), so no map
   fact stays over the map (SOURCE / LIMITS keeps the map's lower-right corner here). The
   map is the box between that band and the sheet; the renderer fits Earth and MMX into
   it and re-measures it when the sheet changes.
   The default sheet leaves at least 180 px of map (--map-keep = band + 180 px); the explicit reading expansion override below keeps 120 px.
   Percentages are of the main area (viewport minus header). Expanding
   (:root.sheet-expanded, set by script on <html> so --scene-bottom is recomputed)
   grows the sheet only up to that limit; beyond it the sheet scrolls inside. */
@media (max-width: 720px) and (orientation: portrait) {
  :root {
    --gap: 8px;
    --controls-band: 108px;
    --canvas-top: var(--controls-band);
    --map-keep: calc(var(--controls-band) + 180px);
    --sheet-room: calc(100% - var(--rail-h) - var(--safe-bottom) - var(--map-keep));
    --sheet-h: min(clamp(176px, 33%, 272px), var(--sheet-room));
    --scene-right: 0px;
    --scene-bottom: calc(var(--rail-h) + var(--sheet-h) + var(--safe-bottom));
  }
  :root.sheet-expanded { --sheet-h: min(520px, var(--sheet-room)); }
  .scene-tags { max-width: 100%; }
  .context-panel {
    top: auto;
    left: 0;
    right: 0;
    bottom: calc(var(--rail-h) + var(--safe-bottom));
    width: auto;
    height: var(--sheet-h);
    gap: 8px;
    padding: 8px 12px 14px;
    border-bottom: 0;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -12px 40px rgba(0, 0, 0, 0.55);
  }
  /* The toggle keeps its one-line label at full width; the short facts beside MMX wrap instead. */
  .sheet-toggle { display: inline-flex; align-items: center; flex: none; white-space: nowrap; }
  .ctx-head { align-items: center; }
  .ctx-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; min-width: 0; }
  .ctx-title { font-size: 18px; }
  .ctx-sub { margin-top: 0; font-size: 11px; line-height: 1.4; }
  .met-value { font-size: 20px; }
  .met-row.is-none { display: none; }               /* no instant: no empty "—" row */
  .status-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6px; }
  .status-grid.is-single { grid-template-columns: minmax(0, 1fr); }
  .fact-callout { padding: 6px 8px; }
  .fact-label { margin-bottom: 2px; font-size: 9px; }
  .fact-text { font-size: 12px; line-height: 1.45; }
  .metric-label { font-size: 9px; }
  .metric-value { font-size: 13px; }
  .signal-open { padding: 0 10px; }
  .journey-title { font-size: 17px; }
  .story-text { font-size: 13px; }
  dialog.modal, dialog.modal-wide { width: 100%; max-width: 100%; margin: auto 0 0; max-height: 94dvh; border-radius: 14px 14px 0 0; }

  /* Collapsed sheet: the map facts are one short flow beside MMX in the header (kind, time,
     short caveats: aria-hidden), so the lead content starts right below the header. The
     full sentences stay in the DOM, visually hidden for screen readers, and are shown when
     the sheet is expanded (with the subtitle). Nothing goes back over the map. */
  .ctx-heading > .ctx-sub { display: none; }
  .map-brief { display: contents; }
  .map-line { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
  .context-panel.is-expanded .ctx-heading > .ctx-sub { display: block; }
  .context-panel.is-expanded .map-brief { display: none; }
  .context-panel.is-expanded .map-line { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; }
  /* Unverified clock, collapsed: one row (short note + 日時をえらぶ, which opens the sheet at the
     three choices); the full message is read by screen readers. The 旅をたどる one-line notice
     is the 時計未確認 mark of the short flow. Expanded: the full notices. */
  .clock-banner.is-full { grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 8px; padding: 4px 4px 4px 12px; }
  .clock-banner.is-full > .clock-msg, .clock-banner.is-compact { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
  .clock-banner.is-full > .clock-short { display: block; font-size: 12px; line-height: 1.5; }
  .clock-banner.is-full > .clock-more { display: inline-flex; padding: 0 12px; }
  .clock-banner.is-full > .clock-device, .clock-banner.is-full > .clock-actions { display: none; }
  .context-panel.is-expanded .clock-banner.is-full { grid-template-columns: minmax(0, 1fr); padding: 12px 14px; }
  .context-panel.is-expanded .clock-banner.is-full > .clock-msg,
  .context-panel.is-expanded .clock-banner.is-compact { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; }
  .context-panel.is-expanded .clock-banner.is-full > .clock-short,
  .context-panel.is-expanded .clock-banner.is-full > .clock-more { display: none; }
  .context-panel.is-expanded .clock-banner.is-full > .clock-device { display: block; }
  .context-panel.is-expanded .clock-banner.is-full > .clock-actions { display: flex; }
  /* A chosen milestone leads with its title and first answer; its badges and the
     previous/next buttons follow (the rail under the map also picks milestones). Only
     the reading order of non-interactive blocks changes; the focus order is the same. */
  .ctx-story.is-lead > .journey-title { order: -3; margin: 0 0 1px; }
  .ctx-story.is-lead > .story-what { order: -2; }
  .ctx-story.is-lead > .story-badges { order: -1; margin: 6px 0 2px; }
}

@media (max-width: 720px) and (orientation: portrait) and (max-height: 600px) {
  :root { --rail-h: 56px; }
  .ctx-sub, .context-panel.is-expanded .ctx-heading > .ctx-sub { display: none; }
  .met-value { font-size: 18px; }
  .context-panel { gap: 6px; }
}

/* The control band (portrait phones and short landscape). The controls are a grid of
   exactly two rows, whatever the readout says, in a band of their own above the map: the
   map box starts below --controls-band, so no control covers a plotted body, label or
   path, and the renderer fits Earth and MMX into the real, unobstructed box. A row is
   46 px (44 px buttons in a group with a 1 px border): 8 px inset + 46 + 4 + 46 = 104 px,
   inside the 108 px band. Row 1: mode tabs, 3D/2D and VIEW; row 2: the time controls
   (PLAY, its speed, the readout, the zone), so the speed has room beside PLAY.
   The readout truncates (its full text stays the button's accessible name, and the panel's
   map line shows the type and time); the tabs keep 44 px targets whatever it says. */
@media (max-width: 720px) and (orientation: portrait), (max-height: 520px) and (orientation: landscape) {
  .top-controls {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "mode view tools" "time time time";
    width: 100%;
    gap: 4px;
  }
  .mode-switch { grid-area: mode; }
  .view-switch { grid-area: view; }
  .time-controls-group { grid-area: time; }
  .view-tools-btn { grid-area: tools; justify-self: end; }
  .mode-switch, .time-controls-group { min-width: 0; }
  .mode-switch .control-btn { flex: 1 1 0; min-width: 44px; padding-inline: 6px; }
  .time-controls-group .date-readout { flex: 1 1 auto; min-width: 0; padding-inline: 6px; overflow: hidden; }
  .readout-mode, .readout-time { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .readout-mode { flex: 0 1 auto; }
  .readout-time { flex: 1 1 auto; }
}

/* Short landscape screens: a narrower side panel and a lower rail, and the control band
   above the map. The map column is wide and short: the fixed-size controls share row 1
   and the time controls get all of row 2, where only the mode label may truncate (the
   time stays whole; the narrow block below moves the speed into the time panel).
   SOURCE / LIMITS moves from the map's corner to the top of the side
   panel, so no control stays over the map (a direction label or body near that corner
   stays visible). The side panel does not take map height, so the map is the main
   area minus the band and the rail: 172 px at 844x390 (the portrait 180 px floor is kept
   by shrinking the sheet, which this layout does not have). */
@media (max-height: 520px) and (orientation: landscape) {
  :root { --rail-h: 58px; --gap: 8px; --panel-w: min(340px, 40vw); --controls-band: 108px; --canvas-top: var(--controls-band); }
  .top-controls { grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "mode view tools" "time time time"; }
  .readout-time { flex: 1 0 auto; }
  .scene-bottom { display: none; }
  .ctx-sources { display: inline-flex; align-items: center; flex: none; }
  .context-panel { padding: 10px 12px 14px; }
  .ctx-title { font-size: 20px; }
  .ctx-sub { font-size: 11px; }
  .met-value { font-size: 18px; }
  .scene-tags .gesture-hint { display: none; }
}

/* Narrow short landscape (568x320, 640x360): row 2 has no room for the speed beside PLAY without
   cutting the time, so there the speed choice is the time panel's own. The page reads the same
   query (PANEL_SPEED_QUERY in mmx-app.js) to keep keyboard focus on the select that is shown. */
@media (max-height: 520px) and (orientation: landscape) and (max-width: 666px) {
  .time-controls-group .time-select { display: none; }
  .speed-row { display: flex; }
}

/* Small maps (portrait phones, short landscape): the persistent map facts are shown
   only in the panel's map line; transient notes (zoom limit, ring note, first hint)
   stay with the map. In the narrow sheet or side panel the photo and its two notes are
   stacked instead of sharing a row of two narrow columns. */
@media (max-width: 720px) and (orientation: portrait), (max-height: 520px) and (orientation: landscape) {
  .map-line { display: grid; gap: 4px; justify-items: start; }
  .scene-tags .tag-line, .scene-tags .stage-tag, .scene-tags .fresh { display: none; }
  .fig-photo { grid-template-columns: minmax(0, 1fr); }
}

@media (pointer: coarse) {
  .gesture-hint { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}


/* GPT review: measured with the public fonts in signed Edge. Keep the shared
   44px header, wordmark and both navigation controls at 320px. */
@media (max-width: 359px) {
  .mmx-header { gap: 9px; }
  .mmx-header .tool-title { display: block; flex: 0 0 auto; min-width: 0; overflow: visible; padding-left: 0; border-left: 0; font-size: 11px; letter-spacing: 0; }
}
.map-brief .brief.is-saved { color: var(--sub); border-color: var(--border); }

/* Expansion keeps its original meaning: more room to read the explanation.
   The default map is unchanged; only the explicitly expanded state gives it
   a 120px minimum, gaining 64px of reading room at 320x568. */
@media (max-width: 720px) and (orientation: portrait) {
  :root.sheet-expanded { --map-keep: calc(var(--controls-band) + 120px); }
  .context-panel.is-expanded .status-grid { grid-template-columns: minmax(0, 1fr); }
  .context-panel.is-expanded .fact-label { font-size: 11px; }
  .context-panel.is-expanded .fact-text { font-size: 14px; line-height: 1.6; }
  .context-panel.is-expanded .story-text { font-size: 14px; line-height: 1.75; }
  .context-panel.is-expanded .ctx-head { position: sticky; top: -8px; z-index: 5; background: rgb(4, 8, 16); padding-block: 6px; }
}

.fresh.is-saved { color: var(--sub); border-color: var(--border); }

/* A short always-visible distinction; the full map credits stay in Sources. */
.surface-note { align-self: flex-end; flex: 1 1 auto; min-width: 0; max-width: 210px; padding: 3px 6px; border-radius: 4px; background: rgba(0,0,0,.72); color: var(--sub); font-family: var(--prose); font-size: 9px; line-height: 1.5; pointer-events: none; }
.details-chevron { display: inline-block; margin-left: 6px; color: var(--cyan); }

/* The short purpose stays inside the existing heading, beside MMX on desktop. */
.ctx-purpose { display: none; margin: 0; color: rgba(255,255,255,.74); font-family: var(--prose); font-size: 11px; line-height: 1.4; }
@media (min-width: 721px) and (min-height: 521px) {
  .ctx-heading { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 10px; }
  .ctx-purpose { display: block; }
  .ctx-sub { flex-basis: 100%; }
}
@media (max-width: 720px) and (orientation: portrait) {
  .ctx-purpose { display: block; }
}
@media (max-width: 720px) and (orientation: portrait) and (min-height: 601px) {
  .context-panel.is-expanded .ctx-purpose { display: none; }
}

/* Once a journey stage leads, its own title supplies the context. */
.context-panel[aria-labelledby="tabJourney"] .ctx-purpose { display: none; }

/* Same guide presentation and controls as GS Planner. */
.mmx-guide-overlay{position:fixed;inset:0;z-index:30000;display:block;pointer-events:none;}
.mmx-guide-overlay[hidden]{display:none;}
.mmx-guide-scrim{position:absolute;inset:0;background:rgba(0,0,0,.36);pointer-events:auto;}
.mmx-guide-highlight{position:absolute;border:2px solid rgba(0,229,255,.92);border-radius:10px;box-shadow:0 0 0 9999px rgba(0,0,0,.34),0 0 24px rgba(0,229,255,.55);pointer-events:none;transition:left .18s ease,top .18s ease,width .18s ease,height .18s ease;}
.mmx-guide-card{position:absolute;width:min(340px,calc(100vw - 24px));max-height:calc(100dvh - 20px);overflow:auto;overscroll-behavior:contain;padding:13px 14px 12px;border:1px solid rgba(0,229,255,.42);border-radius:10px;background:rgba(3,8,16,.97);box-shadow:0 22px 54px rgba(0,0,0,.5),0 0 22px rgba(0,229,255,.14);pointer-events:auto;}
.mmx-guide-card::before{content:"";position:absolute;left:var(--guide-arrow-x,50%);width:12px;height:12px;background:rgba(3,8,16,.97);border-left:1px solid rgba(0,229,255,.42);border-top:1px solid rgba(0,229,255,.42);transform:translateX(-50%) rotate(45deg);}
.mmx-guide-card.is-below::before{top:-7px;}
.mmx-guide-card.is-above::before{bottom:-7px;transform:translateX(-50%) rotate(225deg);}
.mmx-guide-progress{font-family:Orbitron,sans-serif;font-weight:700;font-size:9px;letter-spacing:.08em;color:rgba(255,193,7,.92);}
.mmx-guide-card h2{margin:6px 0 0;font-family:Orbitron,sans-serif;font-weight:700;font-size:14px;line-height:1.35;letter-spacing:0;color:#fff;}
.mmx-guide-card p{margin-top:7px;font-size:12px;line-height:1.58;color:rgba(232,234,239,.88);white-space:pre-line;}
.mmx-guide-actions{display:grid;grid-template-columns:auto 1fr auto auto;align-items:center;gap:8px;margin-top:12px;}
.mmx-guide-actions button{min-height:34px;padding:0 10px;border:1px solid rgba(0,229,255,.2);border-radius:6px;background:rgba(0,229,255,.06);color:var(--cyan);font-family:var(--prose);font-weight:600;font-size:10px;letter-spacing:1px;text-transform:uppercase;cursor:pointer;}
.mmx-guide-actions button:hover{border-color:var(--cyan);background:rgba(0,229,255,.11);}
.mmx-guide-actions button:disabled{opacity:.35;cursor:not-allowed;}
.mmx-guide-actions #mmxGuideSkip{grid-column:3;color:var(--text-dim);border-color:var(--border-h);background:transparent;}
.mmx-guide-actions #mmxGuideNext{grid-column:4;border-color:rgba(0,230,118,.5);background:rgba(0,230,118,.12);color:#dfffea;}

/* GUIDE in the header as adopted on GS Planner, by its own mechanism: the same markup order (the
   phone GUIDE right after the logo; the desktop .guide-reopen after the navigation, before MENU and
   the language) and its rules. The desktop GUIDE follows the inline links (CONTACT), or the page
   name while the links are in the MENU drawer, and the shared navigation's auto margin (on MENU, or
   on the language) keeps the controls at the right. At 600 px and below the subtle cyan GUIDE (GS
   .gs-planner-mobile-guide values, margin-left:auto) joins MENU and the language at the right, as the
   adopted GS Planner's candidate rule sets MENU's margin to 0 there (here one element type more
   specific than the shared navigation's own MENU margin).
   The text is what GS Planner's running app writes into its triggers (ガイド, GUIDE, 指南, GUÍA; see
   mmx-guide.js), not the static placeholder of its HTML. As for MENU and the language button above,
   the drawn 22 / 18 px buttons get transparent 44 px pointer areas inside the header, as wide as the
   buttons (padding box 15.5-35.5 in the 52 px header -> 4-48, 11.5-31.5 in the 44 px header -> 0-44;
   mobile 13.5-29.5 -> 0-44). */
.guide-reopen{font-family:'IBM Plex Mono','Noto Sans JP',monospace;font-size:9px;letter-spacing:2px;color:rgba(255,255,255,0.5);cursor:pointer;text-transform:uppercase;padding:4px 8px;border:1px solid rgba(255,255,255,0.08);border-radius:4px;transition:color 0.2s,background-color 0.2s,border-color 0.2s,box-shadow 0.2s,transform 0.2s,opacity 0.2s;flex-shrink:0;white-space:nowrap;text-decoration:none;background:transparent;}
.guide-reopen:hover{color:#00e5ff;border-color:rgba(0,229,255,0.3);}
.mmx-header .guide-reopen { position:relative; display:inline-flex; align-items:center; height:22px; }
.mmx-header .guide-reopen::before { content:""; position:absolute; left:0; right:0; top:-11.5px; bottom:-12.5px; }
/* With the links inline (above 860 px, as on GS Planner's .nav shell), the public .nav-links grows
   (flex 1 1 0) and would push GUIDE to the far right beside the language. As on GS Planner, the links
   take their own width, GUIDE follows CONTACT 16 px after it (GS Planner's .nav gap; ours is a 12 px
   gap plus 4 px, or 10 plus 6 px at 900 px and below) and the language's shared auto margin keeps it
   alone at the right. In the drawer state the links are fixed (out of the row), so this changes
   nothing at 860 px and below. */
.mmx-header > .nav-links.os-category-nav { flex: 0 1 auto; }
@media (min-width: 861px) {
  .mmx-header > .mmx-guide-desktop { margin-left: 4px; }
}
@media (min-width: 861px) and (max-width: 900px) {
  .mmx-header > .mmx-guide-desktop { margin-left: 6px; }
}
/* From 861 to 1000 px the inline links leave no room for the MMX page name after the wordmark, so it
   yields there (the panel heading still names MMX); the logo, links, GUIDE and language keep their
   public sizes. Widths in tests/header-nav-gate.test.js. */
@media (min-width: 861px) and (max-width: 1000px) {
  .mmx-header .tool-title { display: none; }
}
.mmx-guide-mobile { display:none; }
@media(max-width:600px) {
  .mmx-header .mmx-guide-desktop, .mmx-header .tool-title { display:none; }
  .mmx-guide-mobile { position:relative; display:inline-flex; align-items:center; flex-shrink:0; height:18px; margin-left:auto; padding:0 6px; border:1px solid rgba(0,229,255,.28); border-radius:4px; background:rgba(0,229,255,.07); color:var(--cyan); font-family:'IBM Plex Mono','Noto Sans JP','Noto Sans SC',monospace; font-weight:400; font-size:8px; line-height:1; letter-spacing:1px; text-transform:uppercase; white-space:nowrap; cursor:pointer; }
  .mmx-guide-mobile::before { content:""; position:absolute; left:0; right:0; top:-13.5px; bottom:-14.5px; }
  header.mmx-header.os-navigation-controls > .nav-toggle { margin-left:0 !important; }
  .mmx-header { gap:6px; }
  .mmx-header .logo { gap:6px; }
  /* One element type more specific than the shared .nav shell's 24 px phone logo, which is injected
     after this file: the 320 px row keeps its measured 20 px mark. */
  header.mmx-header .logo > svg { width:20px; height:20px; }
  .mmx-header .logo-text { font-size:12px; letter-spacing:1px; }
}
@media(prefers-reduced-motion:reduce) { .mmx-guide-highlight { transition:none; } }

/* フォボスラボ: a readable 44 px button (12 px name) and its short visible note (11 px, the size of the
   rail's stage names) beside it, or under it in a narrow panel. The return note stays for screen
   readers. No new panel; it follows the lead facts in the sheet. */
.ctx-heading .lab-link { flex:0 1 auto; margin:0; }
.lab-link .secondary-btn { flex:0 0 auto; min-height:44px; padding:0 14px; font-size:12px; line-height:1.3; letter-spacing:0.04em; color:#f0bc7c; border-color:rgba(240,188,124,.45); }

.ctx-story > .lab-link { order:-1; margin:6px 0; }

/* Simplified Chinese (html lang="zh"): Noto Sans JP is a Japanese font and has no glyphs for many
   simplified characters (and draws shared ones in Japanese forms), so Chinese text uses the site's own
   Noto Sans SC first, the family GS Planner requests for Chinese, with Noto Sans JP behind it. Only
   these zh rules name it, so Japanese and English pages render and download exactly as before. The
   header GUIDE keeps GS Planner's own families (指南 is drawn alike in both). */
:root:lang(zh) {
  --prose: "Noto Sans SC", "Noto Sans JP", "IBM Plex Mono", sans-serif;
  --mono: "IBM Plex Mono", "Noto Sans SC", "Noto Sans JP", monospace;
  --head: Orbitron, "Noto Sans SC", "Noto Sans JP", sans-serif;
}
:root:lang(zh), :lang(zh) body, :lang(zh) .story-label { font-family: "IBM Plex Mono", "Noto Sans SC", "Noto Sans JP", monospace; }
:lang(zh) .ctx-title, :lang(zh) .journey-title { font-family: Orbitron, "Noto Sans SC", "Noto Sans JP", sans-serif; }


/* On narrow reading panels use ordinary line filling: WebKit's paragraph-wide
   pretty layout can leave a large right-hand gap in these short explanations.
   Keep one shrinkable full-width track for every journey stage and language. */
@media (max-width: 720px) and (orientation: portrait), (max-height: 520px) and (orientation: landscape) {
  .ctx-story { min-width: 0; grid-template-columns: minmax(0, 1fr); }
  .story-section { min-width: 0; }
  .story-text { width: 100%; max-width: none; white-space: normal; text-wrap: wrap; }
}
@media (max-width: 720px) and (orientation: portrait) {
  /* Let the expanded sheet heading scroll with its contents instead of covering
     a partly visible journey-progress row. The global navigation stays fixed. */
  .context-panel.is-expanded .ctx-head { position: static; }
}
