/* ===========================================================================
   BELL TRAIN · bell-train-v1.css
   ---------------------------------------------------------------------------
   Layout rule that everything else follows: THE SCENE IS A FIXED-RATIO BOX and
   every single thing inside it is positioned in percentages of that box. There
   is not one media query for the scene, because there does not need to be —
   phone, Chromebook and interactive whiteboard all get the same picture at
   different sizes, and a drop target that is 30% wide is a fat target on all
   three.

   The vertical bands, measured FROM THE BOTTOM of the scene, because that is
   where the ground is:

       100% ┬ sky
        64% ┼ horizon (hills sit on this line)
            │ grass
        42% ┼ ground line — houses, market stalls and cargo all stand here
            │ open field — the breathing room between the train and the drop
            │ zone, roughly a third of a wagon's height
        33% ┼ top of a loaded wagon
        18% ┼ rails (top)
            │ the train, in the foreground
         2% ┼ rails (bottom)
         0% ┴ front edge

   Anything that reads as "further away" is drawn earlier and scrolls slower.

   Two things this diagram is enforcing, not describing:

   The ground line sits ABOVE the top of a loaded wagon. Cargo waiting on the
   grass has to be completely visible and completely grabbable; a strawberry
   whose bottom half is behind a wagon is a strawberry a child will try to grab
   by its bottom half.

   And it clears the wagon by a real margin rather than a hair. The house and
   the bells are where the child is aiming; the train is where they are
   dragging from. Butting the two together made the whole lower half read as
   one crowded band.
   =========================================================================== */

:root {
  --ink: #1b233e;
  --muted: #65728f;
  --bg: #eef1f5;
  --card: #ffffff;
  --line: #d9e3f3;
  --teal: #099695;
  --teal-dark: #007777;

  /* Scene bands (see the diagram above). Change them here, not in components. */
  --ground: 42%;
  --rail-bottom: 2%;
  --rail-h: 16%;
  --horizon: 64%;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body { margin: 0; padding: 0; background: var(--bg); }

body {
  min-height: 100vh;
  min-height: 100svh;
  color: var(--ink);
  font-family: "Nunito", "Avenir Next Rounded", "Trebuchet MS", Verdana, sans-serif;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-tap-highlight-color: transparent;
}

/* While a piece of cargo is in the air, the page must not scroll under it. */
body.is-dragging { overflow: hidden; touch-action: none; }

.app { width: min(1060px, 100%); margin: 0 auto; }

.screen {
  padding: 18px 14px calc(28px + env(safe-area-inset-bottom));
  display: grid;
  align-content: start;
  gap: 14px;
  position: relative;
}

/* ── Header ──────────────────────────────────────────────────────────────── */
.game-head { text-align: center; display: grid; gap: 8px; }

.app-title {
  margin: 0;
  font-size: clamp(1.5rem, 4.6vw, 2rem);
  font-weight: 900;
  letter-spacing: -0.01em;
}

.prompt {
  margin: 0 auto;
  max-width: 46ch;
  min-height: 2.6em;
  color: var(--muted);
  font-size: clamp(0.95rem, 2.6vw, 1.06rem);
  line-height: 1.3;
  font-weight: 800;
}

.group-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
}

.group-btn {
  appearance: none;
  border: 1.5px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font: inherit;
  font-weight: 900;
  font-size: clamp(0.78rem, 2.1vw, 0.9rem);
  padding: 7px 13px;
  border-radius: 999px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.1s;
}
.group-btn:hover { border-color: var(--teal); }
.group-btn:active { transform: translateY(1px); }
.group-btn.is-active {
  background: var(--teal);
  border-color: var(--teal-dark);
  color: #fff;
}
/* Three colour beads on each chip — the group's notes, before you press it. */
.group-btn .beads { display: inline-flex; gap: 3px; }
.group-btn .tick { color: #2e9e5b; font-size: 0.9em; line-height: 1; }
.group-btn.is-active .tick { color: #d6f2e0; }
.group-btn .beads i {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--bead);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.22);
}

