/* ==========================================================================
   RoboCode — styles
   ==========================================================================
   The world is a friendly late-night workshop: a robot on a workbench
   blueprint. Deep navy, raised blocks, one amber accent that means "this is
   happening right now" and one teal that means "this is done".

   Amber is reserved. It is the robot and the executing highlight, and nothing
   else, so that when something glows amber the eye already knows what it means.
   ========================================================================== */

:root {
  /* Palette */
  --navy-deep: #0F1626;
  --navy-tile: #1B2740;
  --navy-wall: #2E3D5C;
  --amber: #F2B33D;
  --amber-dim: rgba(242, 179, 61, 0.16);
  --teal: #4FD1A5;
  --teal-dim: rgba(79, 209, 165, 0.14);
  --red: #FF6B6B;
  --red-dim: rgba(255, 107, 107, 0.14);
  --text: #E8ECF7;
  --text-muted: rgba(232, 236, 247, 0.58);
  --text-faint: rgba(232, 236, 247, 0.34);
  --hairline: rgba(232, 236, 247, 0.09);

  /* Type — Fredoka is used with restraint: titles and the win screen only. */
  --font-display: 'Fredoka', 'Trebuchet MS', system-ui, sans-serif;
  --font-body: 'Nunito', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --radius: 12px;
  --radius-sm: 8px;
  --panel-width: 340px;
}

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

/* The `hidden` attribute must always win. Any author `display` — and nearly
   every component here sets one — silently beats the UA stylesheet's [hidden]
   rule, which makes "hide this" fail in a way that looks like a logic bug. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--navy-deep);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.45;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

/* Focus is always visible. A kid navigating by keyboard, or an adult debugging
   next to them, must be able to see where they are. */
:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 2px;
  border-radius: 4px;
}

/* --------------------------------------------------------------- app shell */

.app {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  height: 100%;
  max-width: 1400px;
  margin: 0 auto;
}

/* ---------------------------------------------------------------------- HUD */

.hud {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--hairline);
}

/* The wordmark. Fredoka is used with restraint — here and level titles only. */
.hud__brand {
  margin: 0;
  padding-right: 16px;
  border-right: 1px solid var(--hairline);
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--text-muted);
  white-space: nowrap;
}

.hud__identity { min-width: 0; margin-right: auto; }

.hud__pack {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.hud__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.6vw, 1.75rem);
  font-weight: 600;
  line-height: 1.1;
}

.hud__meta {
  display: flex;
  align-items: center;
  gap: 18px;
}

.field { display: flex; flex-direction: column; gap: 3px; }

.field__label {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.select {
  appearance: none;
  padding: 7px 30px 7px 11px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--navy-tile)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23E8ECF7' opacity='.5'/%3E%3C/svg%3E")
    no-repeat right 10px center;
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
}

.scoreboard { text-align: right; }

.stars { display: flex; gap: 3px; justify-content: flex-end; font-size: 1.4rem; }

.star { color: rgba(232, 236, 247, 0.16); transition: color 180ms ease, transform 180ms ease; }

.star.is-earned { color: var(--amber); transform: scale(1.08); }

.scoreboard__target {
  margin: 2px 0 0;
  font-size: 0.8rem;
  color: var(--text-muted);
  white-space: nowrap;
}

.scoreboard__best {
  margin: 1px 0 0;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-faint);
  white-space: nowrap;
}

/* -------------------------------------------------------------------- stage */

.stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--panel-width);
  gap: 16px;
  min-height: 0;
  padding: 16px 20px;
}

.grid-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
}

/* Positioning context for the win panel, which overlays the grid. */
.grid-panel__canvasWrap {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
}

#gameCanvas {
  flex: 1;
  width: 100%;
  min-height: 220px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--navy-deep);
  touch-action: manipulation;
}

.grid-panel__hint {
  margin: 0;
  padding-left: 22px;
  position: relative;
  font-size: 0.86rem;
  color: var(--text-muted);
}

