/* One screen, no scrolling: the lane takes all the room the bar, the effect picker and the scores leave. */
.app {
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  padding: max(12px, env(safe-area-inset-top)) max(14px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-left));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.topbar { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
/* one line always (.top-title in assets/style.css hides it rather than let it wrap) */
.title { flex: 1; margin: 0; font-size: clamp(1.2rem, 5.2vw, 2.1rem); text-align: center; }

/* The lane: the biggest box that fits in .lane-area (game.js sizes it: 400 wide, 560 to 860 high). The canvas
   is see-through around the lane, so the stage has no frame: the lane lies on the hall's floor. */
.lane-area { flex: 1 1 0; min-height: 200px; width: 100%; display: grid; place-items: center; container-type: size; }
.stage {
  position: relative;
  width: min(100cqw, 100cqh * 400 / 560);
  border-radius: 26px;
  overflow: hidden;
}
#lane { display: block; width: 100%; aspect-ratio: 400 / 560; touch-action: none; cursor: grab; user-select: none; }
#lane:active { cursor: grabbing; }
#lane:focus { outline: none; }
#lane:focus-visible { outline: 4px solid var(--purple); outline-offset: -4px; border-radius: 26px; }
.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; }

.banner {
  position: absolute;
  left: 50%;
  top: 30%;
  width: max-content;
  max-width: 90%;
  padding: 8px 26px;
  border: 5px solid #fff;
  border-radius: 34px;
  font-size: clamp(1.6rem, 7vw, 2.4rem);
  font-weight: 700;
  line-height: 1.15;
  text-align: center;
  text-wrap: balance;
  overflow-wrap: anywhere;
  color: #fff;
  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.18);
  background: var(--purple);
  box-shadow: 0 6px 0 rgba(58, 31, 74, 0.25);
  pointer-events: none;
  animation: banner 1.6s ease-out forwards;
}
.banner small { display: block; font-size: 0.5em; font-weight: 600; line-height: 1.2; }
.banner.turn { font-size: clamp(1.15rem, 5vw, 1.6rem); }
.banner.big { font-size: clamp(2rem, 9vw, 3rem); }
.banner.strike { background: linear-gradient(90deg, var(--pink), var(--orange), #f5b800, var(--green), var(--blue), var(--purple)); }
.banner.spare { background: var(--pink); }
.banner.gutter { background: #9a84c4; }
.banner.almost { background: var(--orange); }

/* Whose turn: a card in the player's colour that waits for a tap */
.handoff {
  position: absolute;
  inset: 0;
  z-index: 8;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(110, 63, 196, 0.35);
  cursor: pointer;
}
.handoff-card {
  width: min(300px, 100%);
  padding: 20px 20px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
  border: 5px solid var(--c-main);
  animation: handoff 0.35s cubic-bezier(0.3, 1.6, 0.5, 1) both;
}
.handoff-ball {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: radial-gradient(circle at 36% 30%, #fff 0 10%, var(--c-light) 22%, var(--c-main) 55%, var(--c) 100%);
  box-shadow: 0 4px 0 rgba(58, 31, 74, 0.18);
}
.handoff-now { margin: 4px 0 0; font-size: clamp(1.6rem, 7vw, 2.1rem); font-weight: 700; line-height: 1.15; overflow-wrap: anywhere; }
.handoff-now b { color: var(--c); }
.handoff-frame { margin: 0 0 10px; color: var(--muted); font-weight: 600; }
.handoff-go {
  width: 100%;
  min-height: 60px;
  font-size: 1.5rem;
  background: linear-gradient(180deg, var(--c-light), var(--c-main) 55%);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.45), 0 6px 0 var(--c), 0 14px 22px -10px var(--c);
}
.handoff-go:active { box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.45), 0 1px 0 var(--c); }
@keyframes handoff {
  0% { transform: scale(0.6); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

.modal {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: grid;
  overflow-y: auto;
  padding: 12px;
  background: rgba(110, 63, 196, 0.55);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}
.modal .end-card { margin: auto; width: min(380px, 100%); }
/* Small screens: the results get the whole screen instead of only the lane. */
@media (max-width: 360px), (max-height: 600px) {
  .modal { position: fixed; z-index: 40; padding: 12px; }
}
@media (max-width: 360px) {
  .modal .end-card { padding: 12px 12px 14px; gap: 6px; }
}
.modal-sub { margin: -4px 0 4px; font-weight: 600; overflow-wrap: anywhere; }
.end-card td:first-child { overflow-wrap: anywhere; }

/* Effect (curve) picker */
.effect { width: min(100%, 640px); display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 14px; }
.effect .label { white-space: nowrap; }
.effect-choice { flex: 1; display: grid; grid-template-columns: 1fr 1fr 1.4fr 1fr 1fr; gap: 6px; }
.effect-choice button {
  height: 40px;
  border: 0;
  border-radius: 12px;
  font: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
  background: #fff;
  box-shadow: 0 3px 0 var(--cream-dark);
  cursor: pointer;
}
.effect-choice button.on { color: #fff; background: var(--purple); box-shadow: 0 3px 0 var(--purple-dark); }
.effect-choice { min-width: 0; }
.effect-choice button { min-width: 0; padding: 0 2px; }
@media (max-width: 360px) {
  .effect { padding-left: 10px; gap: 6px; }
  .effect .label { font-size: 0.82rem; }
  .effect-choice { gap: 4px; }
  .effect-choice button { font-size: 0.9rem; }
}

/* Scoreboard: one row per player, ten frames. */
/* The boxes never shrink below 14px: when even that doesn't fit, the board scrolls sideways. */
.scoreboard { position: relative; flex: none; width: min(100%, 640px); padding: 10px; display: flex; flex-direction: column; gap: 6px; overflow-x: auto; overscroll-behavior-x: contain; }
.sb-row {
  display: grid;
  grid-template-columns: minmax(max(58px, calc(var(--name-ch, 6) * 0.58rem + 10px)), 1.5fr) repeat(9, minmax(28px, 1fr)) minmax(42px, 1.45fr);
  min-width: min-content;
  gap: 3px;
  padding: 4px;
  border-radius: 14px;
  transition: background 0.2s ease;
}
.sb-row.active { background: var(--cream-2); box-shadow: inset 0 2px 4px rgba(120, 80, 40, 0.15); }
.sb-name { display: flex; flex-direction: column; justify-content: center; min-width: 0; padding: 0 4px; }
.sb-name b { font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--c); }
.sb-name span { font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.sb-frame {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 2px 0 var(--cream-dark);
  overflow: hidden;
}
.sb-frame.current { box-shadow: 0 0 0 2px var(--c), 0 2px 0 var(--cream-dark); }
/* each frame is a little rack of ten pins: knocked over ones lie down, the number under it is the score so far */
.sb-rack { display: block; width: 100%; height: auto; padding: 3px 2px 0; overflow: visible; }
.sb-rack .mp { fill: #fff; stroke: #9a84c4; stroke-width: 0.7; }
.sb-rack .mp.down { stroke-width: 0.8; opacity: 0.85; }
.sb-rack .mp.r0 { fill: var(--pink-soft); stroke: var(--pink-dark); }
.sb-rack .mp.r1 { fill: color-mix(in srgb, var(--purple) 35%, #fff); stroke: var(--purple-dark); }
.sb-frame.todo .sb-rack { opacity: 0.4; }
.sb-frame.strike { background: linear-gradient(180deg, #fff6c2, #fff); box-shadow: inset 0 0 0 2px #f5b800, 0 2px 0 var(--cream-dark); }
.sb-frame.spare { background: linear-gradient(180deg, var(--pink-soft), #fff); }
.sb-frame.current.strike, .sb-frame.current.spare { box-shadow: 0 0 0 2px var(--c), 0 2px 0 var(--cream-dark); }
.sb-marks { text-align: center; font-size: 0.82rem; font-weight: 700; line-height: 1.1; color: var(--pink-dark); white-space: nowrap; }
.sb-total { flex: 1; display: grid; place-items: center; min-height: 18px; font-size: 0.85rem; font-weight: 700; font-variant-numeric: tabular-nums; }
/* A narrow board (phones, the side column in landscape): the name and score go on their own line above
   the frames, so all ten still fit. */
.scoreboard { container: board / inline-size; }
@container board (max-width: 420px) {
  .sb-row { grid-template-columns: repeat(9, minmax(28px, 1fr)) minmax(42px, 1.45fr); row-gap: 2px; }
  .sb-name { grid-column: 1 / -1; flex-direction: row; align-items: baseline; justify-content: space-between; gap: 8px; }
  .sb-name span { font-size: 1rem; }
}
/* ...and when even that scrolls, the name and score stay in sight */
@container board (max-width: 350px) {
  .sb-name { position: sticky; left: 4px; max-width: calc(100cqw - 24px); }
}

/* Help, on the start screen */
.help { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 10px; color: var(--muted); font-size: 0.98rem; line-height: 1.5; text-align: left; }
.help summary { list-style: none; min-height: 44px; display: inline-flex; align-items: center; gap: 6px; padding: 8px 18px; border-radius: 999px; cursor: pointer; color: var(--ink); font-weight: 600; }
.help summary::-webkit-details-marker { display: none; }
.help ul { margin: 0; padding: 12px 18px 12px 34px; 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); }

/* Start screen */
.start {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  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 { margin: auto; width: min(360px, 100%); display: flex; flex-direction: column; align-items: center; gap: 18px; text-align: center; }
.start-card h1 { margin: 0; font-size: clamp(2.4rem, 11vw, 4rem); line-height: 1.05; white-space: nowrap; }
/* The hero above the title: a row of pins, the pink ball rolls in and they wobble (3.2 s, transforms only) */
.start-head { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.hero { display: block; width: clamp(240px, 70vw, 330px); height: auto; overflow: visible; }
.hero-floor { fill: rgba(60, 30, 110, 0.16); }
.hero-pin > g { transform-box: fill-box; transform-origin: 50% 100%; animation: hero-pin 3.2s ease-in-out calc(var(--k) * 0.05s) infinite; }
.hero-pin path:first-child { fill: #fff; stroke: #c9b8e6; stroke-width: 1.5; }
.hero-pin .stripe { fill: #ef3c3c; }
.hero-pin .shine { fill: #e9e2f6; }
.hero-ball { animation: hero-ball 3.2s cubic-bezier(0.3, 0.6, 0.5, 1) infinite; }
.hero-ball-spin { transform-box: fill-box; transform-origin: 50% 50%; animation: hero-spin-ball 3.2s cubic-bezier(0.3, 0.6, 0.5, 1) infinite; }
.hero-ball circle:first-child { fill: var(--pink); stroke: var(--pink-dark); stroke-width: 2; }
.hero-ball .hole { fill: #3a1f4a; opacity: 0.75; }
.hero-ball .gloss { fill: #fff; opacity: 0.7; }
@keyframes hero-ball {
  0% { transform: translateX(-150px); opacity: 0; }
  10% { opacity: 1; }
  42% { transform: translateX(0); }
  48%, 80% { transform: translateX(-7px); opacity: 1; }
  92%, 100% { transform: translateX(-7px); opacity: 0; }
}
@keyframes hero-spin-ball { 0% { transform: rotate(-320deg); } 42% { transform: rotate(0deg); } 48%, 100% { transform: rotate(-12deg); } }
@keyframes hero-pin {
  0%, 41% { transform: rotate(0deg); }
  45% { transform: rotate(-9deg); }
  51% { transform: rotate(7deg); }
  57% { transform: rotate(-4deg); }
  63% { transform: rotate(2deg); }
  70%, 100% { transform: rotate(0deg); }
}
@media (orientation: portrait) and (min-width: 600px) { .hero { width: min(440px, 60vw); } }
@media (max-height: 640px) and (orientation: portrait) { .hero { width: 200px; } }
.start-best { margin: 0; padding: 6px 18px; border-radius: 999px; font-size: 1.15rem; font-weight: 700; }
.start-best .art { vertical-align: -0.15em; }
.start-form { width: 100%; padding: 12px 14px 14px; display: flex; flex-direction: column; gap: 10px; }
.start-form .label, .settings-body .label { margin: 0; }
/* level and bumpers: in the gear sheet (or here, when the arcade has no sheets) */
.settings-body { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.settings-body .choice + .label { margin-top: 6px; }
.choice { display: flex; justify-content: center; gap: 10px; }
.choice button {
  min-width: 58px;
  height: 48px;
  padding: 0 14px;
  border: 0;
  border-radius: 16px;
  font: inherit;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--ink);
  background: #fff;
  box-shadow: 0 4px 0 var(--cream-dark);
  cursor: pointer;
}
.choice button.on { color: #fff; background: var(--purple); box-shadow: 0 4px 0 var(--purple-dark); }
/* The names in one row: one wide field, or 2-4 small cards (the ball on top, the name under it); tap to type. */
.names { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; }
.name-chip { min-width: 0; cursor: text; }
.names:not([data-count="1"]) .name-chip { flex-direction: column; gap: 2px; padding: 6px 4px 4px; }
.names:not([data-count="1"]) .name-chip .badge { width: 24px; height: 24px; }
.names:not([data-count="1"]) .name-chip input { width: 100%; text-align: center; font-size: 1rem; }
.player-field { display: flex; align-items: center; gap: 10px; padding: 6px 10px; border-radius: 16px; background: var(--cream-2); box-shadow: inset 0 2px 4px rgba(120, 80, 40, 0.18); }
.player-field .badge { flex: none; width: 28px; height: 28px; border-radius: 50%; background: radial-gradient(circle at 36% 30%, #fff 0 12%, var(--c) 48%); }
.player-field input { flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: 1.1rem; font-weight: 600; color: var(--ink); outline: none; }
.player-field input::placeholder { color: var(--muted); }
.start-actions { width: min(280px, 100%); display: flex; flex-direction: column; align-items: center; gap: 16px; }
.start-actions #start-btn { width: 100%; text-align: center; }
.start-actions a { text-decoration: none; }

/* the stickers earned in this game, again on the end card */
.new-stickers { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 2px 10px; margin: 0; padding: 5px 10px; border-radius: 16px; background: #fff7cc; box-shadow: inset 0 0 0 3px var(--lemon); color: var(--ink); font-weight: 700; line-height: 1.2; animation: sticker-row 0.4s ease 0.3s backwards; }
.new-stickers > span { display: inline-flex; align-items: center; gap: 6px; }
.new-stickers .art { width: 34px; height: 34px; }
@keyframes sticker-row { from { transform: scale(0.85); opacity: 0; } }

@keyframes banner {
  0% { transform: translate(-50%, 14px) scale(0.5) rotate(-6deg); opacity: 0; }
  14% { transform: translate(-50%, 0) scale(1.12) rotate(2deg); opacity: 1; }
  24% { transform: translate(-50%, 0) scale(1) rotate(0); }
  80% { opacity: 1; }
  100% { transform: translate(-50%, -24px) scale(1); opacity: 0; }
}

/* Landscape: scores on the left under back and title, the lane in the middle at the full height,
   the effect picker as a column of five on the right, the round buttons along the right edge. */
@media (orientation: landscape) {
  .app {
    --pad-y: 12px;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto auto;
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas: "back title lane effect actions" "board board lane effect actions";
    align-items: start;
    gap: 12px 14px;
    padding-top: max(var(--pad-y), env(safe-area-inset-top));
    padding-bottom: max(var(--pad-y), env(safe-area-inset-bottom));
  }
  .topbar { display: contents; }
  .topbar .back-link { grid-area: back; }
  .title { grid-area: title; align-self: center; text-align: left; font-size: clamp(1.3rem, 3.2vw, 2.2rem); }
  .top-actions { grid-area: actions; flex-direction: column; }
  .lane-area { grid-area: lane; width: calc((100dvh - 2 * var(--pad-y)) * 400 / 560); height: 100%; min-height: 0; }
  .scoreboard { grid-area: board; width: 100%; }
  .effect { grid-area: effect; width: auto; flex-direction: column; align-self: center; gap: 8px; padding: 10px 8px; }
  .effect-choice { grid-template-columns: 64px; grid-auto-rows: 52px; gap: 8px; }
  .effect-choice button { height: auto; font-size: 0.95rem; }
  .effect-choice button .art { display: inline-block; }
}
@media (orientation: landscape) and (max-height: 500px) {
  .app { --pad-y: 8px; gap: 8px 10px; }
  .topbar .icon-btn, .topbar .back-link { width: 44px; height: 44px; font-size: 1.2rem; }
  .top-actions { gap: 6px; }
  .effect { padding: 6px; gap: 4px; }
  .effect .label { font-size: 0.85rem; }
  .effect-choice { grid-template-columns: 58px; grid-auto-rows: 46px; gap: 6px; }
  .scoreboard { padding: 6px; gap: 4px; }
  .sb-row { padding: 2px 4px; }
}
@media (orientation: landscape) and (min-height: 700px) {
  .effect-choice { grid-template-columns: 76px; grid-auto-rows: 64px; gap: 10px; }
  .effect-choice button { font-size: 1.05rem; }
  .effect .label { font-size: 1.05rem; }
  .sb-total { min-height: 24px; font-size: 1rem; }
  .sb-name b { font-size: 1.05rem; }
}
/* tablets upright: bigger effect buttons and score boxes under the tall lane */
@media (orientation: portrait) and (min-width: 600px) {
  .app { gap: 16px; }
  .effect-choice button { height: 52px; font-size: 1.15rem; }
  .effect .label { font-size: 1.1rem; }
  .sb-total { min-height: 24px; font-size: 1rem; }
}

/* The start screen in landscape: the choices left, the big button right. */
@media (orientation: landscape) and (max-height: 820px) {
  .start-card {
    width: min(780px, 100%);
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    grid-template-areas: "logo actions" "best actions" "form actions";
    gap: 12px 28px;
    align-items: center;
    justify-items: center;
  }
  /* the hero sits left of the title */
  .start-head { grid-area: logo; flex-direction: row; gap: 14px; }
  .start-card h1 { font-size: clamp(2rem, 8.5vh, 3.6rem); }
  .hero { width: clamp(150px, 34vh, 300px); }
  .start-best { grid-area: best; }
  .start-form { grid-area: form; }
  .start-actions { grid-area: actions; width: 100%; gap: 12px; }
  .start-actions #start-btn { padding-top: 22px; padding-bottom: 22px; font-size: 1.5rem; }
  .start-card .help, .start-card .start-utils, .start-card > .settings-body { grid-column: 1 / -1; }
}
@media (orientation: landscape) and (max-height: 500px) {
  .start { padding: 6px 16px; }
  .hero { width: clamp(100px, 25vh, 160px); }
  .start-card { gap: 6px 24px; }
  .start-form { padding: 8px 12px 10px; gap: 6px; }
  .choice button { height: 44px; }
  .start-actions #start-btn { padding-top: 18px; padding-bottom: 18px; }
}
/* the end card in two columns where the screen is low, so both buttons are on screen */
@media (orientation: landscape) and (max-height: 600px) {
  .modal .end-card {
    width: min(620px, 100%);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
    grid-template-areas: "icon text" "title text" "sub text" "stars text" "stickers actions";
    grid-template-rows: auto auto auto auto 1fr;
    align-items: center;
    gap: 6px 20px;
  }
  .end-card .over-icon { grid-area: icon; }
  .end-card .over-title { grid-area: title; }
  .end-card .modal-sub { grid-area: sub; }
  .end-card .over-stars { grid-area: stars; }
  .end-card .over-text { grid-area: text; }
  .end-card .new-stickers { grid-area: stickers; }
  .end-card .over-actions { grid-area: actions; margin-top: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-pin > g, .hero-ball, .hero-ball-spin { animation: none; }
  .banner { animation-name: banner-fade; }
  .handoff-card, .new-stickers { animation: none; }
}
@keyframes banner-fade {
  0% { transform: translateX(-50%); opacity: 0; }
  10%, 80% { transform: translateX(-50%); opacity: 1; }
  100% { transform: translateX(-50%); opacity: 0; }
}

/* ---- Desktop: a big screen (the same test as html.desktop in assets/arcade.js) ----
   The lane in the middle at the full height, the hall on both sides of it. Left: back, title and the scoreboard as a
   column (one or two players: five big frames a row; more: all ten in a row). Right: the round buttons, the Effect
   buttons with their names under each other and, with a mouse (html.mouse), the keys. A big tablet on its side gets
   the same layout without the keys. Sizes scale with --ui (assets/style.css). */
.eff-text, .key-card { display: none; }
@media (hover: hover) and (pointer: fine) {
  .effect-choice button { transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease; }
  .effect-choice button:hover { transform: translateY(-2px); filter: brightness(1.04); box-shadow: 0 6px 0 var(--cream-dark), 0 10px 16px -8px rgba(90, 50, 150, 0.4); }
  .effect-choice button.on:hover { box-shadow: 0 6px 0 var(--purple-dark), 0 10px 16px -8px rgba(90, 50, 150, 0.5); }
  .effect-choice button:active { transform: translateY(2px); }
}
@media (min-width: 1100px) and (min-height: 650px) {
  html.mouse .help .keys-line { display: none; }
  /* the pill's buttons as assets/style.css means them on desktop (its 44px base rule comes later in that file and wins) */
  :is(#start, body) .app .topbar .top-actions > .icon-btn { width: calc(52px * var(--ui)); height: calc(52px * var(--ui)); font-size: calc(1.4rem * var(--ui)); }
  .app {
    --pad-y: calc(14px * var(--ui));
    --side-min: calc(250px * var(--ui));
    --cgap: calc(28px * var(--ui));
    grid-template-columns: minmax(var(--side-min), 1fr) auto minmax(var(--side-min), 1fr);
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas: "top lane actions" "board lane effect" "board lane keys";
    gap: calc(16px * var(--ui)) var(--cgap);
    padding: var(--pad-y) calc(20px * var(--ui));
  }
  /* above the title, which shares its cell (padded to start after it) */
  .topbar .back-link { grid-area: top; justify-self: start; position: relative; z-index: 1; }
  .title { grid-area: top; align-self: center; padding-left: calc(72px * var(--ui)); font-size: calc(1.85rem * var(--ui)); }
  :is(#start, body) .app .topbar .top-actions { grid-area: actions; flex-direction: row; justify-self: end; }
  .lane-area {
    grid-area: lane;
    grid-row: 1 / -1;
    width: min(calc((100dvh - 2 * var(--pad-y)) * 400 / 560), calc(100vw - 2 * (var(--side-min) + var(--cgap)) - 40px * var(--ui)));
  }
  .banner { font-size: calc(2.2rem * var(--ui)); }
  .banner.turn { font-size: calc(1.6rem * var(--ui)); }
  .banner.big { font-size: calc(2.8rem * var(--ui)); }

  /* the scoreboard: a column of players, the name and score above the frames */
  .scoreboard { grid-area: board; align-self: start; width: 100%; max-height: 100%; overflow: hidden auto; padding: calc(12px * var(--ui)); gap: calc(10px * var(--ui)); }
  .scoreboard .sb-row { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: calc(6px * var(--ui)); row-gap: calc(6px * var(--ui)); padding: calc(8px * var(--ui)); min-width: 0; border-radius: calc(16px * var(--ui)); }
  .scoreboard:has(.sb-row:nth-child(3)) .sb-row { grid-template-columns: repeat(10, minmax(0, 1fr)); gap: calc(4px * var(--ui)); }
  .scoreboard .sb-name { grid-column: 1 / -1; position: static; max-width: none; flex-direction: row; align-items: baseline; justify-content: space-between; gap: 10px; padding: 0 calc(4px * var(--ui)); }
  .scoreboard .sb-name b { font-size: calc(20px * var(--ui)); }
  .scoreboard .sb-name span { font-size: calc(28px * var(--ui)); }
  .sb-frame { border-radius: calc(10px * var(--ui)); }
  .sb-rack { padding: calc(4px * var(--ui)) calc(3px * var(--ui)) 0; }
  .sb-marks { font-size: calc(18px * var(--ui)); }
  .sb-total { min-height: calc(32px * var(--ui)); font-size: calc(24px * var(--ui)); }
  .scoreboard:has(.sb-row:nth-child(3)) .sb-total { min-height: calc(26px * var(--ui)); font-size: min(calc(22px * var(--ui)), (100cqw - 40px) / 10 * 0.48); }
  .scoreboard:has(.sb-row:nth-child(3)) .sb-marks { font-size: min(calc(18px * var(--ui)), (100cqw - 40px) / 10 * 0.32); }

  /* the Effect buttons: one under the other, with their names */
  .effect { grid-area: effect; justify-self: start; align-self: start; width: min(100%, calc(300px * var(--ui))); flex-direction: column; align-items: stretch; gap: calc(10px * var(--ui)); padding: calc(14px * var(--ui)); }
  .effect .label { font-size: calc(20px * var(--ui)); padding-left: calc(4px * var(--ui)); }
  .effect-choice { grid-template-columns: minmax(0, 1fr); grid-auto-rows: max(56px, calc(44px * var(--ui))); gap: calc(7px * var(--ui)); }
  .effect-choice button { height: auto; display: flex; align-items: center; gap: calc(12px * var(--ui)); padding: 0 calc(14px * var(--ui)); font-size: calc(18px * var(--ui)); text-align: left; border-radius: calc(14px * var(--ui)); }
  .effect-choice .eff-icon { flex: none; min-width: calc(2.6em); text-align: center; font-size: 1.15em; }
  .effect-choice .eff-straight { display: none; }
  .effect-choice .eff-text { display: inline; }

  /* the keys */
  .key-card {
    grid-area: keys;
    justify-self: start;
    align-self: start;
    width: min(100%, calc(300px * var(--ui)));
    display: flex;
    flex-direction: column;
    gap: calc(10px * var(--ui));
    padding: calc(14px * var(--ui)) calc(16px * var(--ui)) calc(16px * var(--ui));
    font-size: calc(18px * var(--ui));
    color: var(--muted);
    font-weight: 600;
    line-height: 1.3;
  }
  .key-title { margin: 0; color: var(--ink); font-weight: 700; font-size: calc(20px * var(--ui)); }
  .key-card ul { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: calc(9px * var(--ui)) calc(12px * var(--ui)); }
  .key-card li { display: contents; }
  .key-card .keys { display: inline-flex; gap: calc(4px * var(--ui)); }
  .key-card kbd { display: inline-grid; place-items: center; min-width: 1.9em; height: 1.75em; padding: 0 0.4em; font-size: 0.95em; font-weight: 700; }
  .key-mouse { margin: 0; padding-top: calc(8px * var(--ui)); border-top: 2px dashed var(--cream-2); }
  @media (max-height: 820px) { .key-mouse { display: none; } }
  /* a touch screen has no keys to show */
  html:not(.mouse) .key-card { display: none; }

  /* whose turn, and the end card over the whole screen in two columns */
  .handoff-card { width: min(100%, calc(380px * var(--ui))); padding: calc(24px * var(--ui)); gap: calc(8px * var(--ui)); }
  .handoff-ball { width: calc(72px * var(--ui)); height: calc(72px * var(--ui)); }
  .handoff-now { font-size: calc(2.2rem * var(--ui)); }
  .handoff-frame { font-size: calc(19px * var(--ui)); }
  .handoff-go { min-height: calc(64px * var(--ui)); font-size: calc(1.6rem * var(--ui)); }
  .modal { position: fixed; z-index: 40; padding: calc(24px * var(--ui)); }
  .modal .end-card {
    width: min(100%, calc(720px * var(--ui)));
    max-height: calc(100dvh - 48px);
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
    grid-template-areas: "icon text" "title text" "sub text" "stars text" "stickers actions";
    grid-template-rows: auto auto auto auto 1fr;
    align-items: center;
    gap: calc(10px * var(--ui)) calc(28px * var(--ui));
    padding: calc(24px * var(--ui)) calc(28px * var(--ui));
  }
  .end-card .over-icon { grid-area: icon; }
  .end-card .over-icon .art { width: calc(84px * var(--ui)); height: calc(84px * var(--ui)); }
  .end-card .over-title { grid-area: title; font-size: calc(1.9rem * var(--ui)); }
  .end-card .modal-sub { grid-area: sub; font-size: calc(19px * var(--ui)); }
  .end-card .over-stars { grid-area: stars; }
  .end-card .over-stars span { width: calc(46px * var(--ui)); height: calc(46px * var(--ui)); }
  .end-card .over-stars span:nth-child(2) { width: calc(58px * var(--ui)); height: calc(58px * var(--ui)); margin-top: calc(-8px * var(--ui)); }
  .end-card .over-text { grid-area: text; font-size: calc(19px * var(--ui)); }
  .end-card .new-stickers { grid-area: stickers; font-size: calc(18px * var(--ui)); }
  .end-card .new-stickers .art { width: calc(40px * var(--ui)); height: calc(40px * var(--ui)); }
  .end-card .over-actions { grid-area: actions; margin-top: 0; padding: 0; position: static; background: none; gap: calc(14px * var(--ui)); }
  .end-card .over-actions .btn { min-height: calc(60px * var(--ui)); font-size: calc(1.25rem * var(--ui)); border-radius: calc(20px * var(--ui)); }

  /* the start screen in two columns at any height: the hero, title and choices left, the big button right */
  .start { padding: calc(24px * var(--ui)) 24px; }
  .start-card {
    width: min(94vw, calc(900px * var(--ui)));
    display: grid;
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    grid-template-areas: "logo logo" "best actions" "form actions";
    gap: calc(16px * var(--ui)) calc(44px * var(--ui));
    align-items: center;
    justify-items: center;
  }
  .start-head { grid-area: logo; flex-direction: row; gap: calc(24px * var(--ui)); }
  .start-card h1 { font-size: calc(4.4rem * var(--ui)); }
  .hero { width: calc(300px * var(--ui)); }
  .start-best { grid-area: best; font-size: calc(1.3rem * var(--ui)); padding: calc(8px * var(--ui)) calc(22px * var(--ui)); }
  .start-form { grid-area: form; padding: calc(14px * var(--ui)) calc(18px * var(--ui)) calc(18px * var(--ui)); gap: calc(12px * var(--ui)); }
  .start-form .label, .settings-body .label { font-size: calc(19px * var(--ui)); }
  .choice { gap: calc(12px * var(--ui)); }
  .choice button { min-width: calc(72px * var(--ui)); height: calc(64px * var(--ui)); font-size: calc(1.5rem * var(--ui)); border-radius: calc(18px * var(--ui)); }
  .names { gap: calc(10px * var(--ui)); }
  .player-field { padding: calc(8px * var(--ui)) calc(12px * var(--ui)); }
  .player-field .badge { width: calc(32px * var(--ui)); height: calc(32px * var(--ui)); }
  .player-field input, .names:not([data-count="1"]) .name-chip input { font-size: calc(19px * var(--ui)); }
  .names:not([data-count="1"]) .name-chip .badge { width: calc(28px * var(--ui)); height: calc(28px * var(--ui)); }
  .start-actions { grid-area: actions; width: 100%; gap: calc(12px * var(--ui)); }
  .start-actions #start-btn { padding: calc(26px * var(--ui)) 20px; font-size: calc(1.9rem * var(--ui)); border-radius: calc(24px * var(--ui)); }
  .start-card .help, .start-card .start-utils, .start-card > .settings-body { grid-column: 1 / -1; }
}
