:root {
  --bg: #0f1330;
  --panel: #181d44;
  --panel-2: #222958;
  --line: #333c78;
  --text: #f3f1ff;
  --muted: #aeb3dc;
  --accent: #ffd23f;
  --accent-2: #ff8fc0;
  --good: #7dffa0;
  --bad: #ff5f6d;
  --radius: 14px;
  --header-h: 48px;
  /* The screen's safe areas (docs/PLATFORMS.md, "Layout"): under a notch, a
     cut-out or the home indicator. What the player reads or touches stays
     inside them. The browser tests set these to try insets the browsers there
     don't have. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  /* The smallest text: 14 px on a desktop, 15 on a tablet, 13 on a phone. */
  --t-min: 14px;
  /* How far the controls keep from a screen's edge where the game meets it:
     16 px on a touch screen, so a thumb on a control never starts the home or
     back gesture. */
  --edge: 8px;
  color-scheme: dark;
}

/* A tablet: a touch screen at least 600 px each way. */
@media (pointer: coarse) {
  :root {
    --t-min: 15px;
    --edge: 16px;
  }
}

/* A phone: a touch screen under 600 px one way or the other. */
@media (pointer: coarse) and (max-width: 599px), (pointer: coarse) and (max-height: 599px) {
  :root {
    --t-min: 13px;
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Ubuntu, sans-serif;
  -webkit-text-size-adjust: 100%;
}

a {
  color: var(--accent);
}

button {
  font: inherit;
  color: inherit;
  touch-action: manipulation;
  cursor: pointer;
}

[hidden] {
  display: none !important;
}

.site-header {
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  border-bottom: 1px solid var(--line);
}

.site-header nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
}

/* The page keeps the game inside the side insets (a phone held sideways);
   the site header takes the top one. */
.page {
  padding: 8px max(8px, var(--safe-r)) 40px max(8px, var(--safe-l));
}

/* ---------- Game layout ----------

   The game fills the room it has: the page's width and the height under the
   site header, or the whole screen in full screen. Upright it stacks the HUD
   above and below the jar; on a wider screen (from 9:8) the HUD stands in
   columns beside it. The jar is drawn as big as its stage allows (render.js).

   --in-*: the safe areas that reach into the game. On the page the header
   takes the top one and the page's padding the sides; the bottom one reaches
   in where the game meets the screen's foot. In full screen all four do.
   --pad-*: how far the HUD's controls keep from the game's edges: the inset,
   and 16 px more on a touch screen where the game meets the screen's edge.
   --exit-band: the height the site's "Leave full screen" takes at the top
   in full screen (44 px, at max(8px, the top inset)), and 8 px below it. */
.game-root {
  --in-t: 0px;
  --in-r: 0px;
  --in-b: 0px;
  --in-l: 0px;
  --pad-t: 6px;
  --pad-r: 8px;
  --pad-b: 8px;
  --pad-l: 8px;
  --exit-band: calc(max(8px, var(--safe-t)) + 52px);
  position: relative;
  margin: 0 auto;
  width: 100%;
  height: calc(100vh - var(--header-h) - var(--safe-t) - var(--safe-b) - 16px);
  height: calc(100dvh - var(--header-h) - var(--safe-t) - var(--safe-b) - 16px);
  min-height: 460px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  grid-template-areas: 'a' 'ladder' 'stage' 'b';
  background: #121738;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  /* No scrolling, zooming, selection or long-press menu over the game
     (docs/PLATFORMS.md): a card that scrolls takes pan-y, and main.js
     prevents Safari's pinch and the context menu. The page around the game
     still zooms. */
  touch-action: none;
  overscroll-behavior: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

.panel {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--panel);
  min-width: 0;
  touch-action: none;
}

/* Upright: the score, best and chain in a row, Pause at its end, and the
   goal of a challenge or daily jar on a row of its own below them. The
   row's middle stays free: "Leave full screen" sits there in full screen. */
.panel-a {
  grid-area: a;
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto auto;
  grid-template-areas: 'score best . chain pause' 'goal goal goal goal goal';
  align-items: center;
  column-gap: 10px;
  padding: var(--pad-t) var(--pad-r) 6px var(--pad-l);
  border-bottom: 1px solid var(--line);
}

.stat-score {
  grid-area: score;
}

