/* Star Life Cycle
 *
 * The scene is space, so this sim runs a dark surface instead of the house
 * cream. That is a recorded exception to COLOR-3; the entry is in
 * simulations/ai-context/machine-verifiable-checks.md. Everything else, the
 * brand green, Roboto, and the whole info-dialog block below, is the house set.
 */

:root {
  --accent:       #004445;
  --accent-light: #006668;
  --focus-glow:   #FFD166;
  --ink:          #2C3E3E;
  --muted:        #5A6E6E;

  /* Space surfaces. Three steps of the same near-black blue so the panels read
     as one instrument rather than four windows. */
  --void:         #080B14;
  --panel:        #10151F;
  --panel-edge:   #3A4966;
  --panel-ink:    #E6EBF2;
  --panel-muted:  #93A1B5;
}

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
  overflow: hidden;
  background: var(--void);
  font-family: Roboto, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

[hidden] { display: none !important; }

#sim-app {
  display: flex;
  flex-direction: column;
  height: 100%;
}

#stage-panel {
  flex: 1;
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

#sim-canvas {
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
}

#sim-canvas:focus-visible {
  outline: 2px solid var(--focus-glow);
  outline-offset: -2px;
}

/* ── Accessibility ── */
.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;
}

/* ── Info dialog ──
   The dialog is Tuva Sims "chrome", so its accent is espresso (#5c4738),
   NOT the sim's green var(--accent). Header = purple with white text; active
   tab / h3 / footer button = purple; tabs/footer surface = #F8FBFB; body text =
   var(--ink). The shared toolbar stylesheet also injects these purple rules
   (scoped to #info-dialog) so existing green sims reskin automatically — keep
   this block in sync with it; do not redefine per sim. */
#info-dialog {
  border: none;
  border-radius: 12px;
  padding: 0;
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100vh - 80px);
  overflow: hidden;
  margin: auto;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.22);
  background: #ffffff;
}

#info-dialog::backdrop {
  background: rgba(30, 16, 48, 0.55);
}

.dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  background: #5c4738;
  color: #ffffff;
}

.dialog-header h2 {
  font-size: 16px;
  font-weight: 600;
}

#dialog-close-btn {
  background: transparent;
  border: none;
  color: #ffffff;
  font-size: 18px;
  cursor: pointer;
  width: 32px;
  height: 32px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

#dialog-close-btn:hover {
  background: rgba(255, 255, 255, 0.15);
}

#dialog-close-btn:focus-visible {
  outline: 3px solid var(--focus-glow);
  outline-offset: 2px;
}

.dialog-tabs {
  display: flex;
  border-bottom: 2px solid #E5EAE9;
  background: #F8FBFB;
}

.tab-btn {
  flex: 1;
  background: none;
  border: none;
  border-bottom: 3px solid transparent;
  margin-bottom: -2px;
  padding: 10px 0;
  font-family: Roboto, Arial, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.tab-btn:hover {
  color: #5c4738;
}

.tab-btn.active,
.tab-btn[aria-selected="true"] {
  color: #5c4738;
  border-bottom-color: #5c4738;
}

.tab-btn:focus-visible {
  outline: 3px solid var(--focus-glow);
  outline-offset: -3px;
}

.dialog-body {
  padding: 16px 20px;
  overflow-y: auto;
  max-height: calc(100vh - 240px);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.55;
}

.dialog-body h3 {
  font-size: 14px;
  font-weight: 600;
  color: #5c4738;
  margin-top: 14px;
  margin-bottom: 6px;
}

.dialog-body h3:first-child {
  margin-top: 0;
}

.dialog-body p {
  margin-bottom: 8px;
}

.dialog-body ul,
.dialog-body ol {
  padding-left: 20px;
  margin-bottom: 8px;
}

.dialog-body li {
  margin-bottom: 4px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  padding: 12px 20px;
  border-top: 1px solid #E5EAE9;
  background: #F8FBFB;
}

.dialog-close-footer {
  background: #5c4738;
  color: #ffffff;
  border: none;
  border-radius: 6px;
  padding: 8px 20px;
  font-family: Roboto, Arial, sans-serif;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
}

.dialog-close-footer:hover {
  background: #7d6c60;
}

.dialog-close-footer:focus-visible {
  outline: 3px solid var(--focus-glow);
  outline-offset: 2px;
}

/* ── Layout ──
   The scene is the frame. Everything else floats over it, so nothing takes a
   share of the height the star could have had. */
/* ── Stage and panel ──
   Two regions side by side. The stage is the scene and its timeline, and
   nothing is ever drawn over the scene (Ben); the panel is everything a student
   reads or sets. On a narrow screen they stack, stage first. */
#layout {
  position: absolute;
  inset: 0;
  display: flex;
  min-height: 0;
}

