/* The viewer: a lights-out overlay that takes the whole window. Deliberately
   not the site's warm palette — the eye needs to adapt to the render, and
   every panel here sits over a picture.

   The chrome is an instrument face: near-opaque, square, unblurred. That is a
   measurement rather than a taste. A backdrop filter blurs what is behind a
   panel but does not darken it, so the type sits on the mean of whatever is
   back there — and behind this chrome is a sunlit cloud top as often as a
   night ocean. A frosted panel that reads beautifully over the ocean puts its
   subtitles at 1.1:1 over the cloud, where 4.5:1 is the floor; at 0.94 opaque
   the same text holds 6.2:1 against ANY sky. Panels that cannot be read are
   not a style. (Eight skins were built and measured against a sunlit cloud
   top and a night ocean; Thomas picked this one, 2026-08-14.) */

#viewer {
  position: fixed;
  inset: 0;
  z-index: 1005;
  background: #05070a;
  overflow: hidden;
  --panel-bg: rgba(6, 9, 13, 0.94);
  --panel-line: rgba(150, 172, 200, 0.22);
  --panel-radius: 2px;
  --control-radius: 2px;
  --panel-line-lit: rgba(170, 195, 225, 0.42);
  --ink: #d3dcea;
  --ink-bright: #f0f5fb;
  --ink-dim: #8a99ad;
  --hot: #e8834a;
  --ui-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --ui-mono: 'IBM Plex Mono', ui-monospace, Menlo, monospace;
  font-family: var(--ui-font);
  color: var(--ink);
}
#viewer[hidden] { display: none; }

/* --cursor-dart and --cursor-dart-click are defined once, in style.css's
   :root, and used from both files; index.html loads style.css first. */

/* The render keeps the PLAIN dart even though clicking it does something —
   it takes the pointer, and in fullscreen-minimap mode it also travels. The
   click variant is amber, and this element is the cloud: an amber pointer
   over sky is exactly what the earlier all-amber cursor got wrong. Every
   other clickable surface here sits on an opaque panel, so it can have the
   amber one. See the long note in style.css. */
#view {
  display: block;
  width: 100%;
  height: 100%;
  cursor: var(--cursor-dart);
}
#viewer.captured #view { cursor: none; }

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

/* --- panels --- */

.panel {
  position: absolute;
  background: var(--panel-bg);
  border: 1px solid var(--panel-line);
  border-radius: var(--panel-radius);
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.55;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
}
.panel h3 {
  margin: 0 0 10px;
  font-family: var(--ui-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-dim);
}
.panel h3:not(:first-child) { margin-top: 18px; }

/* --- the flight hint, shown until the mouse is taken --- */

#hint {
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  text-align: center;
  max-width: 40rem;
  pointer-events: none;
}
#hint b { color: var(--ink-bright); font-weight: 600; }
#hint .sub { color: var(--ink-dim); font-size: 12px; margin-top: 4px; }
/* Hidden while flying, and under an open menu — the menu states the
   controls and names the field itself, and a tall menu's bottom edge used
   to collide with the hint strip behind it. */
#viewer.captured #hint,
#viewer.menu-open #hint { display: none; }

/* --- corner readouts --- */

#stats {
  right: 14px;
  bottom: 12px;
  font-family: var(--ui-mono);
  font-size: 11.5px;
  line-height: 1.6;
  padding: 8px 11px;
  pointer-events: none;
  color: rgba(220, 232, 246, 0.9);
}
#stats .k { color: var(--ink-dim); }
#stats[hidden] { display: none; }

/* The speed chip sits in the corner the stats overlay would use, and the
   overlay steps up above it when both are on — speed is glanced at in
   flight, the overlay is read while parked. */
#speed {
  right: 14px;
  bottom: 12px;
  font-family: var(--ui-mono);
  font-size: 11.5px;
  line-height: 1.6;
  padding: 6px 10px;
  pointer-events: none;
  color: rgba(220, 232, 246, 0.9);
}
#speed[hidden] { display: none; }
/* #speed precedes #stats in the DOM precisely so this rule can exist: the
   chip keeps the corner (the tutorial points at that corner) and the overlay
   is the one that moves. */