/* ── Stage + scene ───────────────────────────────────────────────────────── */
.stage {
  display: grid;
  gap: 8px;
  justify-items: center;
}

.scene {
  position: relative;
  width: 100%;
  aspect-ratio: 20 / 11;
  border-radius: 18px;
  overflow: hidden;
  background: #cfeef2;
  box-shadow: 0 6px 24px rgba(27, 35, 62, 0.14), inset 0 0 0 1px rgba(27, 35, 62, 0.06);
  touch-action: none;                 /* the scene is a drag surface, not a scroller */
  user-select: none;
  -webkit-user-select: none;
}

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

.sky {
  background:
    radial-gradient(120% 90% at 50% 92%, #dff7f4 0%, #bfeaf0 45%, #a8e0ee 100%);
}
/* The soft sunburst behind the hills in the reference art. */
.sun {
  position: absolute;
  left: 50%; top: calc(100% - var(--horizon));
  width: 120%; aspect-ratio: 1;
  transform: translate(-50%, -55%);
  background: conic-gradient(from 200deg,
    rgba(255,255,255,0.34) 0deg, rgba(255,255,255,0) 12deg,
    rgba(255,255,255,0.34) 24deg, rgba(255,255,255,0) 36deg,
    rgba(255,255,255,0.34) 48deg, rgba(255,255,255,0) 60deg,
    rgba(255,255,255,0.34) 72deg, rgba(255,255,255,0) 84deg,
    rgba(255,255,255,0.34) 96deg, rgba(255,255,255,0) 108deg,
    rgba(255,255,255,0.34) 120deg, rgba(255,255,255,0) 132deg);
  opacity: 0.75;
}

/* The three scrolling strips. Each tiles horizontally and is moved by
   background-position-x, which repeat-x makes seamless at ANY offset — so the
   engine never has to land a trip on a whole multiple of a tile. */
.bg-strip {
  inset: auto 0 auto 0;
  background-repeat: repeat-x;
  background-size: auto 100%;
  background-position: 0 bottom;
}
.hills { bottom: var(--horizon); height: 26%; }
/* Trees stand BEHIND the ground line, not on it. Higher up the field reads as
   further away, so parking them at `--ground` put them shoulder to shoulder
   with the houses and the bells and made the drop zone feel cluttered. */
.trees { bottom: calc(var(--ground) + 8%); height: 14%; }
.rails { bottom: var(--rail-bottom); height: var(--rail-h); }

/* Every band in this file is measured FROM THE BOTTOM, because that is where
   the ground is. `top` here is derived rather than authored — an earlier
   version set `top: var(--horizon)` directly, which quietly gave the token two
   opposite meanings (hills counted up from the floor, grass counted down from
   the ceiling) and tore a band of sky through the middle of the field the
   moment the horizon moved. */
.grass {
  top: calc(100% - var(--horizon));
  bottom: 0;
  background: linear-gradient(#7cc93f 0%, #6dbb36 40%, #5faf2e 100%);
}
.grass::before {                     /* a rolling lip so the horizon isn't a ruler */
  content: "";
  position: absolute; left: -2%; right: -2%; top: -3.4%;
  height: 8%;
  border-radius: 50%;
  background: #7cc93f;
}

/* ── Stops ───────────────────────────────────────────────────────────────── */
.stops { overflow: hidden; }

.stop {
  position: absolute;
  inset: 0;
  will-change: transform;
}
.stop.is-current  { transform: translateX(0); }
.stop.is-incoming { transform: translateX(100%); }

/* The place itself — house, station, market or toy shop. */
.place {
  position: absolute;
  left: 50%;
  bottom: var(--ground);
  width: 26%;
  transform: translateX(-50%);
}
.place svg { display: block; width: 100%; height: auto; }
/* Pickup stops move aside to make room for the cargo waiting on the grass. */
.stop[data-kind="pickup"] .place { left: 21%; }

/* Where cargo waits before it is loaded. */
.platform {
  position: absolute;
  left: 40%;
  right: 4%;
  bottom: var(--ground);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 2.4%;
  pointer-events: auto;
}

/* Where delivered things end up, standing beside the house. */
.yard {
  position: absolute;
  left: 63%;
  right: 3%;
  bottom: var(--ground);
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 1.6%;
}

/* The house drop target: deliberately enormous. A five-year-old aiming at a
   letterbox-sized hitbox is a design failure, not a motor-skill problem. */
.dropzone {
  position: absolute;
  left: 30%;
  right: 30%;
  bottom: calc(var(--ground) - 4%);
  height: 48%;
  padding: 0;
  border: 3px dashed transparent;
  border-radius: 16px;
  background: transparent;
  cursor: pointer;
  pointer-events: none;
  transition: background 0.18s, border-color 0.18s;
}
.scene[data-phase="deliver"] .dropzone { pointer-events: auto; }
.scene.is-aiming .dropzone {
  border-color: rgba(255, 255, 255, 0.85);
  background: rgba(255, 255, 255, 0.16);
}
.dropzone.is-hover {
  border-color: #fff;
  background: rgba(255, 255, 255, 0.34);
}
.dropzone.is-hint { animation: hintPulse 1.1s ease-in-out infinite; }
@keyframes hintPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  50%      { box-shadow: 0 0 0 12px rgba(255, 255, 255, 0.28); }
}

/* ── Train ───────────────────────────────────────────────────────────────── */
.train-wrap {
  position: absolute;
  left: 1.5%;
  right: 1.5%;
  bottom: 4%;
  pointer-events: none;
}
.train {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 0.7%;
}
.train.is-rolling { animation: trainBob 0.42s ease-in-out infinite; }
@keyframes trainBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-0.7%); }
}