#stage {
  flex: 1 1 63%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px;
  min-height: 0;
}

#panel {
  flex: 0 0 37%;
  max-width: 520px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 8px 8px 0;
  min-height: 0;
}

#canvas-frame {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  border-radius: 10px;
  background: #04060C;
}

#sim-canvas { width: 100%; height: 100%; display: block; touch-action: none; }

#scene-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

#canvas-frame.is-booting #scene-overlay { visibility: hidden; }

/* A reminder that the orbits are a ruler. Muted, in the corner, and gone
   whenever no orbit is on screen. */
#orbit-note {
  position: absolute;
  right: 12px;
  bottom: 10px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(8, 11, 20, 0.7);
  color: var(--panel-muted);
  font-size: 12px;
  line-height: 1.4;
  transition: opacity 400ms;
}
#orbit-note[hidden] { display: block; opacity: 0; }

/* ── Scale bar ──
   A real scale bar: a measured length down the left edge, labelled with what it
   spans. It takes as much height as its round number needs and no more. The
   length is recomputed from the live camera every frame, never keyframed. */
#scale-bar {
  position: absolute;
  left: 14px;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}

#scale-bar-rule {
  position: relative;
  width: 11px;
  height: 100%;
}

/* The line and the ticks run the full height and fade out at both ends, so the
   ruler reads as part of the scene rather than as a box drawn around it. The
   tick spacing is set from the camera each frame. */
#scale-line,
#scale-ticks {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  -webkit-mask-image: linear-gradient(to bottom,
    transparent 0%, #000 17%, #000 83%, transparent 100%);
  mask-image: linear-gradient(to bottom,
    transparent 0%, #000 17%, #000 83%, transparent 100%);
}

#scale-line {
  width: 2px;
  background: rgba(230, 235, 242, 0.55);
}

#scale-ticks {
  width: 8px;
  /* One mark every --tick pixels, anchored to the middle of the frame so the
     highlighted gap always has a tick at each end. */
  background-image: repeating-linear-gradient(to bottom,
    rgba(230, 235, 242, 0.42) 0, rgba(230, 235, 242, 0.42) 1px,
    transparent 1px, transparent var(--tick, 90px));
  background-position: 0 var(--tick-offset, 0px);
}

/* The one interval the number is about. */
#scale-span {
  position: absolute;
  left: 0;
  width: 11px;
  height: var(--tick, 90px);
  top: 50%;
  transform: translateY(-50%);
  border-top: 2px solid rgba(230, 235, 242, 0.92);
  border-bottom: 2px solid rgba(230, 235, 242, 0.92);
  border-left: 2px solid rgba(230, 235, 242, 0.92);
}

/* Beside the middle tick, clear of whatever the top of the frame is doing. It
   carries its own ground for the same reason the ring labels do: it can end up
   over a supernova. Tabular figures so the number does not jitter sideways
   while it counts. */
#scale-bar-text {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--panel-ink);
  background: rgba(4, 6, 12, 0.78);
  padding: 2px 6px;
  border-radius: 4px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

#ring-labels { position: absolute; inset: 0; }

