/*
 * TerraGlide interface.
 *
 * Flat panels, one-pixel borders, system type, small radii. No gradients, no
 * glow, no pill shapes. The imagery is the thing worth looking at, so the UI
 * behaves like instrument labelling around it.
 */

:root {
  /* Warm neutral greys rather than blue-black, so the interface reads as
     printed labelling next to the imagery instead of a dark-mode dashboard. */
  --bg: #14140f;
  --panel: rgba(28, 27, 24, 0.72);
  --panel-solid: rgba(28, 27, 24, 0.94);
  --panel-raised: rgba(46, 44, 40, 0.9);
  --line: rgba(232, 228, 216, 0.14);
  --line-strong: rgba(232, 228, 216, 0.26);
  --text: #f0ece2;
  --text-dim: #b8b2a4;
  --text-faint: #8a8478;
  --accent: #d8c48a;
  --accent-dim: #8d8266;
  --good: #9db884;
  --warn: #d4ab6a;
  --bad: #cf8f83;
  --radius: 2px;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* {
  box-sizing: border-box;
}

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

#app {
  position: relative;
  width: 100%;
  height: 100%;
}

#viewport {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  cursor: crosshair;
}

#viewport.dragging {
  cursor: grabbing;
}

#viewport.pan {
  cursor: grab;
}

#ui {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/*
 * Overlays must not eat clicks meant for the world. The HUD and the touch layer
 * cover the whole screen, so they stay transparent to the pointer and only the
 * pieces you can actually press take events back. Getting this wrong made every
 * click on the view do nothing at all.
 */
#ui > .panel,
#ui > .minimap {
  pointer-events: auto;
}

#ui > .hud,
#ui > .touch {
  pointer-events: none;
}

/* ---------- boot ---------- */

#boot {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: #0d0f12;
  z-index: 50;
  transition: opacity 0.4s ease;
}

#boot.done {
  opacity: 0;
  pointer-events: none;
}

.boot-inner {
  text-align: center;
}

.boot-inner h1 {
  margin: 0 0 8px;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

#boot-status {
  margin: 0;
  color: var(--text-dim);
  font-family: var(--mono);
  font-size: 12px;
}

/* ---------- common ---------- */

button {
  font: inherit;
  color: var(--text);
  background: var(--panel-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 10px;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}

button:hover {
  border-color: var(--line-strong);
  background: #20252c;
}

button:active {
  background: #171b21;
}

button.primary {
  border-color: rgba(216, 196, 138, 0.55);
  color: #f4ead0;
  background: rgba(74, 66, 46, 0.72);
}

button.mini {
  padding: 1px 5px;
  font-size: 11px;
  color: var(--text-dim);
  background: transparent;
}

button.link {
  background: none;
  border: none;
  padding: 0;
  text-align: left;
  color: var(--text);
}

button.link:hover {
  color: #fff;
  background: none;
}

button.danger {
  border-color: rgba(201, 138, 128, 0.45);
  color: #e5b6ae;
}

kbd {
  display: inline-block;
  margin-left: 6px;
  padding: 0 4px;
  min-width: 16px;
  font-family: var(--mono);
  font-size: 10px;
  line-height: 15px;
  text-align: center;
  color: var(--text-dim);
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--line);
  border-radius: 2px;
}

input[type='text'],
input[type='password'],
input[type='search'],
select {
  font: inherit;
  color: var(--text);
  background: #0f1216;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 4px 6px;
  min-width: 0;
}

input[type='range'] {
  width: 100%;
  accent-color: var(--accent);
}

input[type='checkbox'] {
  accent-color: var(--accent);
  width: 15px;
  height: 15px;
}

.muted {
  color: var(--text-faint);
}

.panel-block {
  background: var(--panel);
  border: none;
  border-left: 2px solid rgba(216, 196, 138, 0.5);
  border-radius: 0;
  padding: 6px 10px;
  backdrop-filter: blur(4px);
}

/* ---------- hud ---------- */

.hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.hud.hidden {
  opacity: 0;
  pointer-events: none;
}

.hud-topleft,
.hud-rail,
.hud-bottomleft,
.hud-hotbar,
.hud-bottomright,
.hud-toasts,
.hud-debug {
  pointer-events: auto;
}

/* The compass and crosshair are read-only and span the view; never clickable. */
.hud-compass,
.hud-crosshair {
  pointer-events: none;
}