.stat-best {
  grid-area: best;
}

.panel-a .goal {
  grid-area: goal;
}

.panel-a .chain {
  grid-area: chain;
}

.btn-pause {
  grid-area: pause;
}

.panel-b {
  grid-area: b;
  justify-content: space-between;
  padding: 6px var(--pad-r) var(--pad-b) var(--pad-l);
  border-top: 1px solid var(--line);
}

/* The stage's padding is the safe area where it meets the screen's top or
   foot: the jar keeps out of it (render.js), its background fills it. */
.stage {
  grid-area: stage;
  position: relative;
  min-height: 0;
  overflow: hidden;
  touch-action: none;
}

.stage canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  outline: none;
  cursor: crosshair;
}

.stage canvas.pop-mode {
  cursor: pointer;
}

.label {
  display: block;
  font-size: var(--t-min);
  font-weight: 700;
  letter-spacing: 0.5px;
  line-height: 1.25;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

.stat .value {
  display: block;
  font-size: 22px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.stat-score {
  min-width: 70px;
}

.stat-best .value {
  font-size: 17px;
  color: var(--accent);
}

/* The goal: the jar's name, what it asks for and how far it has come, on as
   many lines as it takes. */
.goal {
  min-width: 0;
  margin-top: 6px;
}

.goal .label {
  display: inline;
  margin-right: 6px;
}

.goal-text {
  font-size: max(14px, var(--t-min));
  font-weight: 800;
  line-height: 1.3;
}

.goal-bar,
.chain-bar,
.meter {
  display: block;
  height: 7px;
  margin-top: 3px;
  border-radius: 5px;
  background: #0c1030;
  border: 1px solid var(--line);
  overflow: hidden;
}

.goal-bar i,
.chain-bar i,
.meter i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 5px;
  background: linear-gradient(90deg, #7dffa0, #d8ff7a);
  transition: width 0.2s ease-out;
}

.goal.done .goal-text {
  color: var(--good);
}

.chain {
  width: clamp(64px, 20vw, 150px);
  opacity: 0.35;
  transition: opacity 0.2s;
}

.chain.on {
  opacity: 1;
}

.chain-x {
  display: block;
  font-weight: 900;
  font-size: 18px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.chain-bar i {
  background: linear-gradient(90deg, #ffb347, #ffe36b);
  transition: none;
}

.chain.bump .chain-x {
  animation: bump 0.25s ease-out;
}

@keyframes bump {
  0% {
    transform: scale(1.35);
  }
}

.icon-btn {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  display: grid;
  place-items: center;
  padding: 0;
}

.icon-btn svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
  stroke: currentColor;
}

.icon-btn svg rect {
  stroke: none;
}

.btn-sound.off .waves {
  display: none;
}

.btn-sound.off svg {
  opacity: 0.55;
}

.ladder {
  grid-area: ladder;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 2px;
  margin: 0;
  padding: 4px max(6px, var(--in-r)) 4px max(6px, var(--in-l));
  list-style: none;
  background: #151a3e;
  border-bottom: 1px solid var(--line);
  touch-action: none;
}

.ladder li {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 1 30px;
  min-width: 0;
  opacity: 0.4;
  transition: opacity 0.3s, transform 0.3s;
}

.ladder li.made {
  opacity: 1;
}

.ladder li.top {
  transform: translateY(-2px) scale(1.12);
}

.ladder li + li::before {
  content: '';
  position: absolute;
  left: -3px;
  top: 50%;
  width: 3px;
  height: 2px;
  background: var(--line);
}

.ladder canvas {
  max-width: 100%;
  height: auto !important;
}

.slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 58px;
  min-height: 44px;
  padding: 4px 6px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--panel-2);
}

.slot-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
}

.slot-pocket.empty .slot-icon::after {
  content: '';
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px dashed rgba(255, 255, 255, 0.3);
}

.slot-pocket:disabled {
  opacity: 0.4;
}

.slot-pocket.flash {
  animation: flash 0.3s ease-out;
}

@keyframes flash {
  0% {
    box-shadow: 0 0 0 3px rgba(255, 210, 63, 0.8);
  }
}