/* These sit over whatever the star is doing, and the brightest thing they can
   land on is the white core of a supernova. A text shadow is not a background:
   the contrast it gives depends on what is behind it. So the label carries its
   own ground, opaque enough that the worst case still clears 4.5:1. */
.ring-label {
  position: absolute;
  transform: translate(-50%, -50%);
  font-size: 12px;
  font-weight: 500;
  color: #A9CBEC;
  background: rgba(4, 6, 12, 0.78);
  padding: 1px 5px;
  border-radius: 4px;
  white-space: nowrap;
}

.ring-label.is-minor { color: #9FB3CC; }


.card-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--panel-muted);
}

.card-value {
  font-size: 12px;
  font-weight: 700;
  color: var(--panel-ink);
  white-space: nowrap;
}

/* A tapped element answers here rather than inside the drawing. */
#ledger-tip {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 8px;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(8, 11, 20, 0.94);
  border: 1px solid var(--panel-edge);
  color: var(--panel-ink);
  font-size: 12.5px;
  line-height: 1.45;
}

#ledger-tip[hidden] { display: none !important; }

/* ── Keyboard layer over the element table ── */
#kb-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
}

#kb-layer .kb-proxy {
  position: absolute;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  pointer-events: none;
  outline: none;
  color: transparent;
}

/* ── The moment bar ──
   The playhead has parked on a diamond and the clock on screen is free. Nothing
   advances until Continue. */
/* In the bottom stack rather than floating over it: a bar that overlapped the
   timeline hid the very diamond it had stopped on. */
/* The panel header: which star, and the three read-outs as tabs. */
/* The System card never grows with the panel; its body is the chooser, which
   takes its own height. The head is a button only between runs. */
#rcard-system { flex: none; }
#summary-btn:disabled { cursor: default; }
#summary-btn:disabled:hover { background: none; }
#summary-btn:disabled:hover .card-title { color: var(--panel-muted); }
#rcard-system.is-open .rcard-head { cursor: pointer; }

.card-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--panel-muted);
}


/* ── The moment card ──
   In the stage column, directly above the timeline, where the student is
   already looking (Ben): the scene shrinks a little to make room rather than
   being covered, and Continue sits beside the diamond it belongs to. It arrives
   with a short rise and a flash of its own accent so its arrival is felt while
   the eye is on the star. */
#moment-bar {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 11px 14px 11px 16px;
  border-radius: 10px;
  background: rgba(11, 15, 24, 0.95);
  border: 1px solid var(--focus-glow);
  animation: moment-arrive 520ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}

@keyframes moment-arrive {
  0%   { transform: translateY(14px); opacity: 0; box-shadow: 0 0 0 0 rgba(255, 209, 102, 0); }
  35%  { transform: none; opacity: 1; box-shadow: 0 0 0 6px rgba(255, 209, 102, 0.35); }
  100% { transform: none; opacity: 1; box-shadow: 0 0 0 0 rgba(255, 209, 102, 0); }
}

@media (prefers-reduced-motion: reduce) {
  #moment-bar { animation: none; }
}

#moment-main { display: flex; align-items: center; gap: 14px; }

/* The chooser: the System card's body. */
#setup-view {
  flex: none;
  padding: 12px 14px 14px;
  overflow-y: auto;
  max-height: 60vh;
}

/* ── The cards ──
   The three read-outs stacked, one always open (Ben). The open card grows to
   take the height the others leave; a press on a closed one swaps them, and the
   swap is animated on flex-grow, which is what makes both heights move at once.
   Closed cards keep a live thumbnail of their drawing in the panel's compact
   rendering, so the star's readings are never out of sight. */
#cards {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rcard {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--panel-edge);
  border-radius: 10px;
  background: var(--panel);
  overflow: hidden;
  transition: flex-grow 360ms cubic-bezier(0.2, 0.7, 0.3, 1), border-color 200ms;
}