.grid-panel__hint::before {
  content: '💡';
  position: absolute;
  left: 0;
  filter: grayscale(0.4);
}

/* --------------------------------------------------------------- side panel */

.side-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 0;
  overflow-y: auto;
  padding-right: 2px;
}

.panel-block {
  /* Fixed-size by default: the palette and the inspector are as tall as their
     content, so all the leftover height can go to the program. */
  flex: 0 0 auto;
  padding: 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: rgba(27, 39, 64, 0.5);
}

/* The program strip claims the remaining column height, because a long program
   is the thing most likely to need it. */
.panel-block--grow {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 140px;
}

.panel-block__heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.panel-block__count { font-family: var(--font-mono); letter-spacing: 0; color: var(--text-muted); }

.panel-block__heading-right { display: flex; align-items: baseline; gap: 10px; }

/* A quiet text button, for actions that are secondary to building the program. */
.link-button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-faint);
  font: inherit;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.link-button:hover { color: var(--red); }

.panel-block__note {
  margin: 10px 0 0;
  font-size: 0.74rem;
  color: var(--text-faint);
}

/* ------------------------------------------------------------------ palette */

.palette {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(68px, 1fr));
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.command {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 7px 4px 6px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--navy-wall);
  /* A raised lip on top, matching the wall blocks on the grid. */
  box-shadow: inset 0 2px 0 rgba(232, 236, 247, 0.1), 0 2px 0 rgba(0, 0, 0, 0.3);
  cursor: grab;
  user-select: none;
  /* pan-y lets a vertical swipe scroll the page while any other gesture
     (including the press-and-hold that starts a drag) belongs to us. */
  touch-action: pan-y;
}

.command__glyph { font-family: var(--font-mono); font-size: 1.15rem; line-height: 1.2; }

.command__label {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--text-muted);
  text-align: center;
}

/* PICKED UP. Tap-to-place is a mode, and an invisible mode is a broken mode, so
   the held command is unmistakable and the strips light up to match. */
.command.is-held {
  border-color: var(--amber);
  background: var(--amber);
  box-shadow: 0 0 0 3px var(--amber-dim), 0 3px 0 rgba(0, 0, 0, 0.35);
  transform: translateY(-2px);
}

.command.is-held .command__glyph,
.command.is-held .command__label { color: #221703; font-weight: 700; }

.command--locked {
  background: rgba(46, 61, 92, 0.4);
  box-shadow: none;
  cursor: not-allowed;
  opacity: 0.45;
}

.command__lock { position: absolute; top: 2px; right: 4px; font-size: 0.6rem; }

/* ----------------------------------------------------------- program strips */

.strips {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
  overflow-y: auto;
  /* The executing block nudges 2px right and an errored one shakes; both would
     otherwise overflow the container and raise a horizontal scrollbar. */
  overflow-x: hidden;
}

.strip__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 0 0 6px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}

.strip__usage { color: var(--text-faint); font-weight: 400; }
.strip__usage.is-full { color: var(--amber); }

/* Hitting the slot limit has to be felt, not just read. */
.strip__usage.is-flashing { animation: usageFlash 600ms ease; }

@keyframes usageFlash {
  0%, 100% { color: var(--amber); transform: none; }
  30% { color: var(--red); transform: scale(1.35); }
}