.tools {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.tool {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 52px;
  min-height: 44px;
  padding: 5px 6px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  font-size: max(14px, var(--t-min));
  font-weight: 800;
  line-height: 1.2;
}

.tool svg {
  width: 22px;
  height: 22px;
  fill: #ffd23f;
  stroke: #7fdcff;
}

.tool:disabled {
  opacity: 0.4;
  cursor: default;
}

.tool.active {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent) inset;
}

.tool.ready:not(:disabled) {
  border-color: #ffe36b;
}

.charges {
  width: 54px;
}

.pips {
  display: flex;
  gap: 4px;
  justify-content: center;
}

.pips b {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 1.5px solid #ffe36b;
}

.pips b.on {
  background: #ffe36b;
  box-shadow: 0 0 6px rgba(255, 227, 107, 0.8);
}

.meter i {
  background: linear-gradient(90deg, #ffb347, #ffe36b);
}

/* Key names, in the HUD's buttons. Hints follow the last input used
   (main.js sets html.wj-touch after a touch): a touch hides them, a key or
   the mouse shows them again. */
.key {
  display: inline-block;
  padding: 0 4px;
  border-radius: 4px;
  border: 1px solid var(--line);
  background: #0f1330;
  font: 700 var(--t-min) / 1.3 system-ui, sans-serif;
  letter-spacing: 0;
  color: var(--muted);
  text-transform: none;
  vertical-align: 1px;
}

.wj-touch .key {
  display: none;
}

.game-toast {
  position: absolute;
  left: 50%;
  top: 10px;
  transform: translateX(-50%);
  max-width: min(92%, 420px);
  pointer-events: none;
  z-index: 3;
}

.game-toast div {
  margin-bottom: 6px;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(16, 12, 40, 0.88);
  border: 1px solid var(--line);
  font-size: max(14px, var(--t-min));
  font-weight: 700;
  text-align: center;
  line-height: 1.35;
  animation: toast-in 0.25s ease-out;
}

.game-toast div.out {
  opacity: 0;
  transition: opacity 0.4s;
}

.game-toast .discover {
  display: flex;
  align-items: center;
  gap: 8px;
  border-color: #ffe36b;
}

@keyframes toast-in {
  0% {
    transform: translateY(-8px);
    opacity: 0;
  }
}

/* Behind a card nothing moves: the HUD's little animations wait too. */
.game-root.covered .panel *,
.game-root.covered .ladder * {
  animation-play-state: paused;
}

/* ---------- A phone held upright ----------

   In play the game takes the screen's whole height, the site header
   scrolled away above it (main.js), so the jar gets every pixel the HUD
   leaves; a card over the game (the title, the menus, pause, the results)
   fits under the header, so its "Full screen" shows. The game runs edge to
   edge, its controls 16 px inside the safe areas and 24 px from two of the
   screen's edges at once: a phone's rounded corners. */
@media (max-aspect-ratio: 9/8) and (max-width: 599px) {
  .page {
    padding: 0 var(--safe-r) 32px var(--safe-l);
  }
  .game-root {
    --in-b: var(--safe-b);
    --pad-t: max(24px, calc(var(--safe-t) + var(--edge)));
    --pad-r: max(8px, var(--edge));
    --pad-l: max(8px, var(--edge));
    --pad-b: max(24px, calc(var(--safe-b) + var(--edge)));
    border-radius: 0;
    border-width: 0;
    height: 100vh;
    height: 100dvh;
  }
  .game-root.covered {
    height: calc(100vh - var(--header-h) - var(--safe-t));
    height: calc(100dvh - var(--header-h) - var(--safe-t));
  }
  .panel-a {
    column-gap: 8px;
    padding-bottom: 4px;
  }
  .goal {
    margin-top: 4px;
  }
  .goal-bar {
    height: 6px;
    margin-top: 2px;
  }
  .ladder {
    padding-top: 3px;
    padding-bottom: 3px;
  }
  .ladder li {
    flex-basis: 27px;
  }
  .panel-b {
    padding-top: 4px;
  }
  .slot {
    min-width: 50px;
    padding: 3px 4px;
  }
  .slot .label {
    line-height: 1.15;
  }
  .slot-icon {
    width: 32px;
    height: 32px;
  }
  .tool {
    min-width: 50px;
    padding: 4px;
  }
  .charges {
    width: 42px;
  }
}

/* ---------- A tablet held upright, or a narrow desktop window ----------

   The HUD's row has room for the goal in its middle. In full screen the
   middle is "Leave full screen"'s, and the goal takes a row of its own. */
@media (max-aspect-ratio: 9/8) and (min-width: 600px) {
  .panel-a {
    grid-template-areas: 'score best goal chain pause';
  }
  .panel-a .goal {
    margin-top: 0;
  }
  .game-root.is-fs .panel-a {
    grid-template-areas: 'score best . chain pause' 'goal goal goal goal goal';
  }
  .game-root.is-fs .panel-a .goal {
    margin-top: 6px;
  }
}

/* ---------- Columns beside the jar (a screen wider than 9:8) ---------- */

@media (min-aspect-ratio: 9/8) {
  .game-root {
    /* Wide enough for the jar at the screen's height, and the columns. */
    max-width: max(1080px, calc(68dvh + 380px));
    grid-template-columns: minmax(150px, 210px) minmax(0, 1fr) minmax(150px, 210px);
    grid-template-rows: minmax(0, 1fr) auto;
    grid-template-areas: 'a stage b' 'ladder stage b';
  }
  .panel {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: 10px;
  }
  .stage {
    padding: var(--in-t) 0 var(--in-b);
  }
  .panel-a {
    display: flex;
    padding: max(12px, var(--pad-t)) 12px 12px max(12px, var(--pad-l));
    border-bottom: 0;
    border-right: 1px solid var(--line);
  }
  .panel-b {
    padding: max(12px, var(--pad-t)) max(12px, var(--pad-r)) max(12px, var(--pad-b)) 12px;
    border-top: 0;
    border-left: 1px solid var(--line);
  }
  .stat .value {
    font-size: 30px;
  }
  .stat-best .value {
    font-size: 20px;
  }
  .chain {
    width: auto;
    flex: 0 0 auto;
  }
  .goal {
    margin-top: 0;
  }
  .goal .label {
    display: block;
    margin: 0;
  }
  .btn-pause {
    margin: auto 0 0;
    width: 100%;
  }
  .ladder {
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 4px;
    padding: 10px 12px max(10px, var(--pad-b)) max(12px, var(--pad-l));
    border-bottom: 0;
    border-right: 1px solid var(--line);
    background: var(--panel);
  }
  .ladder li {
    flex: 0 0 calc((100% - 16px) / 5);
  }
  .ladder li + li::before {
    display: none;
  }
  .slot {
    flex-direction: row;
    justify-content: space-between;
    padding: 8px 10px;
  }
  .slot-icon {
    width: 48px;
    height: 48px;
  }
  .tools {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .tool {
    flex-direction: row;
    justify-content: flex-start;
    gap: 8px;
    padding: 8px 10px;
  }
  .charges {
    width: auto;
  }
  .btn-sound {
    margin-top: auto;
    width: 100%;
  }
}

/* ---------- A phone held sideways (a short, wide screen) ----------

   As upright: in play the game takes the screen's whole height, the site
   header scrolled away above it, and a card fits under the header. The jar
   gets the height it can have: the columns take what the jar's width
   leaves, the HUD two to a row in each. The page keeps the side insets (the
   notch), and the controls keep 24 px from the screen's top and foot where
   they meet a side: a phone's rounded corners. */
@media (min-aspect-ratio: 9/8) and (max-height: 540px) {
  .page {
    padding: 0 var(--safe-r) 32px var(--safe-l);
  }
  .game-root {
    --in-t: var(--safe-t);
    --in-b: var(--safe-b);
    --pad-t: max(24px, calc(var(--safe-t) + var(--edge)));
    --pad-r: max(8px, var(--edge));
    --pad-b: max(24px, calc(var(--safe-b) + var(--edge)));
    --pad-l: max(8px, var(--edge));
    max-width: none;
    height: 100vh;
    height: 100dvh;
    min-height: 240px;
    border-radius: 0;
    border-width: 0;
    grid-template-columns: minmax(180px, 1fr) minmax(0, calc(var(--view-aspect, 0.68) * 100dvh + 8px)) minmax(180px, 1fr);
  }
  .game-root.covered {
    height: calc(100vh - var(--header-h) - var(--safe-t));
    height: calc(100dvh - var(--header-h) - var(--safe-t));
  }
  .panel {
    gap: 8px;
  }
  .panel-a {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: 'score pause' 'best chain' 'goal goal';
    align-content: start;
    align-items: center;
    gap: 6px 8px;
    padding: var(--pad-t) 8px 6px var(--pad-l);
  }
  .stat .value {
    font-size: 22px;
  }
  .stat-best .value {
    font-size: 17px;
  }
  .btn-pause {
    width: 44px;
    margin: 0;
  }
  .chain {
    width: 76px;
  }
  .ladder {
    gap: 4px;
    padding: 6px 8px var(--pad-b) var(--pad-l);
  }
  .ladder li {
    flex: 0 0 calc((100% - 20px) / 6);
  }
  .panel-b {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr);
    align-items: start;
    gap: 8px;
    padding: var(--pad-t) var(--pad-r) var(--pad-b) 8px;
  }
  .slot {
    flex-direction: column;
    justify-content: flex-start;
    min-width: 0;
    padding: 4px;
  }
  .slot-icon {
    width: 34px;
    height: 34px;
  }
  .tools {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px;
  }
  .tool {
    flex-direction: row;
    justify-content: center;
    gap: 6px;
    min-width: 0;
    padding: 4px 6px;
  }
  .charges {
    grid-column: 1 / -1;
  }
  .btn-sound {
    grid-column: 1 / -1;
    align-self: end;
  }
}

/* ---------- Full screen (the site's button; main.js sets .is-fs) ----------

   The game fills the screen edge to edge, and everything keeps inside the
   screen's safe areas, the controls 16 px further in on a touch screen.
   "Leave full screen" stays at the top in the middle while the HUD is above
   the jar: the HUD's row leaves its middle free, and on a phone it moves
   down below the button. Beside the jar, the top middle is where the dropper
   holds the next wobble, so the button moves to the top of the right column
   (the game's own rule for .am-fs-exit, docs/PLATFORMS.md). A card always
   starts below it. */
.game-root.is-fs {
  --in-t: var(--safe-t);
  --in-r: var(--safe-r);
  --in-b: var(--safe-b);
  --in-l: var(--safe-l);
  --pad-t: calc(var(--safe-t) + var(--edge));
  --pad-r: calc(var(--safe-r) + var(--edge));
  --pad-b: calc(var(--safe-b) + var(--edge));
  --pad-l: calc(var(--safe-l) + var(--edge));
  max-width: none;
  max-height: none;
  border: 0;
  border-radius: 0;
}

#game-root > .am-fs-exit {
  top: max(8px, var(--safe-t));
}