.hud-topleft {
  position: absolute;
  top: 12px;
  left: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 320px;
}

.climate {
  min-width: 210px;
}

.climate-main {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.climate-main strong {
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.climate-main span {
  color: var(--text-dim);
}

.climate-sub {
  margin-top: 1px;
  font-size: 11px;
  color: var(--text-faint);
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  max-width: 340px;
}

.toolbar button {
  padding: 4px 8px;
}

.toolbar button {
  font-size: 12px;
}

.hud-compass {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  width: 300px;
  height: 20px;
  overflow: hidden;
  background: linear-gradient(
    to right,
    rgba(28, 27, 24, 0) 0%,
    rgba(28, 27, 24, 0.7) 18%,
    rgba(28, 27, 24, 0.7) 82%,
    rgba(28, 27, 24, 0) 100%
  );
  border: none;
}

.compass-strip {
  position: absolute;
  top: 0;
  height: 100%;
  white-space: nowrap;
  will-change: transform;
}

.compass-strip .tick {
  position: absolute;
  top: 4px;
  width: 1px;
  height: 5px;
  background: var(--line-strong);
  font-size: 10px;
  color: var(--text-dim);
  text-align: center;
}

.compass-strip .tick.major {
  height: 8px;
  background: var(--text-faint);
}

.compass-strip .tick:not(:empty) {
  width: 20px;
  margin-left: -10px;
  background: none;
  padding-top: 7px;
}

/*
 * Waypoint labels, pinned to the foot of each beam.
 *
 * Never clickable and never in the way: the beam is the thing you steer by and
 * the label only says what it is.
 */
.hud-beacons {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.beacon-label {
  position: absolute;
  transform: translate(-50%, -100%);
  margin-top: -8px;
  padding: 3px 7px;
  border-radius: 3px;
  border-left: 2px solid var(--beacon, #c8b98f);
  background: rgba(12, 14, 18, 0.72);
  white-space: nowrap;
  font-size: 11px;
  line-height: 1.35;
  text-align: left;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}

.beacon-label b {
  display: block;
  font-weight: 600;
  color: var(--beacon, #c8b98f);
}

.beacon-label span {
  display: block;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

/* The exact bearing, sitting under the needle where an instrument puts it. */
.compass-heading {
  position: absolute;
  top: 100%;
  left: 150px;
  transform: translateX(-50%);
  margin-top: 2px;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: var(--accent);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  pointer-events: none;
}

.compass-needle {
  position: absolute;
  top: 0;
  left: 150px;
  width: 1px;
  height: 100%;
  background: var(--accent);
}

.hud-crosshair {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.hud-crosshair i {
  display: block;
  width: 3px;
  height: 3px;
  background: rgba(255, 255, 255, 0.85);
  outline: 1px solid rgba(0, 0, 0, 0.55);
}

.hud-rail {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 168px;
}

.gauge {
  background: var(--panel);
  border: none;
  border-left: 2px solid var(--line-strong);
  padding: 4px 8px;
  backdrop-filter: blur(4px);
}

.gauge label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* The key that works the gauge, beside its name and updated when you rebind. */
.gauge label kbd {
  margin-left: auto;
  letter-spacing: 0;
  text-transform: none;
}

.gauge label kbd + kbd {
  margin-left: 0;
}

.gauge .bar {
  height: 4px;
  margin: 4px 0 3px;
  background: rgba(255, 255, 255, 0.09);
  overflow: hidden;
}

.gauge .bar i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--text-dim);
}

.gauge span {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-dim);
}

.gauge[data-state='active'] .bar i {
  background: var(--good);
}

.gauge[data-state='cooling'] .bar i {
  background: var(--warn);
}

.gauge[data-state='broken'] .bar i {
  background: var(--bad);
}

.hud-bottomleft {
  position: absolute;
  left: 12px;
  bottom: 12px;
  /* Narrow enough to clear the centred hotbar on a 1280px window. */
  max-width: 282px;
}

.location-address {
  font-size: 14px;
  font-weight: 500;
}

.location-coords {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-dim);
}

.location-figures {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-faint);
}

.hud-hotbar {
  position: absolute;
  bottom: 12px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 3px;
}

.hud-hotbar .slot {
  position: relative;
  display: flex;
  align-items: center;
  gap: 7px;
  /* Wide enough for the longest thing the meta line ever says: a burn time,
     a separator and a three-figure speed with its unit. It was 118px, which
     was right when the line read "hold to fly" and truncated to "0.8s · 120 …"
     the moment it started carrying real numbers. */
  width: 134px;
  height: 50px;
  padding: 4px 8px 5px;
  text-align: left;
  background: var(--panel);
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  backdrop-filter: blur(4px);
}

/* The underline takes the rocket's own colour rather than the generic accent,
   so the lit slot, its icon and the thing in your hand all agree. */
.hud-hotbar .slot.selected {
  border-bottom-color: var(--rocket, var(--accent));
  background: rgba(46, 44, 40, 0.92);
}

.slot-icon {
  flex: none;
  width: 21px;
  height: 21px;
  opacity: 0.55;
  transition: opacity 120ms linear;
}

.hud-hotbar .slot.selected .slot-icon {
  opacity: 1;
}

.slot-text {
  flex: 1;
  min-width: 0;
}

.slot-key {
  display: block;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-faint);
}

.slot-label,
.slot-meta {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.slot-label {
  font-size: 11.5px;
  line-height: 1.2;
}

.slot-meta {
  font-family: var(--mono);
  font-size: 9px;
  color: var(--text-faint);
}

.hud-bottomright {
  position: absolute;
  right: 6px;
  /* Right into the corner and small: it is a credit line and a status line,
     not something you read while flying. */
  bottom: 4px;
  text-align: right;
  max-width: 260px;
  opacity: 0.85;
  /* Small and faint is fine; illegible is not. Pale grey text with nothing
     behind it disappears completely over pale ground — over the tan hills
     north-east of Santo Antônio do Itambé the provider credits could not be
     read at all, and a credit you cannot read is not a credit. A shadow keeps
     the corner uncluttered and keeps the line separate from whatever is
     underneath it, which a panel background would not do as quietly. */
  text-shadow:
    0 1px 2px rgba(18, 17, 14, 0.9),
    0 0 5px rgba(18, 17, 14, 0.7);
}

.status-line {
  font-family: var(--mono);
  font-size: 9px;
  line-height: 1.35;
  color: var(--text-dim);
}

.attribution {
  font-size: 9px;
  line-height: 1.35;
  color: var(--text-faint);
}

.hud-debug {
  position: absolute;
  top: 44px;
  right: 12px;
  padding: 6px 8px;
  white-space: pre;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-dim);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.hud-toasts {
  position: absolute;
  bottom: 74px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.toast {
  padding: 5px 10px;
  background: var(--panel-solid);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 12px;
  transition: opacity 0.3s ease;
}

.toast-warn {
  border-color: rgba(203, 168, 106, 0.5);
}

.toast-bad {
  border-color: rgba(201, 138, 128, 0.5);
}

.toast.leaving {
  opacity: 0;
}

/* ---------- minimap ---------- */

.minimap {
  position: absolute;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: #0f1114;
}

/*
 * The shape of it. The canvas is square and `overflow: hidden` on the frame is
 * what cuts it, so every shape here is one radius — no second element, no mask,
 * and the compass and scale bar inside keep working unchanged.
 */
.minimap[data-shape='circle'] {
  border-radius: 50%;
}

/* A superellipse is not expressible as a border-radius, so this is the closest
   honest approximation: a very large radius that still leaves flat sides. */
.minimap[data-shape='squircle'] {
  border-radius: 28%;
}

.minimap[data-shape='square'] {
  border-radius: 0;
}

.minimap[data-corner='top-right'] {
  top: 12px;
  right: 12px;
}

.minimap[data-corner='top-left'] {
  top: 12px;
  left: 344px;
}

.minimap[data-corner='bottom-right'] {
  bottom: 12px;
  right: 12px;
}

.minimap[data-corner='bottom-left'] {
  bottom: 74px;
  left: 12px;
}

.minimap-canvas {
  display: block;
  cursor: pointer;
}

.minimap-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  font-size: 10px;
  color: var(--text-dim);
}

.minimap-scale {
  position: absolute;
  left: 6px;
  bottom: 5px;
  display: flex;
  align-items: center;
  gap: 5px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}

.minimap-scale i {
  display: block;
  height: 3px;
  border: 1px solid rgba(255, 255, 255, 0.75);
  border-top: none;
}

.minimap-zoom {
  position: absolute;
  right: 4px;
  top: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  pointer-events: auto;
}

.minimap-zoom button {
  width: 20px;
  height: 20px;
  padding: 0;
  line-height: 1;
  font-size: 13px;
}

/* The plus and minus are drawn, not typed.
   They used to be the characters "+" and U+2212 MINUS SIGN, and a glyph that is
   the entire content of a small button is the most visible thing there is to
   get wrong: a font set without U+2212 — which some Android and embedded
   configurations are — draws an empty box where the zoom-out control should be.
   Two rectangles need no font at all and are identical on every device. The
   accessible name is on the button itself, so nothing is lost by the label
   being empty. */
.map-zoom-glyph button {
  position: relative;
}

.map-zoom-glyph button::before,
.map-zoom-glyph button::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  background: currentColor;
  transform: translate(-50%, -50%);
}

.map-zoom-glyph button::before {
  width: 52%;
  height: 2px;
  border-radius: 1px;
}

/* The upright bar of the plus. The minus button has none. */
.map-zoom-glyph button[data-zoom='1']::after {
  width: 2px;
  height: 52%;
  border-radius: 1px;
}

.minimap-hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -18px;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  pointer-events: none;
}