#speed:not([hidden]) ~ #stats { bottom: 48px; }

#toolbar {
  right: 14px;
  top: 14px;
  display: flex;
  gap: 8px;
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  backdrop-filter: none;
}
/* Only while the mouse is free AND the menu is closed — see _syncChrome. */
#viewer.captured #toolbar,
#viewer.menu-open #toolbar { display: none; }

button.chip {
  font-family: var(--ui-font);
  font-size: 12px;
  color: var(--ink);
  background: var(--panel-bg);
  border: 1px solid var(--panel-line);
  border-radius: var(--control-radius);
  padding: 6px 12px;
  cursor: var(--cursor-dart-click);
  transition: border-color 0.15s ease, color 0.15s ease;
}
button.chip:hover { border-color: var(--panel-line-lit); color: var(--ink-bright); }
button.chip.on { border-color: var(--hot); color: var(--hot); }

/* --- the menu --- */

#menu {
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(30rem, calc(100vw - 3rem));
  max-height: calc(100vh - 4rem);
  overflow-y: auto;
  padding: 20px 22px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6);
}
#menu[hidden] { display: none; }
/* Image-tuning panels (quality, sun, terminal render) sit at the bottom so
   the view being adjusted stays visible above them — wider than the centred
   menu so the slider grid keeps the panel short enough not to scroll. */
#menu.dock-bottom {
  top: auto;
  bottom: 24px;
  transform: translateX(-50%);
  width: min(62rem, calc(100vw - 3rem));
  max-height: min(60vh, calc(100vh - 4rem));
}
/* The pause menu needs the width its two columns ask for; the one-column
   panels (controls, open-file questions, messages) stay narrow. */
#menu.wide { width: min(46rem, calc(100vw - 3rem)); }
.slider-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 26px;
}
@media (max-width: 760px) { .slider-grid { grid-template-columns: 1fr; } }

/* --- the pause menu's head, columns and foot --- */

.menu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.menu-head .menu-title { margin: 0; }

button.resume {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--ui-font);
  font-size: 13px;
  color: var(--ink-bright);
  background: rgba(232, 131, 74, 0.14);
  border: 1px solid var(--hot);
  border-radius: var(--control-radius);
  padding: 6px 12px;
  cursor: var(--cursor-dart-click);
  transition: background 0.15s ease;
}
button.resume:hover { background: rgba(232, 131, 74, 0.24); }
button.resume kbd {
  font-family: var(--ui-mono);
  font-size: 10.5px;
  color: var(--ink-dim);
  border: 1px solid var(--panel-line);
  border-radius: var(--control-radius);
  padding: 0 4px;
}
/* The tutorial owns Escape while it runs — it swallows the key with the menu
   up (see Tutorial.interceptEscape), so the hint would be advertising a
   shortcut that answers "not yet". The button itself keeps working: it is the
   walkthrough's own way back to the flight, and the hint is back the moment
   the walkthrough ends, without the menu being rebuilt. */
#viewer.tutorial button.resume kbd { display: none; }

.menu-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 22px;
  align-items: start;
}
.menu-cols .col > h3:first-child { margin-top: 0; }
/* Column-width sliders: the 10.5rem label of a full-width row leaves the
   track no room at all inside half a panel. */
.row.tight { display: block; padding: 5px 10px; }
.row.tight > label { display: block; flex: none; margin-bottom: 2px; }
.row.tight > .value { float: right; flex: none; }
.row.tight input[type="range"] { width: 100%; }

/* Leaving is neither column's business, so it sits under both — on its own,
   in the same left margin as every other item. */
.menu-foot { display: flex; align-items: center; gap: 16px; }
.menu-foot .item { width: auto; flex: none; }

@media (max-width: 760px) {
  .menu-cols { grid-template-columns: 1fr; }
  .menu-foot { display: block; }
}
/* The title is set in the mono face the readouts use, and every panel head
   is closed by one amber rule — the instrument's one piece of colour. */