.car, .engine {
  position: relative;
  flex: 0 0 auto;
  pointer-events: auto;
}
.car    { width: 20%;   aspect-ratio: 240 / 190; }
.engine { width: 25.3%; aspect-ratio: 300 / 190; }

.car svg, .engine svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.art-car-back  { z-index: 1; }
.art-car-front { z-index: 3; }

/* Wheels spin only while the train is actually moving. fill-box puts the
   rotation origin at the centre of each wheel group, so the art file never has
   to publish its coordinates to the stylesheet. */
.wheel { transform-box: fill-box; transform-origin: 50% 50%; }
.train.is-rolling .wheel { animation: spin 0.5s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* The anchor line cargo sits on inside a wagon: the top edge of the front
   face, so anything dropped in is half-swallowed by the box. */
.slot {
  position: absolute;
  left: 20%;
  width: 60%;
  bottom: 55.8%;
  height: 0;
  z-index: 2;
}

/* The whole wagon, and then some. Loading, this is the drop target; delivering,
   it is the HANDLE for whatever is riding inside — grab the wagon anywhere and
   you pull the cargo out. A five-year-old should not have to hit a strawberry.
   The negative top reaches up over the part of the cargo that pokes above the
   rim; the sides stay inside the coupling gap so neighbouring wagons never
   overlap and steal each other's grabs. */
.car-hit {
  position: absolute;
  inset: -22% -1.5% -6%;
  z-index: 4;
  padding: 0;
  border: 3px dashed transparent;
  border-radius: 14px;
  background: transparent;
  cursor: pointer;
  pointer-events: none;
  transition: background 0.18s, border-color 0.18s;
}
.scene[data-phase="load"] .car-hit { pointer-events: auto; }
.scene[data-phase="deliver"] .car.is-full .car-hit { pointer-events: auto; cursor: grab; }
.scene[data-phase="deliver"] .car.is-full .car-hit:active { cursor: grabbing; }
.scene[data-phase="load"].is-aiming .car-hit { border-color: rgba(255, 255, 255, 0.8); }
/* A loaded wagon stops offering itself. Three dashed boxes when only one is a
   real answer is three guesses; two is a choice. */
.car.is-full .car-hit { border-color: transparent !important; background: transparent !important; }
.car-hit.is-hover { border-color: #fff; background: rgba(255, 255, 255, 0.3); }
.car-hit.is-hint  { animation: hintPulse 1.1s ease-in-out infinite; }

.car.is-reject { animation: shake 0.34s ease; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-3%); }
  75%      { transform: translateX(3%); }
}