.minimap-hint kbd {
  margin-right: 4px;
}

.minimap-readout {
  position: absolute;
  right: 6px;
  bottom: 5px;
  font-family: var(--mono);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}

/* ---------- panels ---------- */

.panel {
  position: absolute;
  background: var(--panel-solid);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  z-index: 20;
}

/* `display: flex` above would otherwise beat the browser's [hidden] rule. */
.panel[hidden],
.hud [hidden] {
  display: none;
}

.panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
}

.panel-head h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.panel-close {
  margin-left: auto;
}

/* settings */

.settings {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(860px, 94vw);
  height: min(660px, 92vh);
}

.settings-body {
  display: grid;
  grid-template-columns: 148px 1fr;
  min-height: 0;
  flex: 1;
}

.settings-nav {
  display: flex;
  flex-direction: column;
  padding: 8px;
  gap: 2px;
  border-right: 1px solid var(--line);
  overflow-y: auto;
}

.settings-nav button {
  text-align: left;
  background: none;
  border: none;
  color: var(--text-dim);
}

.settings-nav button.active {
  background: var(--panel-raised);
  border: 1px solid var(--line);
  color: var(--text);
}

.settings-content {
  padding: 12px 14px;
  overflow-y: auto;
}

.settings-intro {
  margin: 0 0 12px;
  color: var(--text-dim);
  max-width: 62ch;
}