.game-root.is-fs .panel-a {
  padding-top: max(var(--pad-t), calc(var(--exit-band) - 44px));
}

.game-root.is-fs .overlay {
  padding-top: var(--exit-band);
}

/* A phone in full screen: its corners keep 24 px clear, as on the page. */
@media (max-aspect-ratio: 9/8) and (max-width: 599px), (min-aspect-ratio: 9/8) and (max-height: 540px) {
  .game-root.is-fs {
    --pad-t: max(24px, calc(var(--safe-t) + var(--edge)));
    --pad-b: max(24px, calc(var(--safe-b) + var(--edge)));
  }
}

@media (max-aspect-ratio: 9/8) and (max-width: 599px) {
  .game-root.is-fs .panel-a {
    padding-top: var(--exit-band);
  }
}

@media (min-aspect-ratio: 9/8) {
  .game-root.is-fs .panel-a {
    padding-top: var(--pad-t);
  }
  .game-root.is-fs .panel-b {
    padding-top: var(--exit-band);
  }
  #game-root.is-fs > .am-fs-exit {
    left: auto;
    right: max(24px, calc(var(--safe-r) + 16px));
  }
}

/* ---------- Overlay screens ---------- */

.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(12px, var(--in-t)) max(12px, var(--in-r)) max(12px, calc(var(--in-b) + 8px)) max(12px, var(--in-l));
  background: rgba(8, 8, 28, 0.7);
  overflow-y: auto;
  z-index: 5;
  touch-action: pan-y;
}