.rcard.is-open { flex-grow: 1; border-color: var(--focus-glow); }

@media (prefers-reduced-motion: reduce) {
  .rcard { transition: none; }
}

.rcard-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-bottom: 1px solid var(--panel-edge);
  background: none;
  font: inherit;
  color: var(--panel-ink);
  text-align: left;
  cursor: pointer;
  flex: none;
}

/* A closed card is a button, and says so on hover: the head lights and the
   card's edge brightens. The open card's head is a heading, not a button. */
.rcard:not(.is-open) .rcard-head:hover { background: rgba(255, 255, 255, 0.07); }
.rcard:not(.is-open) .rcard-head:hover .card-title { color: var(--panel-ink); }
.rcard:not(.is-open):has(.rcard-head:hover) { border-color: rgba(255, 255, 255, 0.3); }
.rcard.is-open .rcard-head { cursor: default; }
.rcard-head:focus-visible { outline: 3px solid var(--focus-glow); outline-offset: -3px; }

.rcard-value { font-size: 12px; font-weight: 700; white-space: nowrap; }

/* The body: a thumbnail's worth of height when closed, and everything the card
   is given when open. One rule does both, because the card's flex-grow is what
   changes and the body just follows it. */
.rcard-body {
  position: relative;
  flex: 1 1 96px;
  min-height: 96px;
  overflow: hidden;
}

.rcard-body canvas { display: block; width: 100%; height: 100%; }

/* The finished-run card takes the moment's slot. */
/* The finished-run line, one row at the top of the stage. */
#run-note {
  flex: none;
  align-self: center;
  padding: 5px 14px;
  border-radius: 999px;
  background: rgba(8, 11, 20, 0.9);
  border: 1px solid var(--focus-glow);
  color: var(--panel-ink);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.3;
}

/* While the chooser is open the cards are shelved: heads only, so the chooser
   has the panel and nothing is squeezed (Ben, round 15). */
#cards.is-shelved .rcard { flex-grow: 0; border-color: var(--panel-edge); }
#cards.is-shelved .rcard-body { display: none; }
















#moment-bar[hidden] { display: none !important; }

#moment-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

/* The ruler's price and, while a key moment holds the run, the zoom handle:
   the number you are changing is the thing you hold (Ben). The chip never
   moves; dragging it re-prices it and everything behind it. */
#scale-bar-text-wrap {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

#canvas-frame.zoom-live { touch-action: none; }

#canvas-frame.zoom-live #scale-bar-rule {
  pointer-events: auto;
  cursor: ns-resize;
  touch-action: none;
}

#canvas-frame.zoom-live #scale-bar-text {
  pointer-events: auto;
  cursor: ns-resize;
  border: 1px solid var(--focus-glow);
  position: relative;
  touch-action: none;
  user-select: none;
}

#canvas-frame.zoom-live #scale-bar-text:focus-visible {
  outline: 3px solid var(--focus-glow);
  outline-offset: 2px;
}

/* Small drawn chevrons above and below the chip while it is a handle, so it
   advertises which way it moves without a word of instruction. */
#canvas-frame.zoom-live #scale-bar-text::before,
#canvas-frame.zoom-live #scale-bar-text::after {
  content: '';
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
}

#canvas-frame.zoom-live #scale-bar-text::before {
  bottom: 100%;
  margin-bottom: 3px;
  border-bottom: 6px solid var(--focus-glow);
}

#canvas-frame.zoom-live #scale-bar-text::after {
  top: 100%;
  margin-top: 3px;
  border-top: 6px solid var(--focus-glow);
}

/* The way back, once the student has left the framing the sim chose. It sits
   clear of the chip's lower chevron. */
#zoom-reset-btn {
  pointer-events: auto;
  margin-top: 10px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: var(--panel-ink);
  background: rgba(11, 15, 24, 0.92);
  border: 1px solid var(--panel-edge);
  border-radius: 6px;
  padding: 4px 8px;
  cursor: pointer;
  white-space: nowrap;
}