.settings-content h3 {
  margin: 18px 0 6px;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.settings-content h4 {
  margin: 14px 0 4px;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.field {
  display: grid;
  grid-template-columns: 220px 1fr;
  align-items: center;
  gap: 8px 12px;
  padding: 6px 0;
  border-bottom: 1px solid rgba(226, 232, 240, 0.06);
}

.field label {
  color: var(--text);
}

.field small {
  grid-column: 2;
  color: var(--text-faint);
  font-size: 11px;
}

.field-toggle input {
  justify-self: start;
}

.field .range {
  display: flex;
  align-items: center;
  gap: 10px;
}

.field .range output {
  min-width: 74px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-dim);
  text-align: right;
}

.binds {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 4px 16px;
}

.bind {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 2px 0;
}

.bind span {
  flex: 1;
  color: var(--text-dim);
}

.bind-key {
  min-width: 76px;
  font-family: var(--mono);
  font-size: 11px;
}

.bind-key.capturing {
  border-color: var(--accent);
  color: var(--accent);
}

.settings-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 12px 0;
}

.file-button {
  display: inline-block;
  padding: 5px 9px;
  background: var(--panel-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
}

/* world map */

.worldmap {
  top: 24px;
  left: 24px;
  right: 24px;
  bottom: 24px;
}

.worldmap-search {
  display: flex;
  gap: 4px;
}

.worldmap-search input {
  width: 240px;
}

.worldmap-body {
  display: grid;
  grid-template-columns: 1fr 268px;
  flex: 1;
  min-height: 0;
}

.worldmap-canvas-wrap {
  position: relative;
  min-width: 0;
  background: #0f1114;
}

.worldmap-canvas-wrap canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
}

.worldmap-canvas-wrap canvas.dragging {
  cursor: grabbing;
}

/* A waypoint under the pointer can be picked up and moved, so say so before
   the press rather than after it. */