.blocks {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Nested lists (a repeat's or conditional's body) step in and hang off a rail,
   so the shape of the nesting is visible at a glance. */
.blocks--nested {
  margin: 0 0 0 13px;
  padding-left: 9px;
  border-left: 2px solid rgba(242, 179, 61, 0.28);
}

/* --- drop zones --------------------------------------------------------- */
/* Thin by default so the program reads as a tight list, and taller while
   something is being placed, because a 4px target is no target at all on a
   finger. Nearest-zone hit testing in blockEditor.js does the rest. */
.dropzone {
  height: 4px;
  border-radius: 2px;
  transition: height 120ms ease, background 120ms ease;
}

.strips.is-placing .dropzone { height: 12px; background: rgba(232, 236, 247, 0.05); }

.dropzone.is-drop-target {
  height: 14px;
  background: var(--amber);
  box-shadow: 0 0 10px rgba(242, 179, 61, 0.5);
}

/* An empty list needs to look like somewhere things go, not like a gap. */
.dropzone--empty {
  display: grid;
  place-items: center;
  height: auto;
  min-height: 34px;
  padding: 6px;
  border: 1px dashed var(--hairline);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--text-faint);
}

.strips.is-placing .dropzone--empty {
  height: auto;
  border-color: rgba(242, 179, 61, 0.5);
  color: var(--amber);
}

/* --- blocks ------------------------------------------------------------- */
/* The program is monospaced because it is code. The contrast with the rounded
   UI around it quietly signals which part of the screen is the program. */
.block {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--navy-tile);
  font-family: var(--font-mono);
  transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
}

.block__head {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 6px 5px 8px;
  cursor: grab;
  user-select: none;
  touch-action: pan-y;
}

.block__glyph {
  flex: 0 0 auto;
  width: 1.4em;
  font-size: 0.95rem;
  text-align: center;
}

.block__label { flex: 1 1 auto; font-size: 0.76rem; color: var(--text-muted); }

/* Tap the count to cycle 2 - 5. A stepper would need two more controls to do
   the same job, in a strip that has no room for them. */
.block__count {
  flex: 0 0 auto;
  padding: 1px 7px;
  border: 1px solid rgba(242, 179, 61, 0.4);
  border-radius: 999px;
  background: var(--amber-dim);
  color: var(--amber);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 700;
  cursor: pointer;
}

.block__count:hover { background: rgba(242, 179, 61, 0.3); }

.block__remove {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-faint);
  font-size: 0.7rem;
  cursor: pointer;
  /* Visible at all times rather than on hover: there is no hover on an iPad,
     and a delete you cannot find is a program you cannot fix. */
  opacity: 0.5;
  transition: opacity 120ms ease, background 120ms ease, color 120ms ease;
}

.block__remove:hover,
.block__remove:focus-visible {
  opacity: 1;
  background: var(--red-dim);
  color: var(--red);
}

/* A finger needs more than 22px. Only widened on touch devices, where the
   extra room costs nothing, rather than on a mouse where 22px is generous. */
@media (pointer: coarse) {
  .block__remove { width: 36px; height: 30px; }
  .block__head { padding: 6px 4px 6px 8px; }
}

.block--container { background: rgba(46, 61, 92, 0.55); }

.block.is-being-dragged { opacity: 0.3; }

/* --- the executing-now highlight ---------------------------------------- */
/* This is the single most important visual state in the game. Amber, obvious,
   and it moves. */
.block.is-executing {
  border-color: var(--amber);
  background: var(--amber-dim);
  transform: translateX(2px);
}

.block.is-executing > .block__head .block__label { color: var(--text); }

.block.is-error {
  border-color: var(--red);
  background: var(--red-dim);
  animation: shake 320ms ease;
}

.block.is-noop { border-color: rgba(242, 179, 61, 0.45); }

@keyframes shake {
  0%, 100% { transform: translateX(2px); }
  25% { transform: translateX(-3px); }
  50% { transform: translateX(4px); }
  75% { transform: translateX(-2px); }
}

/* --- the drag ghost ----------------------------------------------------- */
/* What the pointer carries while dragging. Fixed-position and pointer-events
   none so it can never intercept its own drop. */
.drag-ghost {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border: 1px solid var(--amber);
  border-radius: var(--radius-sm);
  background: var(--navy-wall);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  pointer-events: none;
  transform: translate3d(-999px, -999px, 0);
  rotate: -2deg;
}