#zoom-reset-btn:hover { border-color: var(--focus-glow); }

#zoom-reset-btn:focus-visible {
  outline: 3px solid var(--focus-glow);
  outline-offset: 1px;
}

#zoom-reset-btn[hidden] { display: none !important; }

/* One heading carries the stage's name and the star's age, in the accent the
   eyebrow used to wear, so the card keeps its colour without a second line. */
#moment-title {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--focus-glow);
  line-height: 1.3;
}

#moment-caption { font-size: 13.5px; line-height: 1.45; color: var(--panel-ink); }

/* ── Quiet chrome while a moment is held ──
   Everything that is not the moment steps back, so the scene and its caption are
   what the eye lands on. Nothing is removed, only dimmed. */
/* Nothing steps back during a key moment. The read-outs stay bright and stay
   clickable, because a key moment is exactly when a student wants to open the
   element table and look at what just landed in it; the ruler stays bright
   because a change of framing is one of the things a moment is for; and the
   timeline stays because the diamond it has stopped on is the signal (Ben). */


/* ── The timeline ──
   One block per stage, labelled with what that stage really lasted, and a diamond
   on every key moment. The playhead crosses at a steady rate and stops ON a
   diamond; while it is stopped the clock on screen is free. */
#timeline {
  flex: none;
  display: flex;
  align-items: center;
  gap: 14px;
  /* Deeper at the foot than the head: the age landmarks hang under the track. */
  padding: 7px 14px 22px;
  border-radius: 10px;
  background: rgba(11, 15, 24, 0.92);
  border: 1px solid var(--panel-edge);
}

#timeline.is-held { border-color: var(--focus-glow); }

#tl-stage {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 132px;
  max-width: 190px;
}

#tl-stage-name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--panel-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The age landmarks. A tick is a hairline through the track with its name
   under it; where two land together the smaller one keeps the line and loses
   the name, so the track never prints two words in one place. */
#tl-ticks { position: absolute; inset: 0; pointer-events: none; }

.tl-tick {
  position: absolute;
  top: 3px;
  height: 12px;
  width: 1px;
  background: rgba(147, 161, 181, 0.55);
}

.tl-tick span {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  transform: translateX(-50%);
  font-size: 12px;
  color: var(--panel-muted);
  white-space: nowrap;
}

.tl-tick.is-bare { background: rgba(147, 161, 181, 0.3); }

#tl-stage-time {
  font-size: 12px;
  color: var(--panel-muted);
  /* Wraps: inside a stage shorter than a year the clock carries a second
     clause, and a single line of it ran under the first diamond. */
  white-space: normal;
  line-height: 1.3;
}

#tl-track { position: relative; flex: 1; height: 18px; min-width: 60px; }

#tl-segments { position: absolute; left: 0; right: 0; top: 7px; height: 4px; }

.tl-seg {
  position: absolute;
  top: 0;
  height: 4px;
  background: rgba(42, 51, 70, 0.9);
  border-radius: 2px;
}

.tl-seg + .tl-seg { border-left: 1px solid var(--void); }

#tl-fill {
  position: absolute;
  left: 0;
  top: 7px;
  height: 4px;
  width: 0;
  border-radius: 2px;
  background: #16C2A3;
}

#tl-head {
  position: absolute;
  top: 3px;
  width: 3px;
  height: 12px;
  border-radius: 2px;
  background: #8FF3E0;
  transform: translateX(-50%);
}

#timeline.is-held #tl-head { background: var(--focus-glow); }

#tl-marks { position: absolute; inset: 0; }

.tl-mark {
  position: absolute;
  top: 4px;
  width: 10px;
  height: 10px;
  transform: translateX(-50%) rotate(45deg);
  background: var(--panel);
  border: 2px solid #16C2A3;
  border-radius: 2px;
}