/* ── Cargo (bells, fruit, toys) ──────────────────────────────────────────── */
.cargo {
  position: relative;
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: grab;
  touch-action: none;
  /* Every cargo is square: the bell PNGs are 300×300 and the placeholder art
     boxes are 120×120. Stating it here rather than letting the content decide
     is load-bearing — an <img> gives an absolutely-positioned button an
     intrinsic height, but an inline <svg> (viewBox, no width/height) does NOT,
     so the button collapsed to zero and every fruit and toy rendered hanging
     out below the wagon while the bells looked perfect. */
  aspect-ratio: 1;
  filter: drop-shadow(0 3px 4px rgba(24, 40, 20, 0.28));
  transition: transform 0.16s ease, filter 0.16s ease;
}
.cargo svg, .cargo img {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;             /* the button is the target, never its art */
}
.cargo:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 4px;
  border-radius: 12px;
}

/* On the platform, waiting to be loaded. */
.platform .cargo { width: 30%; }
.platform .cargo::after {           /* contact shadow so it stands on the grass */
  content: "";
  position: absolute;
  left: 12%; right: 12%; bottom: -4%;
  height: 9%;
  border-radius: 50%;
  background: rgba(24, 60, 16, 0.22);
  z-index: -1;
}

/* Riding in a wagon. */
.car .cargo {
  position: absolute;
  left: 0;
  width: 100%;
  bottom: 0;
  transform: translateY(16%);
  filter: drop-shadow(0 2px 3px rgba(24, 40, 20, 0.34));
}
/* Hovering anywhere on a loaded wagon lifts its cargo — the affordance has to
   match the hit area, or the wagon looks inert right where it is grabbable. */
/* The only affordance telling a child this wagon can be grabbed — and on a
   touch screen :hover never fires, so it never appeared on the device the game
   is actually played on. Shown unconditionally where there is no hover. */
@media (hover: none) {
  .scene[data-phase="deliver"] .car.is-full .cargo { transform: translateY(8%); }
}
.scene[data-phase="deliver"] .car.is-full:hover .cargo { transform: translateY(8%); }

/* Delivered, standing in the yard. */
.yard .cargo { width: 31%; cursor: pointer; }

.cargo.is-selected {
  transform: translateY(-6%) scale(1.06);
  filter: drop-shadow(0 0 0 #fff) drop-shadow(0 6px 8px rgba(24, 40, 20, 0.34));
  animation: selectedBounce 0.9s ease-in-out infinite;
}
.car .cargo.is-selected { transform: translateY(6%) scale(1.06); }
@keyframes selectedBounce {
  0%, 100% { filter: drop-shadow(0 6px 8px rgba(24, 40, 20, 0.34)) brightness(1); }
  50%      { filter: drop-shadow(0 6px 8px rgba(24, 40, 20, 0.34)) brightness(1.13); }
}

/* In flight. Pointer-events off so the target underneath stays hit-testable —
   this is also exactly why the drag listeners live on window, not on the card. */
.cargo.is-floating {
  position: fixed;
  z-index: 9000;
  width: var(--drag-w);
  margin: 0;
  pointer-events: none;
  transform: rotate(-4deg) scale(1.08);
  filter: drop-shadow(0 12px 14px rgba(24, 40, 20, 0.4));
  transition: none;
}
.cargo.is-landing { animation: land 0.34s cubic-bezier(0.22, 1.4, 0.4, 1); }
@keyframes land {
  0%   { transform: translateY(-24%) scale(1.14); }
  100% { transform: translateY(16%) scale(1); }
}
.yard .cargo.is-landing { animation-name: landYard; }
@keyframes landYard {
  0%   { transform: translateY(-30%) scale(1.14); }
  100% { transform: translateY(0) scale(1); }
}

/* Ringing: a bell that just sounded. */
.cargo.is-ring { animation: ring 0.42s ease; }
@keyframes ring {
  0%, 100% { rotate: 0deg; }
  25%      { rotate: -7deg; }
  60%      { rotate: 5deg; }
}

/* Nothing is grabbable while the train is between stops. */
.scene[data-phase="travel"] .cargo,
.scene[data-phase="idle"] .cargo,
.scene[data-phase="done"] .cargo { pointer-events: none; }

/* After two wrong tries the right answer starts waving. No penalty, ever —
   the hint exists so a stuck child gets unstuck, not so we can measure them. */
.cargo.is-hint { animation: hintBob 0.9s ease-in-out infinite; }
@keyframes hintBob {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -8%; }
}