.worldmap-canvas-wrap canvas.over-waypoint {
  cursor: move;
}

.worldmap-canvas-wrap canvas.dragging-waypoint {
  cursor: grabbing;
}

.worldmap-hud {
  position: absolute;
  left: 8px;
  bottom: 8px;
  display: flex;
  gap: 14px;
  align-items: center;
  padding: 3px 8px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-dim);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.worldmap-scale {
  display: flex;
  align-items: center;
  gap: 6px;
}

.worldmap-scale i {
  display: block;
  height: 4px;
  border: 1px solid var(--line-strong);
  border-top: none;
}

.worldmap-zoom {
  position: absolute;
  right: 8px;
  top: 8px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.worldmap-zoom button {
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 15px;
}

.worldmap-results {
  position: absolute;
  top: 8px;
  left: 8px;
  margin: 0;
  padding: 4px;
  list-style: none;
  width: min(420px, 60%);
  max-height: 240px;
  overflow-y: auto;
  background: var(--panel-solid);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.worldmap-results li button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 4px 6px;
  font-size: 12px;
}

.worldmap-results li button:hover {
  background: var(--panel-raised);
}

.worldmap-side {
  border-left: 1px solid var(--line);
  padding: 10px;
  overflow-y: auto;
}

.worldmap-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.worldmap-stats {
  margin-top: 12px;
  font-size: 12px;
}

.worldmap-stats div {
  display: flex;
  justify-content: space-between;
  padding: 2px 0;
  border-bottom: 1px solid rgba(226, 232, 240, 0.06);
  color: var(--text-dim);
}

.worldmap-stats strong {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.worldmap-side h3 {
  margin: 14px 0 4px;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.worldmap-list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 12px;
}

.worldmap-list li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 0;
  border-bottom: 1px solid rgba(226, 232, 240, 0.06);
}

.worldmap-list li span.muted {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 10px;
}

.worldmap-list i {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  vertical-align: -1px;
}

.worldmap-tick {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 4px;
  color: var(--text-dim);
  cursor: pointer;
}

.worldmap-danger {
  margin-top: 16px;
}

/* help */

.help {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(680px, 94vw);
  max-height: 88vh;
}

.help-body {
  padding: 12px 14px;
  overflow-y: auto;
}

.help-lead {
  margin-top: 0;
  color: var(--text);
  max-width: 64ch;
}

.help-mouse {
  padding: 6px 8px;
  background: var(--panel-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text-dim);
}

.help-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 2px 18px;
  margin: 12px 0;
}

.help-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 2px 0;
  color: var(--text-dim);
}

.help-keys {
  flex: 0 0 108px;
}

.help-keys kbd {
  margin: 0 2px 0 0;
}

.help-note {
  margin-bottom: 0;
  color: var(--text-faint);
  max-width: 68ch;
}

/* cheats */

.cheats {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(620px, 94vw);
  max-height: 88vh;
  border-left: 2px solid var(--warn);
}

.cheats-body {
  padding: 12px 14px;
  overflow-y: auto;
}

.cheats .field {
  grid-template-columns: 190px 1fr;
}

.cheat-goto {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 8px 0;
}

.cheat-goto input {
  flex: 1 1 220px;
}

.cheat-status {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--warn);
  padding: 4px 0;
}

.cheat-flag {
  background: var(--panel);
  border-left: 2px solid var(--warn);
  padding: 4px 8px;
  backdrop-filter: blur(4px);
}

.cheat-flag label {
  display: block;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--warn);
}

.cheat-flag span,
.cheat-flag em {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  font-style: normal;
  color: var(--text-dim);
  word-break: break-word;
}

.cheat-flag em:empty {
  display: none;
}

@media (max-width: 900px) {
  /* Narrow, not gone.
   *
   * The rail and the compass used to be switched off outright below nine
   * hundred pixels, which is any phone held upright and plenty of ordinary
   * windows — and the rail is where the speed-mode meter, the air you have
   * left underwater and your height all live. "The boost meter is sometimes
   * not visible" was this: not a bug in the meter, a stylesheet deciding you
   * did not need it. Everything readable stays; only the space it takes goes. */
  .hud-rail {
    width: 116px;
    gap: 5px;
    font-size: 10px;
  }

  .gauge label kbd {
    display: none;
  }

  .hud-compass {
    width: 220px;
  }

  .worldmap-body {
    grid-template-columns: 1fr;
  }

  .worldmap-side {
    display: none;
  }

  .settings-body {
    grid-template-columns: 110px 1fr;
  }
}