.tl-mark.done { background: #16C2A3; }

.tl-mark.active {
  background: var(--focus-glow);
  border-color: var(--focus-glow);
  animation: tlPulse 1.6s ease-in-out infinite;
}

@keyframes tlPulse {
  0%, 100% { transform: translateX(-50%) rotate(45deg) scale(1); }
  50%      { transform: translateX(-50%) rotate(45deg) scale(1.35); }
}

@media (prefers-reduced-motion: reduce) {
  .tl-mark.active { animation: none; }
}

/* ── Controls, inside the setup card ── */
#setup-controls {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 4px 12px 14px;
}

.dock-group { display: flex; flex-direction: column; gap: 5px; min-width: 0; }

.dock-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--panel-muted);
}

.dock-note { font-size: 12px; line-height: 1.45; max-width: 280px; color: var(--panel-muted); }

.chip-row { display: flex; flex-wrap: wrap; gap: 6px; }

.chip {
  font: 500 12.5px Roboto, Arial, sans-serif;
  color: var(--panel-ink);
  background: #182034;
  border: 1px solid var(--panel-edge);
  border-radius: 999px;
  padding: 6px 12px;
  cursor: pointer;
}

.chip:hover { background: #202B44; }

/* Chips with a drawn mark beside the word. */
.chip.has-art {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding-left: 8px;
}

.chip-art { width: 18px; height: 18px; flex: none; display: inline-flex; }
.chip-art svg { width: 100%; height: 100%; display: block; }

.chip[aria-checked="true"],
.chip[aria-pressed="true"] {
  background: var(--accent-light);
  border-color: #16C2A3;
  color: #ffffff;
}

.chip:focus-visible,
.primary-btn:focus-visible,
.ghost-btn:focus-visible,
#mass-slider:focus-visible {
  outline: 3px solid var(--focus-glow);
  outline-offset: 2px;
}

.slider-row { display: flex; align-items: center; gap: 10px; }
#setup-hint { color: var(--panel-muted); font-size: 12px; }

#mass-slider { width: 100%; accent-color: #16C2A3; }

#mass-readout {
  font: 600 13px Roboto, Arial, sans-serif;
  color: var(--panel-ink);
  min-width: 118px;
}

.primary-btn {
  font: 600 14px Roboto, Arial, sans-serif;
  color: #06231F;
  background: #16C2A3;
  border: none;
  border-radius: 8px;
  padding: 10px 22px;
  cursor: pointer;
}

.primary-btn:hover { background: #2FD8BA; }

.primary-btn[disabled] { background: #2A3346; color: #6B7A92; cursor: default; }

.ghost-btn {
  font: 600 12.5px Roboto, Arial, sans-serif;
  color: var(--panel-ink);
  background: #182034;
  border: 1px solid var(--panel-edge);
  border-radius: 7px;
  padding: 6px 14px;
  cursor: pointer;
  white-space: nowrap;
}

.ghost-btn:hover { background: #202B44; }

/* ── Reset dialog ── */

/* ── Narrow layouts ──
   The read-outs become a strip of tabs under the star chooser, so the bottom of
   the frame belongs to the key moment alone. */
@media (max-width: 780px) {
  /* Stage on top, panel under it. The stage keeps a little over half the
     height so the star stays the biggest thing on the screen; the panel scrolls
     if it has to, with the header and the moment always at its top. */
  #layout { flex-direction: column; }
  #stage { flex: 0 0 56%; padding: 8px 8px 0; }
  #panel { flex: 1 1 auto; max-width: none; padding: 8px; overflow-y: auto; }
  #scale-bar { left: 12px; }
  /* No room to stack three thumbnails under a stage: closed cards are their
     heads, the open one has a height the table and the diagram can be read at,
     and the panel scrolls to it (Ben). */
  #cards { flex: none; }
  .rcard { transition: none; }
  .rcard:not(.is-open) .rcard-body { display: none; }
  .rcard.is-open .rcard-body { flex: none; height: 380px; }
  #setup-view { max-height: none; }
}