/* ── Conductor's line ────────────────────────────────────────────────────── */
.coach {
  position: absolute;
  left: 50%;
  top: 3.5%;
  transform: translateX(-50%);
  max-width: 78%;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.94);
  color: var(--ink);
  font-weight: 900;
  font-size: clamp(0.72rem, 1.9vw, 0.98rem);
  line-height: 1.25;
  text-align: center;
  box-shadow: 0 4px 12px rgba(27, 35, 62, 0.18);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.coach.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.coach.is-oops { background: #fff3d6; }
.coach b { color: var(--hl, var(--teal)); }

/* ── Status bar under the scene ──────────────────────────────────────────── */
.status-bar {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 4px;
}

.stop-name {
  font-weight: 900;
  font-size: clamp(0.82rem, 2.2vw, 0.98rem);
  color: var(--muted);
  min-width: 8ch;
  text-align: left;
}

.pips { display: flex; gap: 10px; }
.pip-group { display: flex; gap: 3px; }
.pip {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--pip);
  opacity: 0.24;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
  transition: opacity 0.24s ease, transform 0.24s ease;
}
.pip.is-done { opacity: 1; transform: scale(1.18); }

.status-tools { display: flex; gap: 6px; min-width: 8ch; justify-content: flex-end; }
.tool-btn {
  min-width: 44px;
  min-height: 44px;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 10px;
  border: 1.5px solid var(--line);
  background: var(--card);
  color: var(--muted);
  cursor: pointer;
}
.tool-btn:hover { color: var(--teal); border-color: var(--teal); }
.tool-btn svg { width: 17px; height: 17px; }
.tool-btn .ico-off { display: none; }
.tool-btn[aria-pressed="true"] .ico-on { display: none; }
.tool-btn[aria-pressed="true"] .ico-off { display: block; }