/* ---------- touch ---------- */

.touch {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
}

.touch-stick {
  position: absolute;
  left: 22px;
  bottom: 22px;
  width: 132px;
  height: 132px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: rgba(28, 27, 24, 0.4);
  pointer-events: auto;
  touch-action: none;
}

.touch-stick i {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 52px;
  height: 52px;
  margin: -26px 0 0 -26px;
  border-radius: 50%;
  background: rgba(240, 236, 226, 0.32);
  border: 1px solid var(--line-strong);
}

.touch-buttons {
  position: absolute;
  right: 16px;
  bottom: 16px;
  display: grid;
  grid-template-columns: repeat(2, 88px);
  gap: 8px;
  pointer-events: auto;
}

.touch-buttons button {
  height: 52px;
  font-size: 13px;
  background: rgba(28, 27, 24, 0.72);
  touch-action: none;
}

.touch-buttons button.down {
  background: rgba(74, 66, 46, 0.85);
  border-color: var(--accent);
}

/* On a touch screen the hotbar and rail would sit under your thumbs. */
body.touch-active .hud-rail {
  display: none;
}

body.touch-active .hud-hotbar {
  bottom: auto;
  top: 40px;
}

/* A narrow touch screen puts the hotbar above the thumbs, not under them.

   It used to go across the top for that, and on a phone the top is where the
   minimap is. Measured at 390x844 the two overlapped by 133x44 px — which hid
   rockets four and five completely, so on a phone you could not select them at
   all — and at 360 wide the bar also ran eleven pixels off the left edge.
   
   So it goes back along the bottom, in the band above the one the stick and
   the buttons reserve for themselves: clear of both thumbs and of the minimap.
   The slots are sized to the window rather than to a fixed 74px, because five
   of anything fixed will eventually not fit. */
@media (max-width: 900px) {
  body.touch-active .hud-topleft {
    top: 40px;
  }

  body.touch-active .hud-hotbar {
    top: auto;
    /* The stick is 132px tall and sits 22px up, so its top is at 154. */
    bottom: 182px;
  }

  body.touch-active .hud-hotbar .slot {
    width: min(74px, calc((100vw - 28px) / 5));
    height: 44px;
  }

  /* Above the hotbar, which is above the controls. */
  body.touch-active .hud-bottomleft {
    bottom: 234px;
  }

  /* 74px is an icon and a keycap wide. The name and the burn-and-speed line
     do not fit and were being cut off mid-word; on a touch screen you pick a
     rocket by its colour anyway. */
  body.touch-active .hud-hotbar .slot .slot-label,
  body.touch-active .hud-hotbar .slot .slot-meta {
    display: none;
  }
}

/* Wide touch screens keep the hotbar along the bottom too, so the location
   panel clears both it and the controls. Narrow ones override this above. */
body.touch-active .hud-bottomleft {
  bottom: 234px;
}

body.touch-active .hud-crosshair {
  display: none;
}


/* ---------------------------------------------------------------- short windows

   A phone on its side is 390px tall, and at their ordinary sizes the four
   things that want the left edge do not fit in that: the climate and toolbar
   block is 122px, the location panel 111, the hotbar 44 and the stick 154.
   That is 431px of content in 390px of screen, and what it did instead of
   overflowing was overlap — the location panel sat on top of the toolbar,
   measured at 282x91px of collision.

   So on a short screen everything on that edge gets smaller: the climate loses
   its second line, the toolbar its padding, the location panel its figures
   row, and the stick and buttons come down to a size that still suits a thumb
   on a screen this short. Nothing is hidden that you cannot get at another way
   — the figures are on the HUD readout and the climate detail is in the
   forecast.
*/
@media (max-height: 460px) {
  .climate-sub {
    display: none;
  }

  .toolbar button {
    padding: 4px 6px;
    font-size: 10.5px;
  }

  .location-figures {
    display: none;
  }

  .location-address {
    font-size: 12px;
  }

  .touch-stick {
    width: 92px;
    height: 92px;
    left: 14px;
    bottom: 12px;
  }

  .touch-stick i {
    width: 38px;
    height: 38px;
    margin: -19px 0 0 -19px;
  }

  .touch-buttons {
    grid-template-columns: repeat(2, 74px);
    gap: 6px;
    right: 12px;
    bottom: 12px;
  }

  .touch-buttons button {
    height: 40px;
    font-size: 12px;
  }

  /* Stick tops out at 104; hotbar above it; location panel above that. */
  body.touch-active .hud-hotbar {
    bottom: 112px;
  }

  body.touch-active .hud-bottomleft {
    bottom: 164px;
  }

  body.touch-active .hud {
    padding-bottom: 164px;
  }
}