.overlay:empty {
  display: none;
}

.overlay.clear {
  background: linear-gradient(180deg, rgba(8, 8, 28, 0.2), rgba(8, 8, 28, 0.55));
}

.card {
  position: relative;
  width: 100%;
  max-width: 440px;
  max-height: 100%;
  overflow-y: auto;
  margin: auto;
  background: linear-gradient(180deg, rgba(40, 46, 104, 0.97), rgba(24, 28, 70, 0.97));
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 18px;
  text-align: center;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
  animation: pop 0.22s ease-out;
  touch-action: pan-y;
}

.card.wide {
  max-width: 560px;
}

/* A card's text scrolls by itself when it is longer than the screen (a
   returning player's results with several awards): its buttons stay in
   reach below it, or beside it on a short screen. */
.card.split {
  display: flex;
  flex-direction: column;
}

.card.split > .card-info {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
}

.card.split > .menu,
.card.split > .row-buttons {
  flex: 0 0 auto;
}

.card,
.overlay {
  overscroll-behavior: contain;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  list-style: none;
  padding: 0;
  margin: 6px 0;
}

.chips li {
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(125, 255, 160, 0.12);
  color: var(--good);
  font-size: var(--t-min);
  font-weight: 800;
}

.chips li span {
  font-weight: 600;
  color: var(--muted);
}