#menu .menu-title {
  font-family: var(--ui-mono);
  font-size: 15px;
  letter-spacing: 0.02em;
  color: var(--ink-bright);
  margin: 0 0 2px;
}
.menu-head,
.panel-head {
  border-bottom: 1px solid var(--hot);
  padding-bottom: 10px;
  margin-bottom: 14px;
}
.panel-head h3 { margin-bottom: 4px; }
#menu .menu-sub {
  color: var(--ink-dim);
  font-size: 12px;
  margin: 0 0 16px;
}

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 5px 0;
}
.row > label {
  flex: 0 0 10.5rem;
  color: var(--ink-dim);
  font-size: 12.5px;
}
.row > .value {
  flex: 0 0 4.25rem;
  text-align: right;
  font-family: var(--ui-mono);
  font-size: 12px;
  color: var(--ink-bright);
}
.row input[type="range"] {
  flex: 1 1 auto;
  min-width: 0;
  accent-color: var(--hot);
  cursor: var(--cursor-dart-click);
}

.item {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--ui-font);
  font-size: 13.5px;
  color: var(--ink);
  background: none;
  border: 1px solid transparent;
  border-radius: var(--control-radius);
  padding: 8px 10px;
  cursor: var(--cursor-dart-click);
}
.item:hover { background: rgba(150, 175, 210, 0.10); border-color: var(--panel-line); }
.item .note { display: block; color: var(--ink-dim); font-size: 11.5px; margin-top: 2px; }
.item[disabled] { opacity: 0.42; cursor: var(--cursor-dart); }
.item[disabled]:hover { background: none; border-color: transparent; }

/* Two groups of buttons on one line — the quality tiers and the preview.
   A docked panel is meant to be looked past, so a row saved is sky. */
.seg-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
}
.seg-group { display: flex; align-items: center; gap: 10px; }
.seg-group h3 { margin: 0; }

.segmented { display: flex; gap: 6px; flex-wrap: wrap; }
.segmented button {
  font-family: var(--ui-font);
  font-size: 12px;
  color: var(--ink-dim);
  background: rgba(150, 175, 210, 0.07);
  border: 1px solid var(--panel-line);
  border-radius: var(--control-radius);
  padding: 5px 10px;
  cursor: var(--cursor-dart-click);
}
.segmented button:hover { color: var(--ink-bright); }
.segmented button.on {
  color: var(--ink-bright);
  border-color: var(--hot);
  background: rgba(232, 131, 74, 0.14);
}

/* A control small enough to live inside a slider's label, in the running
   text — the exposure row's auto toggle. Same box as .segmented button, one
   size down, so it reads as the same kind of thing. */
button.mini {
  font-family: var(--ui-mono);
  font-size: 11px;
  line-height: 1.35;
  color: var(--ink-dim);
  background: rgba(150, 175, 210, 0.07);
  border: 1px solid var(--panel-line);
  border-radius: var(--control-radius);
  padding: 0 5px;
  cursor: var(--cursor-dart-click);
}
button.mini:hover { color: var(--ink-bright); }
button.mini.on {
  color: var(--ink-bright);
  border-color: var(--hot);
  background: rgba(232, 131, 74, 0.14);
}

/* A labelled flip switch — the video panel's overlays toggle. Off greys the
   whole control, label included, so the state reads without the knob. */
button.flip {
  display: flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  padding: 0;
  font-family: var(--ui-font);
  font-size: 12px;
  color: var(--ink-bright);
  cursor: var(--cursor-dart-click);
}
.flip-track {
  flex: none;
  position: relative;
  width: 30px;
  height: 17px;
  border-radius: 9px;
  border: 1px solid var(--hot);
  background: rgba(232, 131, 74, 0.14);
  transition: background 0.15s, border-color 0.15s;
}
.flip-knob {
  position: absolute;
  top: 1px;
  left: 14px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--hot);
  transition: left 0.15s, background 0.15s;
}
button.flip:not(.on) {
  color: var(--ink-dim);
  opacity: 0.55;
}
button.flip:not(.on):hover { opacity: 0.8; }
button.flip:not(.on) .flip-track {
  border-color: var(--panel-line);
  background: rgba(150, 175, 210, 0.07);
}
button.flip:not(.on) .flip-knob {
  left: 1px;
  background: var(--ink-dim);
}