/* ---------------------------------------------------------------- narrow windows

   The hotbar is five 134px slots plus gaps — a shade over 680px — and it is
   centred. The location panel and the attribution live in the bottom corners
   on the same row, so once the window drops below about 1180px the three
   collide and the hotbar's panel background covers the text underneath.

   That is a real case, not a corner one: a Chromebook in a split window, a
   small laptop, a phone in landscape. Below the threshold the two corner
   blocks step up above the hotbar rather than sliding under it.
*/
@media (max-width: 1180px) {
  .hud-bottomleft,
  .hud-bottomright {
    bottom: 68px;
  }
}

/* ---------------------------------------------------------------- phones

   Under about seven hundred pixels there is no longer a left half and a right
   half to put things in: the toolbar reaches the minimap across the top, and
   the location panel reaches the credit line across the bottom. Both corners
   stop being corners and stack instead — the credit and status line sit above
   the location panel, which sits above the hotbar, and the top-left block is
   held clear of whatever width the minimap has settled on.
*/
@media (max-width: 700px) {
  .hud-topleft {
    /* The minimap caps itself at a third of the window; this is the rest of
       the row, less the two gutters and a gap between them. */
    max-width: calc(66% - 36px);
  }

  .climate {
    min-width: 0;
  }

  .toolbar {
    gap: 4px;
  }

  .toolbar button {
    padding: 5px 7px;
    font-size: 11px;
  }

  /* The two bottom blocks stop being corners and become a column.
     Stacking them by hand needs a number for how tall the location panel is,
     and it is as tall as its address happens to be — so they are laid out
     instead. Everything else in the HUD is absolutely positioned and stays
     exactly where it was; only these two join the flow. */
  .hud {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    /* The hotbar keeps its place along the bottom; this is its row. */
    padding-bottom: 66px;
    gap: 6px;
  }

  .hud-bottomleft,
  .hud-bottomright {
    position: static;
    margin: 0 12px;
    max-width: none;
    text-align: left;
  }

  /* Credit and status above, location below, whatever the markup order. */
  .hud-bottomright {
    order: 1;
  }

  .hud-bottomleft {
    order: 2;
  }

  /* The controls' own band, plus the hotbar's row above it, so the two blocks
     that join the flow on a phone stack clear of both. */
  body.touch-active .hud {
    padding-bottom: 234px;
  }
}

/* Narrower still and the hotbar itself will not fit across the window, so the
   slots shed their padding and then their labels rather than overflowing. Five
   134px slots and their gaps come to 682px, so the labels have to go before
   the window does, not after. */
@media (max-width: 720px) {
  .hud-hotbar .slot {
    width: 62px;
    padding: 4px 5px 5px;
    gap: 4px;
  }

  .hud-hotbar .slot .slot-label,
  .hud-hotbar .slot .slot-meta {
    display: none;
  }

  .slot-icon {
    width: 18px;
    height: 18px;
  }
}

/* The provider test: one row per provider, coloured by what came back. */
.field-action button {
  justify-self: start;
}

.provider-test {
  grid-column: 2;
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  display: grid;
  gap: 2px;
  font-size: 11px;
}

.provider-test li {
  display: grid;
  grid-template-columns: 210px 1fr;
  gap: 10px;
  padding: 3px 6px;
  border-radius: 3px;
  background: rgba(226, 232, 240, 0.04);
}

.provider-test li span {
  color: var(--text-faint);
}

.provider-test .provider-ok b { color: #86efac; }
.provider-test .provider-error b { color: #fca5a5; }
.provider-test .provider-no-key b { color: #fcd34d; }
.provider-test .provider-no-cover b { color: #93c5fd; }
.provider-test .provider-checking b { color: var(--text-faint); }

/* "Test this one", beside the provider it tests. */
.field-test {
  grid-column: 2;
  justify-self: start;
  font-size: 11px;
  padding: 2px 8px;
}