@keyframes pop {
  0% {
    transform: scale(0.92);
    opacity: 0;
  }
}

.card h2 {
  margin: 0 0 6px;
  font-size: 26px;
}

.card h3 {
  margin: 14px 0 6px;
  font-size: max(15px, var(--t-min));
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}

.card p {
  color: var(--muted);
  margin: 6px 0;
  line-height: 1.45;
}

.logo {
  margin: 2px 0 4px;
  font-size: clamp(34px, 9vw, 52px);
  font-weight: 900;
  letter-spacing: 1px;
  line-height: 1;
}

.logo span {
  display: inline-block;
  animation: wob 2.4s ease-in-out infinite;
  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.25);
}

@keyframes wob {
  0%,
  100% {
    transform: translateY(0) scale(1, 1);
  }
  40% {
    transform: translateY(-3px) scale(0.96, 1.05);
  }
  55% {
    transform: translateY(1px) scale(1.06, 0.94);
  }
}

.tagline {
  font-weight: 700;
  color: var(--text) !important;
}

.menu {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 290px;
  margin: 14px auto 0;
}

.menu-row {
  display: flex;
  gap: 10px;
}

.menu-row .btn {
  flex: 1 1 0;
}

.btn {
  min-height: 44px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  border-radius: 12px;
  padding: 10px 14px;
  font-weight: 800;
}

.btn small {
  display: block;
  font-weight: 600;
  font-size: var(--t-min);
  color: var(--muted);
  margin-top: 2px;
}

.btn:hover {
  border-color: var(--muted);
}

.btn:focus-visible,
.icon-btn:focus-visible,
.tool:focus-visible,
.slot:focus-visible,
.lvl:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.btn-primary {
  background: linear-gradient(180deg, #ffe07a, #ffb52e);
  color: #3b2200;
  border-color: #ffd23f;
  font-size: 18px;
  padding: 12px 22px;
  box-shadow: 0 4px 0 #b07000;
}

.btn-primary small {
  color: #6b4a10;
}

.btn-primary:active {
  transform: translateY(2px);
  box-shadow: 0 2px 0 #b07000;
}

.btn:disabled {
  opacity: 0.45;
  cursor: default;
}

.row-buttons {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 14px;
}

.big-score {
  font-size: 40px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.badge {
  display: inline-block;
  margin: 4px 0;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(255, 210, 63, 0.18);
  color: var(--accent);
  font-weight: 800;
  font-size: var(--t-min);
}

.badge.good {
  background: rgba(125, 255, 160, 0.16);
  color: var(--good);
}

.facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin: 12px 0 4px;
}

.facts div {
  padding: 8px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.05);
  font-size: var(--t-min);
  color: var(--muted);
}

.facts b {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font-size: 18px;
  color: var(--text);
}

.list {
  list-style: none;
  padding: 0;
  margin: 8px 0;
  text-align: left;
}

.list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: 10px;
  margin-bottom: 4px;
  background: rgba(255, 255, 255, 0.04);
}

.list li.got {
  background: rgba(125, 255, 160, 0.1);
}

.list li.locked {
  opacity: 0.55;
}

.list small {
  display: block;
  font-size: var(--t-min);
  color: var(--muted);
}