.segmented button[disabled] {
  opacity: 0.4;
  cursor: var(--cursor-dart);
}
.segmented button[disabled]:hover { color: var(--ink-dim); }

/* The mode toggle stands in the pause menu's title line, where the word
   "Paused" was, so it carries the title's weight. */
.segmented.mode button {
  font-family: var(--ui-mono);
  font-size: 12.5px;
  letter-spacing: 0.02em;
  padding: 5px 12px;
}

.divider { height: 1px; background: var(--panel-line); margin: 14px 0; }

/* --- the first-flight tutorial --- */

/* The prompts replace the hint strip for as long as they are up; the strip
   says the same six things at once, which is what the tutorial exists not to
   do. */
#viewer.tutorial #hint { display: none; }

.tutorial-box {
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(30rem, calc(100vw - 3rem));
  padding: 18px 20px;
  text-align: center;
}
/* `#ui > *` turns pointer events on for every child, and its ID beats a
   class — so the three tutorial layers have to say so at the same weight.
   The box must not eat the click that takes the mouse: step one is "click
   once", and the box is in the middle of the window. */
#ui > .tutorial-box,
#ui > .tutorial-spot,
#ui > .tutorial-spot-label { pointer-events: none; }
.tutorial-box[hidden] { display: none; }
/* A menu step: the box hangs under the menu, whose height it cannot know, so
   `top` is set per frame from the menu's own rect — see Tutorial._dockBox.
   The value here is only what it looks like for the frame before that runs. */
.tutorial-box.docked {
  top: 24px;
  transform: translateX(-50%);
}
/* And the menu makes room for it — without moving: the pause menu lives in the
   middle of the window and that is where someone who has hit Escape before
   expects to find it, tutorial or no tutorial. All that changes is the cap on
   its height, and only for a menu tall enough to reach the cap; every menu
   shorter than that sits exactly where it always does.
   Twice the reservation, because the menu is centred: half of every pixel it
   gives up goes to the top, where nothing needs it. --tutorial-dock is the
   measured height of the prompt plus its gaps, set by Tutorial._dockBox, since
   how tall a prompt is, is the step's business and not a number to guess at.
   :not(.dock-bottom) — the sun, quality and terminal panels dock to the bottom
   edge, and a menu step can leave one of them open. */
#viewer.tutorial #menu:not(.dock-bottom) {
  max-height: calc(100vh - 4rem - 2 * var(--tutorial-dock, 0px));
}
.tutorial-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-bright);
}
/* A step that is a list of cases rather than a paragraph. Left-aligned inside
   the centred box, because a centred bullet list is neither. */
.tutorial-list {
  margin: 10px 0 0;
  padding-left: 1.2em;
  text-align: left;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
}
.tutorial-list[hidden] { display: none; }
.tutorial-list li + li { margin-top: 6px; }
.tutorial-list li::marker { color: var(--hot); }
.tutorial-graphic { margin-top: 14px; }
.tutorial-graphic[hidden] { display: none; }

.keycaps { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.keycap-row { display: flex; gap: 5px; }
/* Ghosts: the shape of the keys, not a button anyone should try to press.
   Two rows inside each: the letter, and under it the direction it flies. */
.keycap {
  display: grid;
  place-items: center;
  row-gap: 1px;
  width: 34px;
  height: 34px;
  font-family: var(--ui-mono);
  font-size: 12px;
  color: var(--ink-dim);
  border: 1px solid var(--panel-line-lit);
  border-radius: var(--control-radius);
  background: rgba(150, 175, 210, 0.07);
}
/* Quieter than the letter and half its size: it is a gloss on the key, not a
   second key. */
.keycap .cap-arrow {
  font-size: 9px;
  line-height: 1;
  color: var(--ink-dim);
  opacity: 0.65;
}

/* Answers a click on a menu row the walkthrough is not ready for — see the
   interceptor in Tutorial._build. Amber, because it is the one line in the box
   that is about what just happened rather than about the step. */
.tutorial-note {
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--hot);
}
.tutorial-note[hidden] { display: none; }

.tutorial-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 16px;
}
.tutorial-actions > * { pointer-events: auto; }

