.app {
  max-width: 1100px;
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  padding: 12px 14px max(12px, env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow: hidden;
}

/* Top bar: back, score board, sound + pause. On narrow screens the score board gets its own row. */
.topbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mini-logo { display: none; margin: 0; font-size: clamp(1.25rem, 6.2vw, 1.9rem); text-align: center; white-space: nowrap; }
.hud { flex: 1; min-width: 0; max-width: 460px; display: grid; grid-template-columns: 0.8fr 1fr 1.2fr; padding: 6px 10px; }
.stat { min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.1; }
.stat b { font-size: 1.3rem; font-variant-numeric: tabular-nums; }
.stat small { font-size: 0.78rem; font-weight: 600; color: var(--muted); white-space: nowrap; }
.stat + .stat { border-left: 2px dashed var(--cream-2); }
.mini-stars { display: flex; gap: 2px; height: 1.55rem; align-items: center; }
.mini-stars span { width: 1.35rem; height: 1.35rem; line-height: 0; transition: filter 0.3s ease, opacity 0.3s ease; }
.mini-stars span:nth-child(2) { width: 1.55rem; height: 1.55rem; }
.mini-stars span:not(.on) { filter: grayscale(1); opacity: 0.3; }
.bump { animation: bump 0.4s ease; }
#pause-btn svg { display: block; }

/* The field: a canvas sized by game.js to fit the room that is left. */
.board {
  flex: 1;
  min-height: 0;
  display: grid;
  place-items: center;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  outline: none;
}
.board:focus-visible .frame { box-shadow: 0 0 0 4px #fff, 0 0 0 8px #2d8dff; }
/* The window round the field (drawn by game.js from world.js): a porthole, an airship window or a
   rocket window, depending on the world of the level. */
.frame { position: relative; padding: 10px; border-radius: 32px; box-shadow: 0 22px 30px -14px rgba(20, 10, 50, 0.55); }
.frame-art { position: absolute; left: 0; top: 0; display: block; pointer-events: none; }
.frame.shake { animation: shake 0.4s ease; }
.field {
  position: relative;
  border-radius: 22px;
  overflow: hidden;
}
.field canvas { display: block; }
/* a narrow field (phones on their side) gets a smaller tip card */
.field { container-type: inline-size; }
@container (max-width: 300px) {
  .tip { padding: 8px 10px 8px 8px; gap: 8px; }
  .tip-icon { width: 38px; height: 38px; }
  .tip-text { font-size: 0.82rem; }
  .banner { font-size: 1.2rem; }
  .banner.levelup { font-size: 1.5rem; }
}

/* A see-through button over the "next" bubble: tapping it swaps */
.swap {
  position: absolute;
  width: var(--s, 48px);
  height: var(--s, 48px);
  translate: -50% -50%;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.swap:focus-visible { outline: 3px solid #2d8dff; outline-offset: 0; }

/* Level 1: a hand that shows how to aim */
.hint {
  position: absolute;
  left: 50%;
  bottom: 24%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  translate: -50% 0;
  pointer-events: none;
  text-align: center;
}
.hint-hand { line-height: 0; animation: hint-swipe 2.4s ease-in-out infinite; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.12)); }
.hint-text {
  padding: 6px 14px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 3px 0 var(--cream-dark);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.2;
  color: var(--ink);
  white-space: nowrap;
}

/* A friendly card that explains a special bubble */
.tip {
  position: absolute;
  left: 50%;
  top: 14%;
  width: min(330px, calc(100% - 24px));
  translate: -50% 0;
  margin: 0;
  padding: 10px 14px 10px 10px;
  display: flex;
  align-items: center;
  gap: 10px;
  box-shadow: 0 0 0 4px var(--lemon), var(--panel-shadow);
  cursor: pointer;
  animation: tip-in 0.4s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.tip.out { animation: tip-out 0.3s ease forwards; }
.tip-icon { flex: none; width: 52px; height: 52px; }
.tip-text { margin: 0; font-weight: 500; line-height: 1.3; color: var(--ink); }
.tip-text b { color: var(--pink-dark); }

/* Messages over the field: combo, "Pfoe!", level done */
.banner {
  position: absolute;
  left: 50%;
  top: 40%;
  padding: 6px 20px;
  border: 4px solid #fff;
  border-radius: 999px;
  font-size: 1.6rem;
  font-weight: 700;
  white-space: nowrap;
  color: #fff;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.18);
  box-shadow: 0 5px 0 rgba(58, 31, 74, 0.25);
  pointer-events: none;
  z-index: 3;
}
.banner.combo {
  background: linear-gradient(90deg, #ff4b55, #ff922b, #ffcf2e, #4fc92f, #3a9bff, #a066f0);
  animation: combo 1.1s ease-out forwards;
}
.banner.toast {
  top: 30%;
  font-size: 1.25rem;
  background: linear-gradient(180deg, #ff7a82, #e5303b);
  animation: toast 1.7s ease forwards;
}
.banner.levelup {
  top: 32%;
  padding: 8px 26px;
  font-size: 2.1rem;
  background: linear-gradient(180deg, #ffe066, #ffb703 60%, #f08c00);
  text-shadow: 0 2px 0 #b86a00;
  box-shadow: 0 6px 0 #b86a00, 0 0 0 6px rgba(255, 224, 102, 0.35), 0 12px 30px rgba(255, 190, 40, 0.6);
  animation: levelup 1.7s ease-out forwards;
}

/* Confetti when a level is won */
.confetti { position: fixed; inset: 0; z-index: 45; overflow: hidden; pointer-events: none; }
.confetti i { position: absolute; top: -20px; width: 9px; height: 15px; border-radius: 2px; animation: fall 2.4s cubic-bezier(0.25, 0.4, 0.6, 1) forwards; }
.confetti i.round { width: 11px; height: 11px; border-radius: 50%; }

/* End card and pause */
.modal { position: fixed; inset: 0; z-index: 40; display: grid; place-items: center; padding: 14px; background: rgba(110, 63, 196, 0.45); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.sheet { width: min(400px, 100%); max-height: calc(100dvh - 28px); overflow-y: auto; padding: 18px 18px 20px; display: flex; flex-direction: column; gap: 10px; text-align: center; animation: pop-in 0.3s ease; }
.over-icon { display: flex; justify-content: center; line-height: 0; }
.over-title { margin: 0; font-size: 1.6rem; font-weight: 700; line-height: 1.2; outline: none; }
.over-title.record { color: var(--pink-dark); animation: bump 0.6s ease 0.2s; }
.over-stars { display: flex; justify-content: center; gap: 6px; line-height: 0; }
.over-stars:empty { display: none; }
.over-stars span { width: 46px; height: 46px; animation: star-in 0.45s cubic-bezier(0.2, 1.5, 0.4, 1) backwards; }
.over-stars span:nth-child(2) { width: 58px; height: 58px; margin-top: -10px; animation-delay: 0.15s; }
.over-stars span:nth-child(3) { animation-delay: 0.3s; }
.over-stars.fx span { animation: none; } /* ArcadeFx pops them in instead */
.over-stars span:not(.on) { filter: grayscale(1); opacity: 0.3; }
.over-text { color: var(--muted); font-weight: 500; line-height: 1.45; }
.over-text p { margin: 0 0 8px; }
.over-text p:last-child { margin: 8px 0 0; }
.over-text b { color: var(--ink); }
.over-text .over-news { margin: 0 0 8px; padding: 6px 10px; border-radius: 14px; background: #ebfadf; color: #2c7a14; font-weight: 700; }
.over-text table { width: 100%; border-collapse: collapse; color: var(--ink); }
.over-text td { padding: 4px 6px; text-align: left; }
.over-text td:last-child { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
.over-text tr + tr td { border-top: 2px dashed var(--cream-2); }
.over-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 6px; }
.over-actions .btn { flex: 1 1 120px; padding-left: 12px; padding-right: 12px; font-size: 1.1rem; white-space: nowrap; }
.over-actions .btn:first-child { flex-basis: 100%; }
.pause-actions { display: flex; flex-direction: column; gap: 14px; margin-top: 6px; }

/* Level map: three worlds, each a winding path of ten bubbles */
.map {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  background: var(--theme-sky, #bfe2ff) var(--theme-bg, url("../../assets/candy-bg.svg")) center bottom / cover no-repeat;
}
.map-head {
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(560px, 100%);
  margin: 0 auto;
  padding: 12px 14px 8px;
}
.map-title { flex: 1; min-width: 0; margin: 0; padding: 8px 16px; border-radius: 999px; font-size: 1.35rem; text-align: center; white-space: nowrap; }
.map-total { margin: 0; padding: 6px 14px; border-radius: 999px; font-size: 1.1rem; font-weight: 700; white-space: nowrap; }
.map-scroll { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 4px 14px max(24px, env(safe-area-inset-bottom)); }
.map-inner { width: min(460px, 100%); margin: 0 auto; display: flex; flex-direction: column; gap: 10px; }
.world-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 8px 0 0;
  padding: 8px 16px 8px 10px;
  font-size: 1.3rem;
  line-height: 1.1;
}
.world-head small { display: block; font-size: 0.8rem; font-weight: 600; color: var(--muted); }
.world-art { display: grid; place-items: center; width: 50px; height: 50px; flex: none; border-radius: 50%; background: #fff; box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.06); }
.world-stars { margin-left: auto; font-size: 1rem; font-weight: 700; color: var(--muted); white-space: nowrap; }
.world.locked .world-head { filter: saturate(0.4); opacity: 0.85; }
.track { position: relative; margin: 0 auto; max-width: 100%; }
.track-path { position: absolute; inset: 0; overflow: visible; }
.track-path path { fill: none; stroke-linecap: round; }
.track-path .rim { stroke: rgba(255, 255, 255, 0.85); stroke-width: 16; }
.track-path .dash { stroke: var(--purple-soft); stroke-width: 6; stroke-dasharray: 2 12; }
.node {
  position: absolute;
  width: 64px;
  height: 64px;
  translate: -50% -50%;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff 0 8%, transparent 30%), radial-gradient(circle at 40% 35%, var(--c), var(--d));
  box-shadow: 0 0 0 4px #fff, 0 6px 0 4px var(--cream-dark), 0 14px 18px -8px rgba(60, 30, 110, 0.5);
  font: inherit;
  font-size: 1.6rem;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.25);
  cursor: pointer;
  transition: transform 0.12s ease;
}
.node:hover { transform: scale(1.06); }
.node:active { transform: scale(0.95); }
.node-num { display: grid; place-items: center; width: 100%; height: 100%; }
.node.current { box-shadow: 0 0 0 4px #fff, 0 0 0 9px var(--pink), 0 6px 0 9px var(--pink-dark), 0 18px 24px -8px rgba(60, 30, 110, 0.5); animation: beat 1.4s ease-in-out infinite; }
.node.locked { background: radial-gradient(circle at 40% 35%, #d9d5e2, #9a95aa); color: #77728a; text-shadow: none; cursor: default; }
.node.locked:hover { transform: none; }
.node .lock { width: 26px; height: 26px; }
.node.nope { animation: shake 0.4s ease; }
.node-stars { position: absolute; left: 50%; bottom: -20px; display: flex; gap: 1px; translate: -50% 0; line-height: 0; }
.node-stars span { display: block; line-height: 0; filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.15)); }
.node-stars span:nth-child(2) { margin-top: 5px; }
.node-stars span:not(.on) { filter: grayscale(1); opacity: 0.45; }

/* Start screen */
.start {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  overflow-y: auto;
  padding: 24px 16px;
  background: var(--theme-sky, #bfe2ff) var(--theme-bg, url("../../assets/candy-bg.svg")) center bottom / cover no-repeat;
}
.start-card { width: min(380px, 100%); margin: auto; display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }
.start-card h1 { margin: 0; font-size: clamp(2.6rem, 13vw, 3.8rem); line-height: 0.95; }
.start-card h1 .line { display: block; white-space: nowrap; }
.start-bubbles { --b: 46px; position: relative; width: calc(var(--b) * 4.4); height: calc(var(--b) * 2.85); }
.sb {
  position: absolute;
  left: calc(var(--x) * var(--b) * 1.04 + var(--b) * 0.15);
  top: calc(var(--y) * var(--b) * 0.9);
  width: var(--b);
  height: var(--b);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(ellipse 22% 13% at 30% 24%, rgba(255, 255, 255, 0.85) 90%, transparent), radial-gradient(circle at 50% 52%, rgba(255, 255, 255, 0.5), transparent 62%), radial-gradient(circle at 35% 30%, var(--l), var(--c) 50%, var(--d));
  box-shadow: inset 0 0 0 1.5px rgba(40, 20, 60, 0.3);
  animation: sb-in 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) backwards, sb-bob 3s ease-in-out infinite;
  animation-delay: calc(var(--i) * 0.06s), calc(var(--i) * -0.4s);
}
.sb svg { position: relative; }
/* the whole bunch floats slowly up and down */
.start-bubbles { animation: sb-float 4s ease-in-out infinite; }
@keyframes sb-float { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-7px) rotate(-1.5deg); } }
.start-best { margin: 0; padding: 6px 18px; border-radius: 999px; font-size: 1.15rem; font-weight: 700; }
.start-form { width: 100%; padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 8px; }
.start-form .label { margin: 0; }
.targets { display: flex; justify-content: center; gap: 8px; }
.targets button {
  flex: 1;
  min-height: 52px;
  padding: 4px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 16px;
  font: inherit;
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.15;
  color: var(--ink);
  background: #fff;
  box-shadow: 0 4px 0 var(--cream-dark);
  cursor: pointer;
}
.targets button:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--cream-dark); }
.targets button small { font-size: 0.78rem; font-weight: 600; color: var(--muted); }
.targets button.on { color: #fff; background: var(--purple); box-shadow: 0 4px 0 var(--purple-dark); }
.targets button.on small { color: rgba(255, 255, 255, 0.85); }
.start-actions { width: min(320px, 100%); display: flex; flex-direction: column; align-items: stretch; gap: 14px; }
.start-actions #play { width: 100%; font-size: 1.5rem; }
/* the small tiles under the big button: Eindeloos (with its record) and the level map */
.start-tiles { display: flex; justify-content: center; gap: 10px; }
.start-tile { flex: 1 1 0; min-width: 64px; max-width: 132px; min-height: 72px; padding: 6px 6px 7px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; border: 0; border-radius: 18px; background: #fff; box-shadow: 0 4px 0 var(--cream-dark); font: inherit; font-size: 0.85rem; font-weight: 700; line-height: 1.1; color: var(--ink); cursor: pointer; }
.start-tile:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--cream-dark); }
.start-tile-icon { line-height: 0; }
.start-tile-icon svg { width: 34px; height: 34px; }
.start-tile .mode-best { font-size: 0.82rem; color: var(--pink-dark); }
.mode-best { display: flex; align-items: center; justify-content: center; gap: 5px; margin-top: 1px; font-size: 0.95rem; font-weight: 600; opacity: 0.95; }
.mode-best b { font-variant-numeric: tabular-nums; }
.help { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 10px; color: var(--muted); font-size: 0.96rem; line-height: 1.5; text-align: left; }
.help summary { list-style: none; cursor: pointer; }
.help summary::-webkit-details-marker { display: none; }
.help ul { margin: 0; padding: 12px 16px 12px 32px; width: 100%; }
.help strong { color: var(--ink); }
kbd { font: inherit; font-size: 0.85em; padding: 0 7px; border-radius: 8px; background: #fff; box-shadow: 0 2px 0 var(--cream-dark); color: var(--ink); }

.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

@keyframes shake { 20% { transform: translateX(-6px) rotate(-0.6deg); } 40% { transform: translateX(5px) rotate(0.6deg); } 60% { transform: translateX(-3px); } 80% { transform: translateX(2px); } }
@keyframes bump { 50% { transform: scale(1.25); } }
@keyframes pop-in { from { transform: scale(0.85); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes star-in { from { transform: scale(0) rotate(-40deg); } }
@keyframes fall { to { transform: translate(var(--x), 110vh) rotate(var(--r)); } }
@keyframes beat { 50% { transform: scale(1.08); } }
@keyframes sb-in { from { transform: translateY(-40px) scale(0.4); opacity: 0; } }
@keyframes sb-bob { 50% { translate: 0 -4px; } }
@keyframes hint-swipe { 0%, 100% { transform: translate(-46px, 0) rotate(-12deg); } 50% { transform: translate(46px, -6px) rotate(12deg); } }
@keyframes tip-in { from { transform: translateY(-20px) scale(0.8); opacity: 0; } }
@keyframes tip-out { to { transform: translateY(-16px); opacity: 0; } }
@keyframes combo {
  0% { transform: translate(-50%, 10px) scale(0.5) rotate(-6deg); opacity: 0; }
  20% { transform: translate(-50%, 0) scale(1.1) rotate(2deg); opacity: 1; }
  70% { opacity: 1; }
  100% { transform: translate(-50%, -30px) scale(1); opacity: 0; }
}
@keyframes toast {
  0% { transform: translate(-50%, -8px) scale(0.8); opacity: 0; }
  12% { transform: translate(-50%, 0) scale(1.05); opacity: 1; }
  20% { transform: translate(-50%, 0) scale(1); }
  80% { opacity: 1; }
  100% { transform: translate(-50%, 0); opacity: 0; }
}
@keyframes levelup {
  0% { transform: translate(-50%, 0) scale(0.3) rotate(-8deg); opacity: 0; }
  15% { transform: translate(-50%, 0) scale(1.15) rotate(3deg); opacity: 1; }
  25% { transform: translate(-50%, 0) scale(1) rotate(0deg); }
  85% { opacity: 1; }
  100% { transform: translate(-50%, -20px); opacity: 0; }
}
@keyframes fade { 0% { opacity: 0; transform: translateX(-50%); } 10%, 80% { opacity: 1; transform: translateX(-50%); } 100% { opacity: 0; transform: translateX(-50%); } }

@media (max-width: 559px) {
  .app { gap: 8px; padding: 8px 8px max(8px, env(safe-area-inset-bottom)); }
  .topbar { flex-wrap: wrap; row-gap: 8px; }
  .mini-logo { display: block; flex: 1; min-width: 0; }
  .hud { order: 3; flex-basis: 100%; max-width: none; padding: 4px 8px; }
  .stat b { font-size: 1.15rem; }
}
@media (max-width: 360px) {
  .stat small { font-size: 0.72rem; }
  .node { width: 58px; height: 58px; font-size: 1.4rem; }
  .map-head { gap: 8px; padding: 10px 10px 6px; }
  .map-title { padding: 8px 10px; font-size: 1.1rem; }
  .map-total { padding: 6px 10px; font-size: 1rem; }
}
/* tablets: the start screen has room to spare, so the bubbles are big */
@media (min-width: 700px) and (min-height: 1000px) {
  .start-bubbles { --b: 64px; }
}
@media (max-height: 880px) {
  .start-bubbles { --b: 34px; }
  .start-card { gap: 12px; }
}
/* short screens: the start screen drops its picture so everything fits */
@media (max-height: 700px) {
  .start { padding: 12px 16px; }
  .start-bubbles { display: none; }
  .start-card { gap: 11px; }
  .start-actions { gap: 13px; }
}
/* phones on their side: one slim top row, and the start screen in two columns */
@media (max-height: 500px) {
  .app { gap: 6px; padding-top: 6px; padding-bottom: 6px; }
  .topbar .icon-btn, .topbar .back-link { width: 44px; height: 44px; font-size: 1.2rem; }
  .hud { padding: 2px 10px; }
  .stat b { font-size: 1.05rem; }
  .stat small { font-size: 0.7rem; }
  .mini-stars { height: 1.25rem; }
  .mini-stars span { width: 1.1rem; height: 1.1rem; }
  .mini-stars span:nth-child(2) { width: 1.25rem; height: 1.25rem; }
  .field { border-radius: 14px; }
  .hint-text { font-size: 0.85rem; }
}
/* wide screens: the start screen in two columns, the choices on the left and the big button with the
   tiles and the arcade's chip row on the right */
@media (orientation: landscape) and (min-width: 600px) {
  .start-card {
    width: min(820px, 100%);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "bubbles actions" "logo actions" "best actions" "form utils";
    align-items: center;
    justify-items: center;
    gap: 12px 28px;
  }
  .start-bubbles { grid-area: bubbles; }
  .start-card h1 { grid-area: logo; }
  .start-best { grid-area: best; }
  .start-form { grid-area: form; align-self: start; }
  .start-actions { grid-area: actions; align-self: end; }
  .help { grid-area: utils; align-self: start; }
  #start .start-utils { grid-area: utils; align-self: start; }
}
@media (orientation: landscape) and (min-width: 600px) and (max-height: 500px) {
  .start { padding-top: 10px; padding-bottom: 10px; }
  .start-card { gap: 8px 24px; grid-template-areas: "logo actions" "best actions" "form utils"; }
  .start-bubbles { display: none; }
  .start-card h1 { font-size: 2.6rem; }
}
/* phones on their side: the buttons and the score move to the sides, so the field gets the full height */
@media (orientation: landscape) and (max-height: 500px) {
  .app {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr);
    gap: 8px 12px;
    padding: 6px max(10px, env(safe-area-inset-right)) max(6px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));
  }
  .topbar { display: contents; }
  .topbar .back-link { grid-column: 1; grid-row: 1; justify-self: start; }
  .hud { grid-column: 1; grid-row: 2; align-self: start; width: 112px; grid-template-columns: 1fr; padding: 4px 8px; }
  .stat { padding: 3px 0; }
  .stat + .stat { border-left: 0; border-top: 2px dashed var(--cream-2); }
  .top-actions { grid-column: 3; grid-row: 1 / 3; flex-direction: column; align-self: start; }
  .board { grid-column: 2; grid-row: 1 / 3; }
}
/* the moving bits of the world (world.js): bubbles rising, balloons drifting, stars twinkling */
.world-fx { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }
.world-fx span { position: absolute; line-height: 0; opacity: 0.75; will-change: transform; animation-timing-function: linear; animation-iteration-count: infinite; }
.world-fx .wf-rise { bottom: -40px; animation-name: wf-rise; }
.world-fx .wf-drift { bottom: -60px; animation-name: wf-drift; }
.world-fx .wf-swim { top: 40%; animation-name: wf-swim; }
.world-fx .wf-twinkle { animation-name: wf-twinkle; animation-timing-function: ease-in-out; }
.world-fx .wf-shoot { top: 8%; animation-name: wf-shoot; }
@keyframes wf-rise { 0% { transform: translate(0, 0); } 50% { transform: translate(-18px, -55vh); } 100% { transform: translate(12px, -112vh); } }
@keyframes wf-drift { 0% { transform: translate(0, 0) rotate(-5deg); } 50% { transform: translate(30px, -55vh) rotate(5deg); } 100% { transform: translate(-10px, -118vh) rotate(-4deg); } }
@keyframes wf-swim { 0% { transform: translate(0, 0); } 50% { transform: translate(55vw, -24px); } 100% { transform: translate(calc(100vw + 160px), 0); } }
@keyframes wf-twinkle { 0%, 100% { opacity: 0.15; transform: scale(0.6); } 50% { opacity: 0.9; transform: scale(1.1); } }
@keyframes wf-shoot { 0%, 70% { opacity: 0; transform: translate(0, 0); } 74% { opacity: 1; } 100% { opacity: 0; transform: translate(calc(100vw + 160px), 34vh); } }

@media (prefers-reduced-motion: reduce) {
  .sheet, .over-title.record, .over-stars span, .sb, .start-bubbles, .tip, .node.current, .hint-hand { animation: none !important; }
  .banner { animation-name: fade !important; }
  .frame.shake, .node.nope { animation: none; }
  .world-fx { display: none; }
}

/* ---------- Desktop: a big screen ----------
   The field (it stays upright) at the full height in the middle, with the world on both sides. Left, against
   the field: level, points and stars, then the drop meter and the mode. Right: the round buttons, the next
   bubble (click it to swap) and the keys. The field draws no next bubble and no meter of its own then (game.js).
   The map shows the three worlds as three rows of ten big tiles. A big tablet on its side gets the same layout;
   without a mouse (html.mouse) the keys make way for how to aim with a finger. Phones and smaller tablets never
   match this query. */
.desk-side { display: none; }
.keys-line, .desk-keys, .touch-line, .desk-touch { display: none; }
@media (min-width: 1100px) and (min-height: 650px) {
  .app {
    --pad: calc(14px * var(--ui));
    --col: calc(270px * var(--ui));
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    grid-template-rows: auto auto auto minmax(0, 1fr);
    gap: calc(14px * var(--ui)) clamp(18px, 2vw, 40px);
    padding: var(--pad);
    font-size: calc(16px * var(--ui));
  }
  .topbar { display: contents; }
  .topbar .back-link { grid-column: 1; grid-row: 1; justify-self: start; align-self: start; }
  .mini-logo { display: none; }
  .top-actions { grid-column: 3; grid-row: 1; justify-self: end; align-self: start; }
  /* the board is as wide as the field at the full height (18 × 24.77 radii, plus the 12px rim) */
  .board { grid-column: 2; grid-row: 1 / -1; width: calc((100dvh - 2 * var(--pad) - 24px) * 0.7267 + 26px); min-height: 0; align-self: stretch; }
  .swap { display: none; }
  .field canvas { cursor: crosshair; }

  .hud { grid-column: 1; grid-row: 2; justify-self: end; width: min(var(--col), 100%); max-width: none; display: flex; flex-direction: column; padding: calc(8px * var(--ui)) calc(18px * var(--ui)); border-radius: calc(26px * var(--ui)); }
  .stat { flex-direction: row-reverse; justify-content: space-between; align-items: baseline; gap: 10px; padding: calc(10px * var(--ui)) 0; }
  .stat + .stat { border-left: 0; border-top: 2px dashed var(--cream-2); }
  .stat b { font-size: max(28px, calc(28px * var(--ui))); }
  .stat small { font-size: max(18px, calc(17px * var(--ui))); }
  .mini-stars { height: calc(2rem * var(--ui)); gap: 4px; }
  .mini-stars span { width: calc(1.8rem * var(--ui)); height: calc(1.8rem * var(--ui)); }
  .mini-stars span:nth-child(2) { width: calc(2.1rem * var(--ui)); height: calc(2.1rem * var(--ui)); }
  #hud-third { flex-direction: column-reverse; align-items: flex-start; }

  /* never wider than their column: on a 4:3 screen (1366×1024, 1280×1024) the tall field leaves less room beside it */
  .desk-side { display: flex; flex-direction: column; gap: calc(14px * var(--ui)); width: min(var(--col), 100%); min-width: 0; }
  .desk-left { grid-column: 1; grid-row: 3; justify-self: end; }
  .desk-right { grid-column: 3; grid-row: 2 / span 2; justify-self: start; }
  .desk-side .label { margin: 0; font-size: max(18px, calc(17px * var(--ui))); }
  .meter { padding: calc(14px * var(--ui)) calc(18px * var(--ui)); display: flex; flex-direction: column; gap: calc(8px * var(--ui)); border-radius: calc(26px * var(--ui)); }
  .meter-dots { display: flex; flex-wrap: wrap; gap: calc(6px * var(--ui)); }
  .meter-dots i { width: calc(18px * var(--ui)); height: calc(18px * var(--ui)); border-radius: 50%; background: rgba(110, 63, 196, 0.16); transition: background 0.2s ease, transform 0.2s ease; }
  .meter-dots i.on { background: var(--purple); box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.15); }
  .meter.warn .meter-dots i.on { background: #ef3c3c; animation: meter-warn 0.7s ease-in-out infinite; }
  .meter-text { margin: 0; font-size: max(22px, calc(22px * var(--ui))); font-weight: 700; color: var(--ink); line-height: 1.15; }
  .meter.warn .meter-text { color: #d3252f; }
  .desk-mode { margin: 0; padding: calc(10px * var(--ui)) calc(18px * var(--ui)); border-radius: calc(22px * var(--ui)); font-size: max(18px, calc(17px * var(--ui))); font-weight: 600; color: var(--muted); line-height: 1.3; }
  .desk-mode b { display: block; font-size: max(22px, calc(21px * var(--ui))); color: var(--ink); }

  .next { padding: calc(14px * var(--ui)) calc(18px * var(--ui)) calc(16px * var(--ui)); display: flex; flex-direction: column; align-items: center; gap: calc(8px * var(--ui)); border-radius: calc(26px * var(--ui)); }
  .next .label { align-self: flex-start; }
  .next-btn {
    position: relative;
    display: grid;
    place-items: center;
    width: calc(132px * var(--ui));
    height: calc(132px * var(--ui));
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: radial-gradient(circle at 40% 32%, #fff, var(--cream-2));
    box-shadow: inset 0 -4px 0 rgba(120, 80, 40, 0.12), 0 5px 0 var(--cream-dark);
    cursor: pointer;
    transition: transform 0.12s ease-out, filter 0.12s ease-out;
  }
  @media (hover: hover) { .next-btn:hover:not(:disabled) { transform: translateY(-3px); filter: brightness(1.04); } }
  .next-btn:active:not(:disabled) { transform: translateY(2px) scale(0.96); }
  .next-btn:disabled { cursor: default; }
  .next-btn canvas { width: 72%; height: 72%; }
  .next-btn.spin canvas { animation: next-spin 0.3s ease-out; }
  /* a curved arrow round the bubble: click to swap */
  .next-arrows { position: absolute; inset: -6px; border-radius: 50%; border: calc(4px * var(--ui)) solid transparent; border-top-color: var(--purple); border-right-color: var(--purple); transform: rotate(-20deg); pointer-events: none; }
  .next-arrows::after { content: ""; position: absolute; right: 4%; top: 22%; border: calc(8px * var(--ui)) solid transparent; border-top-color: var(--purple); transform: rotate(110deg); }
  .keys-line { display: block; margin: 0; font-size: max(18px, calc(16px * var(--ui))); font-weight: 600; color: var(--muted); text-align: center; }
  .desk-keys { display: flex; flex-direction: column; gap: calc(8px * var(--ui)); margin: 0; padding: calc(14px * var(--ui)) calc(18px * var(--ui)); list-style: none; border-radius: calc(26px * var(--ui)); font-size: max(18px, calc(16px * var(--ui))); font-weight: 600; color: var(--muted); }
  .desk-keys li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; line-height: 1.25; }
  .desk-keys li:first-child { color: var(--ink); font-weight: 700; }
  .desk-side kbd { display: inline-grid; place-items: center; min-width: 2em; height: 2em; padding: 0 0.5em; border-radius: 9px; background: #fff; box-shadow: inset 0 -3px 0 var(--cream-dark), 0 0 0 2px var(--cream-dark); font-size: 1em; font-weight: 700; line-height: 1; color: var(--ink); }
  .desk-side kbd .art { width: 1em; height: 1em; vertical-align: 0; }
  /* a touch screen: no keys, the finger's words instead */
  html:not(.mouse) :is(.keys-line, .desk-keys) { display: none; }
  html:not(.mouse) .touch-line { display: block; margin: 0; font-size: max(18px, calc(16px * var(--ui))); font-weight: 600; color: var(--muted); text-align: center; }
  html:not(.mouse) .desk-touch { display: block; margin: 0; padding: calc(14px * var(--ui)) calc(18px * var(--ui)); border-radius: calc(26px * var(--ui)); font-size: max(18px, calc(16px * var(--ui))); font-weight: 700; line-height: 1.3; color: var(--ink); }
  .desk-touch .art { width: 1.4em; height: 1.4em; vertical-align: -0.35em; }

  .hint-text { font-size: calc(1.15rem * var(--ui)); padding: calc(8px * var(--ui)) calc(18px * var(--ui)); }
  .tip { width: min(calc(400px * var(--ui)), calc(100% - 24px)); }
  .tip-text { font-size: max(18px, calc(1rem * var(--ui))); }
  .tip-icon { width: calc(60px * var(--ui)); height: calc(60px * var(--ui)); }
  .banner { font-size: calc(2rem * var(--ui)); }
  .banner.levelup { font-size: calc(2.6rem * var(--ui)); }
  .banner.toast { font-size: calc(1.5rem * var(--ui)); }

  /* the end card in two columns: the picture, the title and the stars left; the results and the buttons right */
  #over .sheet {
    width: min(calc(820px * var(--ui)), 100%);
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    grid-template-rows: auto auto auto;
    grid-template-areas: "icon text" "title text" "stars actions";
    align-items: center;
    gap: calc(10px * var(--ui)) calc(28px * var(--ui));
    padding: calc(24px * var(--ui)) calc(26px * var(--ui)) calc(26px * var(--ui));
    border-radius: calc(30px * var(--ui));
    font-size: calc(16px * var(--ui));
  }
  #over .sheet > * { grid-column: auto; grid-row: auto; }
  #over .over-icon { grid-area: icon; align-self: end; }
  #over .over-icon svg { width: calc(84px * var(--ui)); height: calc(84px * var(--ui)); }
  #over .over-title { grid-area: title; font-size: calc(2rem * var(--ui)); }
  #over .over-stars { grid-area: stars; align-self: start; gap: calc(10px * var(--ui)); }
  #over .over-stars span { width: calc(60px * var(--ui)); height: calc(60px * var(--ui)); }
  #over .over-stars span:nth-child(2) { width: calc(76px * var(--ui)); height: calc(76px * var(--ui)); margin-top: calc(-12px * var(--ui)); }
  #over .over-text { grid-area: text; align-self: end; font-size: max(18px, calc(1.05rem * var(--ui))); }
  #over .over-text td { padding: calc(6px * var(--ui)) 8px; }
  #over .over-actions { grid-area: actions; align-self: start; position: static; margin: 0; padding: 0; background: none; gap: calc(14px * var(--ui)); }
  #over .over-actions .btn { min-height: max(60px, calc(58px * var(--ui))); font-size: calc(1.25rem * var(--ui)); }

  /* pause: a bigger card */
  #pause .sheet { width: min(calc(460px * var(--ui)), 100%); padding: calc(24px * var(--ui)) calc(26px * var(--ui)); border-radius: calc(30px * var(--ui)); }
  #pause .over-title { font-size: calc(2rem * var(--ui)); }
  .pause-actions { gap: calc(14px * var(--ui)); }
  .pause-actions .btn { min-height: max(60px, calc(58px * var(--ui))); font-size: calc(1.3rem * var(--ui)); }

  /* the map: three worlds, each a row of ten big tiles */
  .map-head { width: min(calc(1500px * var(--ui)), 100%); padding: calc(16px * var(--ui)) 32px calc(10px * var(--ui)); gap: calc(14px * var(--ui)); }
  .map-head .icon-btn { width: max(56px, calc(56px * var(--ui))); height: max(56px, calc(56px * var(--ui))); font-size: calc(1.5rem * var(--ui)); }
  .map-title { font-size: calc(1.6rem * var(--ui)); padding: calc(10px * var(--ui)) 18px; }
  .map-total { font-size: max(22px, calc(1.35rem * var(--ui))); padding: calc(8px * var(--ui)) 18px; }
  .map-scroll { padding: 4px 32px 28px; }
  .map-inner.grid { width: min(calc(1500px * var(--ui)), 100%); gap: calc(14px * var(--ui)); }
  .map-inner.grid .world-head { margin: 0; font-size: max(22px, calc(1.35rem * var(--ui))); padding: calc(8px * var(--ui)) 20px calc(8px * var(--ui)) 10px; }
  .map-inner.grid .world-head small { font-size: max(18px, calc(0.95rem * var(--ui))); }
  .map-inner.grid .world-art { width: calc(52px * var(--ui)); height: calc(52px * var(--ui)); }
  .map-inner.grid .world-stars { font-size: max(18px, calc(1.1rem * var(--ui))); }
  .level-row { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: clamp(10px, 1vw, 20px); padding: 10px 4px 26px; }
  .map-inner.grid .node {
    position: relative;
    width: auto;
    height: auto;
    aspect-ratio: 1;
    translate: none;
    min-width: 96px;
    border-radius: 28%;
    font-size: clamp(1.8rem, 2.3vw, 3rem);
  }
  @media (hover: hover) { .map-inner.grid .node:hover:not(.locked) { transform: translateY(-4px) scale(1.04); filter: brightness(1.06); } }
  .map-inner.grid .node.current { animation: none; }
  .map-inner.grid .node .lock { width: 34%; height: 34%; }
  .map-inner.grid .node-stars { bottom: -18px; }
  .map-inner.grid .node-stars svg { width: calc(20px * var(--ui)); height: calc(20px * var(--ui)); }
  .map-inner.grid .node-stars span:nth-child(2) svg { width: calc(24px * var(--ui)); height: calc(24px * var(--ui)); }

  /* the start screen: the choices left, the bubbles, the title and the big button right */
  .start { padding: calc(24px * var(--ui)) 32px; }
  .start-card {
    width: min(calc(1000px * var(--ui)), 100%);
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "best bubbles" "form logo" "form actions" "utils utils";
    gap: calc(16px * var(--ui)) calc(48px * var(--ui));
  }
  .start-bubbles { --b: calc(62px * var(--ui)); align-self: end; }
  .start-card h1 { font-size: calc(4.4rem * var(--ui)); }
  .start-best { align-self: end; font-size: max(20px, calc(1.2rem * var(--ui))); padding: calc(8px * var(--ui)) calc(22px * var(--ui)); }
  .start-form { align-self: start; padding: calc(16px * var(--ui)) calc(18px * var(--ui)) calc(18px * var(--ui)); gap: calc(12px * var(--ui)); }
  .start-form .label { font-size: max(19px, calc(1.1rem * var(--ui))); }
  .targets { gap: calc(12px * var(--ui)); }
  .targets button { min-height: max(76px, calc(76px * var(--ui))); font-size: calc(1.3rem * var(--ui)); border-radius: calc(20px * var(--ui)); }
  .targets button small { font-size: max(16px, calc(0.95rem * var(--ui))); }
  .start-actions { width: min(calc(400px * var(--ui)), 100%); align-self: start; gap: calc(16px * var(--ui)); }
  .start-actions #play { min-height: calc(80px * var(--ui)); font-size: calc(1.8rem * var(--ui)); border-radius: calc(26px * var(--ui)); }
  .start-tiles { gap: calc(14px * var(--ui)); }
  .start-tile { max-width: none; min-height: calc(112px * var(--ui)); font-size: max(18px, calc(1.05rem * var(--ui))); border-radius: calc(22px * var(--ui)); gap: 4px; }
  .start-tile-icon svg { width: calc(46px * var(--ui)); height: calc(46px * var(--ui)); }
  .start-tile .mode-best { font-size: max(22px, calc(1.3rem * var(--ui))); gap: 6px; }
  .start-tile .mode-best .art { width: 1em; height: 1em; }
}
@keyframes meter-warn { 50% { transform: scale(1.2); } }
@keyframes next-spin { from { transform: rotate(-360deg) scale(0.7); } }
@media (prefers-reduced-motion: reduce) {
  .meter.warn .meter-dots i.on, .next-btn.spin canvas { animation: none; }
}