.list .tick {
  flex: 0 0 22px;
  font-weight: 900;
  color: var(--good);
  text-align: center;
}

/* The merge order with every wobble's name, in How to play: what the HUD's
   ladder tells a mouse in its tooltips. */
.order {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 4px;
  list-style: none;
  padding: 0;
  margin: 8px 0;
}

.order li {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 64px;
  font-size: var(--t-min);
  line-height: 1.2;
  color: var(--muted);
}

.collection {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 8px;
  margin-top: 10px;
}

.collection div {
  padding: 8px 6px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  font-size: var(--t-min);
  color: var(--muted);
}

.collection b {
  display: block;
  color: var(--text);
  font-size: calc(var(--t-min) + 1px);
  margin-top: 2px;
}

.collection small {
  display: block;
  margin-top: 4px;
  font-size: var(--t-min);
}

.collection .unknown b {
  color: var(--muted);
}

.worlds section {
  margin-top: 12px;
  text-align: left;
}

.worlds h3 {
  display: flex;
  justify-content: space-between;
  margin: 0 0 6px;
}

.worlds h3 small {
  font-size: var(--t-min);
}

.levels {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}

.lvl {
  aspect-ratio: 1;
  min-height: 44px;
  border-radius: 14px;
  border: 2px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.07);
  font-weight: 900;
  font-size: 17px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0;
}

.lvl .st {
  font-size: var(--t-min);
  letter-spacing: -1px;
  color: #ffd23f;
  line-height: 1;
  min-height: 1em;
}

.lvl:disabled {
  opacity: 0.35;
  cursor: default;
}

.lvl.current {
  background: linear-gradient(180deg, #ffe07a, #ffb52e);
  color: #3b2200;
  border-color: #fff;
}

.lvl.current .st {
  color: #7a4a00;
}

.goal-card {
  margin: 10px 0;
  padding: 12px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  font-size: 18px;
  font-weight: 800;
}

.goal-card small {
  display: block;
  margin-top: 4px;
  font-size: var(--t-min);
  font-weight: 600;
  color: var(--muted);
}

.tip {
  background: rgba(255, 255, 255, 0.06);
  border-radius: 10px;
  padding: 8px 10px;
  color: var(--text) !important;
}

.stars {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin: 10px 0;
}

.star {
  width: 50px;
  height: 50px;
  clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  background: #3c4278;
}

.star.lit {
  background: #ffd23f;
  animation: pop 0.3s ease-out;
}

.star:nth-child(2) {
  transform: translateY(-8px) scale(1.12);
}

.star-marks {
  font-size: var(--t-min);
  color: var(--muted);
}

/* A switch is pressed by its whole row: 48 px tall, 8 px from the next. */
.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 48px;
  margin-bottom: 8px;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  text-align: left;
  cursor: pointer;
}

.toggle-row input {
  width: 22px;
  height: 22px;
  accent-color: #ffd23f;
}

.styles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px;
  margin-top: 8px;
}

.style-opt {
  padding: 10px 8px;
  border-radius: 12px;
  border: 2px solid transparent;
  text-align: left;
  font-size: max(14px, var(--t-min));
  font-weight: 800;
  min-height: 64px;
}

.style-opt small {
  display: block;
  font-weight: 600;
  font-size: var(--t-min);
  color: rgba(255, 255, 255, 0.75);
}

.style-opt.on {
  border-color: #ffd23f;
}

.style-opt:disabled {
  opacity: 0.55;
  cursor: default;
}

.ad-in-card {
  margin-top: 14px;
}

.share-note {
  font-size: var(--t-min);
  min-height: 18px;
}

/* ---------- Ads & page ---------- */

.ad-slot {
  max-width: 970px;
  margin: 12px auto 0;
  min-height: 0;
}

.about {
  max-width: 820px;
  margin: 24px auto 0;
  color: var(--muted);
  line-height: 1.55;
  font-size: 15px;
}

.about h1,
.about h2 {
  color: var(--text);
}

kbd {
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0 5px;
  font-size: 12px;
  color: var(--text);
}

@media (max-width: 520px) {
  .about {
    padding: 0 12px;
  }
  .card {
    padding: 14px;
  }
}

/* Short screens (a phone held sideways): cards tighten up, and a card's two
   halves sit side by side, what it says and what can be done, so it fits
   under the site header (or below "Leave full screen") without scrolling. */