.drag-ghost__count {
  padding: 0 6px;
  border-radius: 999px;
  background: var(--amber-dim);
  color: var(--amber);
  font-size: 0.68rem;
}

body.is-dragging-block { cursor: grabbing; user-select: none; }

/* --- the execution pulse ------------------------------------------------ */
/* The spark that flies from the running instruction into the robot. Positioned
   at the origin and moved entirely by transform, so it never triggers layout. */
.pulse {
  position: fixed;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: var(--amber);
  box-shadow: 0 0 12px 3px rgba(242, 179, 61, 0.65);
  pointer-events: none;
  z-index: 300;
}

/* ----------------------------------------------------------- level editor */

/* The play panels and the build panels occupy the same column, one at a time. */
.side-panel__group {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 12px;
  min-height: 0;
}

.editor__sizes { display: flex; gap: 10px; margin-bottom: 12px; }

.editor__size {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
}

.editor__sizeLabel {
  flex: 1;
  font-size: 0.72rem;
  color: var(--text-muted);
}

.editor__sizeValue {
  min-width: 1.4em;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  text-align: center;
}

.stepper {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--navy-wall);
  color: var(--text);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.stepper:hover { filter: brightness(1.15); }

/* What each tile colour means — the editor's only real instruction. */
.editor__legend {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px 10px;
  margin: 0 0 8px;
  padding: 0;
  list-style: none;
  font-size: 0.74rem;
  color: var(--text-muted);
}

.editor__legend li { display: flex; align-items: center; gap: 7px; }

.swatch {
  width: 15px;
  height: 15px;
  border-radius: 4px;
  flex: 0 0 auto;
}

.swatch--floor { background: var(--navy-tile); box-shadow: inset 0 0 0 1px var(--hairline); }
.swatch--wall { background: var(--navy-wall); box-shadow: inset 0 2px 0 rgba(232, 236, 247, 0.16); }
.swatch--goal { background: transparent; box-shadow: inset 0 0 0 2px var(--teal); }
.swatch--pit { background: #080C15; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.6); }

.editor__row { display: flex; gap: 8px; align-items: center; margin-top: 10px; }

.button--small {
  min-height: 36px;
  padding: 0 12px;
  font-size: 0.82rem;
}

.editor__nameInput {
  flex: 1;
  min-width: 0;
  min-height: 36px;
  padding: 0 10px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--navy-deep);
  color: var(--text);
  font: inherit;
  font-size: 0.85rem;
}

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

/* --- the My Levels shelf ------------------------------------------------ */

.shelf { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }

.shelf__item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 6px 6px 10px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--navy-tile);
}

.shelf__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.84rem;
}

.shelf__size {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-faint);
}

.icon-button {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--text-faint);
  font-size: 0.8rem;
  cursor: pointer;
}

.icon-button:hover { background: var(--red-dim); color: var(--red); }

/* The editor's smallest controls, sized up for fingers. */
@media (pointer: coarse) {
  .stepper,
  .icon-button { width: 42px; height: 42px; }
}

.editor__share {
  width: 100%;
  height: 90px;
  padding: 8px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: var(--navy-deep);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  line-height: 1.4;
  resize: vertical;
}

/* ------------------------------------------------------------- win overlay */

.win {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 16px;
  border-radius: var(--radius);
  background: rgba(15, 22, 38, 0.82);
  backdrop-filter: blur(3px);
  z-index: 5;
  animation: winFadeIn 220ms ease;
}

.win__card {
  max-width: 340px;
  padding: 22px 20px;
  border: 1px solid rgba(79, 209, 165, 0.35);
  border-radius: 18px;
  background: var(--navy-tile);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5);
  text-align: center;
}

.stars--large { justify-content: center; font-size: 2.1rem; }

/* Fredoka, used with restraint: level titles and this. */
.win__headline {
  margin: 8px 0 4px;
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--teal);
}