/* ── Win overlay ─────────────────────────────────────────────────────────── */
.win-overlay {
  position: fixed;
  inset: 0;
  z-index: 9500;
  display: grid;
  place-items: center;
  padding: 18px;
  background: rgba(18, 26, 48, 0.5);
  backdrop-filter: blur(3px);
  animation: fadeIn 0.24s ease;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.win-card {
  width: min(420px, 100%);
  background: var(--card);
  border-radius: 22px;
  padding: 22px 22px 20px;
  text-align: center;
  box-shadow: 0 18px 44px rgba(18, 26, 48, 0.36);
  animation: pop 0.34s cubic-bezier(0.2, 1.3, 0.4, 1);
}
@keyframes pop { from { transform: scale(0.86); opacity: 0; } to { transform: scale(1); opacity: 1; } }

.win-logo { width: 66px; height: auto; margin: 0 auto 4px; display: block; }
.win-card h2 { margin: 4px 0 2px; font-size: 1.42rem; font-weight: 900; }
.win-group { margin: 0; font-weight: 900; color: var(--teal); font-size: 1.06rem; }
.win-message { margin: 8px 0 0; color: var(--muted); font-weight: 800; font-size: 0.94rem; line-height: 1.35; }

.win-stars { display: flex; justify-content: center; gap: 6px; margin: 10px 0 0; }
.win-stars span { font-size: 1.6rem; line-height: 1; filter: grayscale(1) opacity(0.3); }
.win-stars span.on { filter: none; animation: pop 0.4s cubic-bezier(0.2, 1.5, 0.4, 1) backwards; }
.win-stars span.on:nth-child(2) { animation-delay: 0.12s; }
.win-stars span.on:nth-child(3) { animation-delay: 0.24s; }

/* The three notes, replayable, so the round ends on the sound not the score. */
.win-bells { display: flex; justify-content: center; gap: 8px; margin: 14px 0 4px; }
.win-bells button {
  width: 62px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  display: grid;
  justify-items: center;
  gap: 2px;
  font: inherit;
}
.win-bells img { width: 100%; height: auto; display: block; }
.win-bells span { font-weight: 900; font-size: 0.78rem; color: var(--muted); }
.win-bells button:hover img { transform: translateY(-3px); }
.win-bells img { transition: transform 0.14s ease; }

.win-actions { display: flex; gap: 8px; justify-content: center; margin-top: 14px; }

.action-btn {
  appearance: none;
  border: 0;
  font: inherit;
  font-weight: 900;
  font-size: 0.98rem;
  padding: 12px 20px;
  border-radius: 999px;
  cursor: pointer;
  transition: transform 0.1s ease, filter 0.15s ease;
}
.action-btn:active { transform: translateY(1px); }
.action-btn.primary { background: var(--teal); color: #fff; }
.action-btn.primary:hover { filter: brightness(1.08); }
.action-btn.ghost { background: #eef1f5; color: var(--ink); }

/* ── Confetti + sparkles ─────────────────────────────────────────────────── */
.confetti-layer { position: fixed; inset: 0; pointer-events: none; z-index: 9600; overflow: hidden; }
.confetti-piece {
  position: absolute;
  top: -24px;
  border-radius: 2px;
  animation: fall var(--confetti-duration, 2600ms) linear forwards;
}
@keyframes fall {
  to { transform: translate(var(--confetti-x, 0), 108vh) rotate(720deg); }
}

.fx { z-index: 6; overflow: hidden; }
.spark {
  position: absolute;
  width: 10px; height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: #fff;
  animation: sparkOut var(--spark-dur, 700ms) ease-out forwards;
}
@keyframes sparkOut {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  100% { transform: translate(var(--sx), var(--sy)) scale(0.2); opacity: 0; }
}

/* ── Score submit block spacing ──────────────────────────────────────────── */
#pk5ScoreSubmit:empty { display: none; }
#pk5ScoreSubmit { width: min(520px, 100%); margin: 0 auto; }

/* ── Motion ──────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .train.is-rolling,
  .train.is-rolling .art-car-front > circle,
  .train.is-rolling .art-engine > circle,
  .cargo.is-selected,
  .dropzone.is-hint,
  .car-hit.is-hint,
  .confetti-piece { animation: none !important; }
  .cargo, .stop, .coach { transition-duration: 0.01ms !important; }
}

/* ── Small screens ───────────────────────────────────────────────────────── */
@media (max-width: 640px) {
  .screen { padding: 12px 8px 24px; gap: 10px; }
  .scene { border-radius: 14px; }
  .stop-name { display: none; }
  .status-bar { justify-content: center; }
  .status-tools { min-width: 0; }

  /* Seven chips wrap to four rows on a phone and push the game off screen.
     One swipeable row instead — the active chip is scrolled into view by
     `scroll-margin` when a round starts. */
  .group-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    justify-content: flex-start;
    padding: 2px 8px 6px;
    margin: 0 -8px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .group-row::-webkit-scrollbar { display: none; }
  .group-btn { flex: 0 0 auto; scroll-margin-inline: 12px; }

  /* The bubble sits directly over the cargo on a small scene, so keep it thin. */
  .coach { max-width: 90%; padding: 6px 12px; font-size: 0.7rem; }
}

/* Desktop: PK5 sidebar mode. Keep the page on PK5 paper, not the game's blue. */
@media (min-width: 901px) {
  html, body { background: #f5f5f3; }
  .screen { padding: 28px 40px 48px; }
}