@media (max-height: 540px) {
  .overlay {
    padding-top: max(8px, var(--in-t));
    padding-bottom: max(8px, calc(var(--in-b) + 8px));
  }
  .card {
    padding: 12px 16px;
  }
  .card h2 {
    font-size: 20px;
    margin-bottom: 2px;
  }
  .card h3 {
    margin: 8px 0 4px;
    font-size: var(--t-min);
  }
  .card p {
    margin: 3px 0;
  }
  .logo {
    font-size: 34px;
  }
  .big-score {
    font-size: 30px;
  }
  .facts {
    grid-template-columns: repeat(4, 1fr);
    margin: 8px 0 2px;
  }
  .facts div {
    padding: 5px 4px;
  }
  .facts b {
    font-size: 15px;
  }
  .goal-card {
    margin: 6px 0;
    padding: 8px 10px;
    font-size: 16px;
  }
  .stars {
    margin: 4px 0;
  }
  .star {
    width: 36px;
    height: 36px;
  }
  .row-buttons {
    margin-top: 10px;
  }
  .ad-in-card {
    display: none;
  }
}

@media (max-height: 540px) and (min-aspect-ratio: 9/8) {
  .game-root.is-fs .overlay {
    padding-top: var(--exit-band);
  }
  .card.split {
    flex-direction: row;
    align-items: stretch;
    gap: 18px;
    max-width: 680px;
  }
  .card.split > .card-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
  }
  /* Short text sits in the middle; long text scrolls from its top. */
  .card.split > .card-info > :first-child {
    margin-top: auto;
  }
  .card.split > .card-info > :last-child {
    margin-bottom: auto;
  }
  .card.split > .card-info > .badge {
    align-self: center;
  }
  .card.split > .menu,
  .card.split > .row-buttons {
    flex: 0 0 auto;
    align-self: center;
    margin: 0;
  }
  .card.split > .row-buttons {
    flex-direction: column;
    flex-wrap: nowrap;
    min-width: 150px;
  }
  .card.split > .menu {
    display: grid;
    grid-template-columns: repeat(2, minmax(140px, 1fr));
    gap: 8px;
    max-width: none;
  }
  .card.split > .menu .menu-row {
    display: contents;
  }
  .card.split .btn {
    min-height: 44px;
    padding: 6px 12px;
  }
  .card.split .btn small {
    margin-top: 0;
  }
  .card.split .btn-primary {
    font-size: 17px;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Calm decoration; action and result feedback keep their timing. */
  .logo span, .slot-pocket.flash, .card, .game-toast div { animation: none; }
  .game-toast div, .hud-piece, .slot { transition: none; }
}

/* Short upright screens need the height for the jar. The merge order is
   still named in How to play and Wobbles; its decorative HUD row yields
   to the play area. Keep every action, with compact 44 px controls. */
@media (max-aspect-ratio: 9/8) and (max-width: 599px) and (max-height: calc(240px + 140vw)) {
  .stage canvas {
    --jar-foot: 0.6;
  }
  .game-root:not(.covered) {
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas: 'a' 'stage' 'b';
  }
  .game-root:not(.covered) .ladder {
    display: none;
  }
  .game-root:not(.covered) .panel-b .slot {
    min-height: 44px;
    gap: 0;
    padding: 2px 4px;
  }
  .game-root:not(.covered) .slot-icon {
    width: 24px;
    height: 24px;
  }
  .game-root:not(.covered) .slot-icon canvas {
    max-width: 100%;
    max-height: 100%;
  }
  .game-root:not(.covered) .tool {
    flex-direction: row;
    gap: 4px;
    min-height: 44px;
  }
  .game-root.is-fs:not(.covered) .panel-a {
    padding-top: max(20px, calc(var(--safe-t) + var(--edge)));
    padding-right: calc(max(24px, calc(var(--safe-r) + 16px)) + 52px);
    column-gap: 6px;
  }
  .game-root.is-fs:not(.covered) .chain {
    width: 44px;
  }
  #game-root.is-fs:not(.covered) > .am-fs-exit {
    left: auto;
    right: max(24px, calc(var(--safe-r) + 16px));
    top: max(20px, calc(var(--safe-t) + var(--edge)));
  }
}