.win__detail { margin: 0 0 16px; font-size: 0.86rem; color: var(--text-muted); }

.win__actions { display: flex; flex-direction: column; gap: 8px; }

.button--quiet {
  background: none;
  box-shadow: none;
  color: var(--text-muted);
  font-weight: 400;
}

@keyframes winFadeIn {
  from { opacity: 0; transform: scale(0.97); }
  to { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------- inspector */

.inspector {
  flex: 0 0 auto;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: rgba(27, 39, 64, 0.5);
}

.inspector__summary {
  padding: 9px 12px;
  cursor: pointer;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.inspector__grid {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 4px 12px;
  margin: 0;
  padding: 0 12px 12px;
  font-family: var(--font-mono);
  font-size: 0.74rem;
}

.inspector__grid dt { color: var(--text-faint); }
.inspector__grid dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }

/* ----------------------------------------------------------------- controls */

.controls {
  padding: 12px 20px 16px;
  border-top: 1px solid var(--hairline);
}

/* Every failure state says what happened, right above the Reset button. */
.message {
  margin: 0 0 10px;
  min-height: 1.4em;
  font-size: 0.88rem;
  color: var(--text-muted);
}

.message[data-tone='success'] { color: var(--teal); font-weight: 700; }
.message[data-tone='error'] { color: var(--red); font-weight: 700; }
.message[data-tone='warn'] { color: var(--amber); }

.controls__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.controls__buttons { display: flex; flex-wrap: wrap; gap: 8px; }

.button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  /* Comfortably past the 44px touch target, because this is used on an iPad. */
  min-height: 46px;
  padding: 0 18px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--navy-wall);
  box-shadow: inset 0 2px 0 rgba(232, 236, 247, 0.1), 0 2px 0 rgba(0, 0, 0, 0.35);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  transition: transform 90ms ease, filter 120ms ease;
}

.button:hover:not(:disabled) { filter: brightness(1.12); }
.button:active:not(:disabled) { transform: translateY(2px); box-shadow: inset 0 2px 0 rgba(232, 236, 247, 0.08); }
.button:disabled { opacity: 0.4; cursor: not-allowed; }

.button--primary {
  border-color: transparent;
  background: var(--teal);
  color: #0B1A16;
}

.button--primary.is-running { background: var(--amber); color: #221703; }

.button__glyph { font-size: 0.9rem; }

.speed {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0;
  padding: 4px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}

.speed__legend {
  float: left;
  padding: 0 8px 0 4px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.speed__option { position: relative; }

.speed__option input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.speed__option span {
  display: grid;
  place-items: center;
  min-width: 40px;
  min-height: 36px;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  color: var(--text-muted);
}

.speed__option input:checked + span { background: var(--amber-dim); color: var(--amber); font-weight: 700; }
.speed__option input:focus-visible + span { outline: 2px solid var(--amber); outline-offset: 2px; }

/* -------------------------------------------------------------- responsive */
/* Tablet portrait and below: the grid goes above the palette and program, so
   the robot stays the first thing on screen. */
@media (max-width: 900px) {
  .stage {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(200px, 46vh) auto;
    overflow-y: auto;
  }

  .side-panel { overflow: visible; }
  .strips { overflow: visible; }
  .hud { padding: 12px 14px; }
  .stage { padding: 12px 14px; }
  .controls { padding: 10px 14px 14px; }
  .hud__meta { width: 100%; justify-content: space-between; }
}

@media (max-width: 520px) {
  .palette { grid-template-columns: repeat(4, 1fr); }
  .controls__row { flex-direction: column; align-items: stretch; }
  .speed { justify-content: center; }
}

/* -------------------------------------------------- reduced motion, honoured */
/* Instant moves instead of tweens (the renderer checks the same query), and no
   pulse or shake here. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .star.is-earned { transform: none; }
  .block.is-executing { transform: none; }
}