button.tutorial-ok {
  font-family: var(--ui-font);
  font-size: 13px;
  color: var(--ink-bright);
  background: rgba(232, 131, 74, 0.14);
  border: 1px solid var(--hot);
  border-radius: var(--control-radius);
  padding: 5px 18px;
  cursor: var(--cursor-dart-click);
}
button.tutorial-ok:hover { background: rgba(232, 131, 74, 0.24); }
button.tutorial-ok[hidden] { display: none; }

button.tutorial-skip {
  font-family: var(--ui-font);
  font-size: 12px;
  color: var(--ink-dim);
  background: none;
  border: none;
  border-bottom: 1px solid var(--panel-line);
  padding: 2px 0;
  cursor: var(--cursor-dart-click);
}
button.tutorial-skip:hover { color: var(--ink); border-bottom-color: var(--hot); }

/* The dim is one enormous spread shadow on a transparent box, so the hole is
   the box itself — no four-rect layout to keep in agreement with a rect that
   moves every frame.
   The spread has to clear the window's far corner, and the number that decides
   that is not the distance to it. A spread shadow's own corners are rounded by
   the spread: the outer radius is (border-radius + spread), so the arc cuts
   about 0.29 × spread back in along the diagonal. At 100vmax and a ring in the
   bottom-right corner — which is exactly where the speed step puts it — that
   arc fell several hundred pixels inside the top-left corner of the window and
   left a bright undimmed wedge there. The ring can be at most a window
   diagonal (≈1.42 vmax) from a corner, so a spread of 200vmax puts the arc
   outside the viewport from anywhere on screen. */
.tutorial-spot {
  position: absolute;
  border: 1px solid var(--hot);
  border-radius: var(--control-radius);
  /* Glow first: a box-shadow list paints earliest on top, and behind the dim
     a 16 px halo is 16 px of dim. */
  box-shadow: 0 0 16px rgba(232, 131, 74, 0.45),
              0 0 0 200vmax rgba(3, 5, 8, 0.76);
  z-index: 2;
}
.tutorial-spot[hidden] { display: none; }
/* The one caption on the screen, in the corner the eye is least likely to be
   in: at 11.5px it was as quiet as the readout it is there to point out. */
.tutorial-spot-label {
  position: absolute;
  font-family: var(--ui-mono);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--hot);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.85);
  white-space: nowrap;
  z-index: 3;
}
.tutorial-spot-label[hidden] { display: none; }
/* Above the dim, or the prompt naming the thing is dimmer than the thing. */
.tutorial-box { z-index: 4; }

/* --- transient toast (screenshot saved, command copied, …) --- */

#toast {
  left: 50%;
  bottom: 92px;
  transform: translateX(-50%);
  padding: 9px 15px;
  font-size: 12.5px;
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
  white-space: pre-line;
  text-align: center;
}
#toast.show { opacity: 1; }

/* --- minimap / bird view --- */

#bird {
  left: 14px;
  top: 14px;
  padding: 0;
  overflow: hidden;
  line-height: 0;
}
#bird[hidden] { display: none; }
#bird canvas { display: block; }

/* --- ice-detection readout (I), centre bottom --- */

#ice-readout {
  position: absolute;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  font-family: var(--ui-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  padding: 7px 14px;
  border-radius: 6px;
  background: rgba(6, 14, 10, 0.55);
  border: 1px solid rgba(120, 255, 190, 0.25);
  color: rgba(190, 255, 225, 0.95);
  pointer-events: none;
  white-space: nowrap;
}
#ice-readout[hidden] { display: none; }
/* The pre-flight hint owns the same spot; while it shows, sit above it. */
#viewer:not(.captured) #ice-readout { bottom: 92px; }

/* --- progress while a field loads inside the viewer --- */

#viewer-progress {
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  min-width: 20rem;
  text-align: center;
}
#viewer-progress[hidden] { display: none; }
#viewer-progress .bar {
  height: 3px;
  background: rgba(150, 175, 210, 0.16);
  border-radius: 2px;
  margin-top: 10px;
  overflow: hidden;
}
#viewer-progress .bar span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--hot);
  transition: width 0.2s ease;
}
