:root {
  --ink: #3a2a1a;
  --cream: #fff8e7;
  --line: #ead9b5;
  --leaf: #2f7a3d;
  --sun: #ffb400;
  font-family: system-ui, 'Apple SD Gothic Neo', 'Hiragino Sans', 'PingFang SC', 'Microsoft YaHei', 'Malgun Gothic', sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  touch-action: manipulation;
  /* The script pins this while a keyboard is up, so typing never squeezes the page. */
  height: var(--app-h, 100%);
  background: #24572f;
  color: var(--ink);
  overscroll-behavior: none;
}

[hidden] {
  display: none !important;
}

button {
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  background: #fff;
  border: 2px solid var(--line);
  border-radius: 999px;
  padding: 0.55em 1.2em;
  cursor: pointer;
}

button:hover {
  background: #fff3d0;
}

button.primary {
  background: var(--sun);
  border-color: #e69a00;
  box-shadow: 0 4px 0 #c98400;
}

button.primary:hover {
  background: #ffc21f;
}

button.primary:active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 #c98400;
}

.card {
  background: var(--cream);
  border: 3px solid var(--line);
  border-radius: 24px;
  box-shadow: 0 10px 0 rgba(0, 0, 0, 0.18);
}

/* ---------- lobby ---------- */

#lobby {
  min-height: 100%;
  display: grid;
  place-items: center;
  padding: 24px 16px;
  background:
    radial-gradient(circle at 15% 20%, rgba(255, 255, 255, 0.08) 0 90px, transparent 91px),
    radial-gradient(circle at 85% 75%, rgba(255, 255, 255, 0.06) 0 130px, transparent 131px), #24572f;
}

#lobby .card {
  width: min(560px, 100%);
  padding: 26px 26px 22px;
}

#lobby h1 {
  margin: 0 0 6px;
  font-size: 40px;
  letter-spacing: -0.02em;
}

#muteLobby {
  float: right;
  padding: 0.35em 0.6em;
}

#lobby header p {
  margin: 0 0 18px;
  line-height: 1.55;
}

#lobby h2 {
  margin: 0 0 8px;
  font-size: 14px;
  color: #a07a45;
  letter-spacing: 0.06em;
}

#slots {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  display: grid;
  gap: 8px;
}

#slots li {
  display: grid;
  grid-template-columns: 52px 1fr 148px;
  gap: 10px;
  align-items: center;
  padding: 6px 10px 6px 6px;
  background: #fff;
  border: 2px solid var(--line);
  border-left: 8px solid var(--c);
  border-radius: 16px;
  position: relative;
}

#slots li.teamed {
  grid-template-columns: 52px 1fr 96px 148px;
}

/* What each column of the list is, over the first row and lined up with it. */
#slotHead {
  display: grid;
  grid-template-columns: 52px 1fr 148px;
  gap: 10px;
  padding: 0 12px 0 16px;
  margin: 0 0 4px;
  font-size: 12px;
  font-weight: 700;
  color: #a07a45;
}

#slotHead span {
  padding-left: 0.7em;
}

#slotHead .team {
  display: none;
}

#slotHead.teamed {
  grid-template-columns: 52px 1fr 96px 148px;
}

#slotHead.teamed .team {
  display: block;
}

/* Somebody new: said in a line, and their row glows yellow for a while. */
#newcomer {
  margin: 0 0 8px;
  padding: 8px 12px;
  border-radius: 12px;
  background: #ffe066;
  font-weight: 700;
  text-align: center;
  animation: appear 0.3s;
}

#slots li.fresh {
  background: #fff3b0;
  border-color: #f2b705;
  box-shadow: 0 0 0 4px rgba(255, 210, 40, 0.55);
}

#mode {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px;
  flex-wrap: wrap;
}

#mapPick {
  margin: 0 0 10px;
  padding: 8px 12px 10px;
  background: #fff;
  border: 2px solid var(--line);
  border-radius: 14px;
  font-weight: 700;
}

#mapSel {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 6px;
  margin-top: 6px;
}

#mapSel button {
  display: grid;
  justify-items: center;
  gap: 2px;
  padding: 6px 2px;
  border-radius: 12px;
  background: var(--cream);
  font-size: 13px;
}

#mapSel button i {
  font-style: normal;
  font-size: 28px;
  line-height: 1.1;
}

#mapSel button.on {
  background: #ffe27a;
  border-color: #e0a800;
  box-shadow: 0 0 0 2px #e0a800;
}

#mapSel button:disabled {
  cursor: default;
  opacity: 0.45;
}

#mapSel button.on:disabled {
  opacity: 1;
}

#mode button {
  padding: 0.35em 0.9em;
}

#mode button.on {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

#mode button:disabled {
  opacity: 1;
  cursor: default;
}

#modeNow {
  padding: 0.35em 1em;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font-size: 15px;
}

#modeNow.team {
  background: linear-gradient(90deg, #e5484d, #3e63dd);
}

#teamInfo {
  margin-left: auto;
  font-weight: 700;
}

#addSlot {
  display: block;
  width: 100%;
  margin: -10px 0 18px;
  border-style: dashed;
  background: transparent;
  color: #a07a45;
}

.bubble {
  position: absolute;
  left: 34px;
  bottom: calc(100% - 12px);
  z-index: 5;
  max-width: 80%;
  padding: 4px 10px;
  background: #fff;
  border: 2px solid var(--c);
  border-radius: 12px 12px 12px 3px;
  box-shadow: 0 3px 8px rgba(58, 42, 26, 0.18);
  font-size: 14px;
  overflow-wrap: anywhere;
  pointer-events: none;
}

.bubble b {
  color: var(--c);
}

#slots li.closed {
  opacity: 0.5;
}

/* Nobody sits here: a dashed outline with no face and no colour. */
#slots li.vacant {
  background: transparent;
  border: 2px dashed var(--line);
  padding-left: 12px;
}

#slots li.vacant > span {
  height: 46px;
}

#slots li.vacant input,
#slots li.vacant select {
  background: transparent;
  border-style: dashed;
  color: #a07a45;
}

#slots canvas {
  width: 52px;
  height: 46px;
}

#slots input,
#slots select {
  font: inherit;
  color: var(--ink);
  min-width: 0;
  width: 100%;
  padding: 0.45em 0.6em;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: var(--cream);
}

#slots input {
  font-weight: 700;
}

#invite,
#joinFail {
  margin: 0 0 18px;
  padding: 12px;
  background: #fff;
  border: 2px dashed var(--line);
  border-radius: 14px;
  text-align: center;
}

#joinFail p {
  margin: 0 0 10px;
  font-size: 14px;
}

#newRoom {
  display: block;
  width: 100%;
  font-size: 18px;
  padding: 0.6em;
  margin-bottom: 10px;
}

#retryJoin {
  font-size: 13px;
  padding: 0.35em 1em;
}

#netStatus {
  margin: -8px 0 18px;
  padding: 10px 12px;
  background: #fff;
  border: 2px dashed var(--line);
  border-radius: 14px;
  font-size: 14px;
}

#invite .row {
  margin-top: 6px;
  justify-content: stretch;
}

#invite input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  padding: 0.4em 0.6em;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: var(--cream);
}

#roomPw {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  padding: 8px 12px;
  background: #fff;
  border: 2px solid var(--line);
  border-radius: 14px;
  font-weight: 700;
}

#roomPw input,
#pwForm input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  padding: 0.35em 0.6em;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: var(--cream);
}

#roomPw input:disabled {
  border-color: transparent;
  background: transparent;
  opacity: 1;
  -webkit-text-fill-color: var(--ink);
}

#pwForm {
  margin: -8px 0 18px;
}

#updateBtn {
  display: block;
  width: 100%;
  margin-bottom: 14px;
  background: #d8f0c8;
  border-color: #9fd08a;
  color: #2f7a3d;
}

#roomListBtn {
  display: block;
  width: 100%;
  margin-bottom: 14px;
}

#rooms {
  margin-bottom: 18px;
  padding: 12px;
  background: #fff;
  border: 2px solid var(--line);
  border-radius: 16px;
}

#roomsStatus {
  margin: 0;
  font-size: 14px;
  color: #a07a45;
}

#roomsStatus:empty {
  display: none;
}

#roomItems {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

#roomItems li {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  align-items: center;
  padding: 8px 10px;
  background: var(--cream);
  border-radius: 12px;
}

#roomItems li div {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 8px;
  min-width: 0;
}

#roomItems small {
  flex-basis: 100%;
  color: #a07a45;
}

#roomItems button {
  padding: 0.45em 0.9em;
}

#roomItems button:disabled {
  opacity: 0.45;
  cursor: default;
}

.badge.mine {
  background: #ffe2a8;
  color: #a06a00;
}

.badge {
  padding: 0.1em 0.6em;
  border-radius: 999px;
  background: #d8f0c8;
  color: #2f7a3d;
  font-size: 12px;
  font-weight: 700;
}

.badge.playing {
  background: #ffe2a8;
  color: #a06a00;
}

.listed {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 13px;
}

#watchRow {
  margin-top: 10px;
}

#watching {
  position: absolute;
  top: 6cqw;
  right: 1.4cqw;
  padding: 0.25em 0.8em;
  border-radius: 999px;
  background: rgba(47, 111, 237, 0.9);
  color: #fff;
}

#netStatus:empty {
  display: none;
}

#start {
  width: 100%;
  font-size: 20px;
  padding: 0.7em;
  margin-bottom: 20px;
}

.howto ul {
  margin: 0;
  padding-left: 1.1em;
  line-height: 1.7;
  font-size: 14.5px;
}

.touch-only {
  display: none;
}

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

#stage {
  height: 100%;
  display: grid;
  place-items: center;
  overflow: hidden;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

#field {
  position: relative;
  width: min(100vw, calc(var(--app-h, 100dvh) * 914 / 560));
  aspect-ratio: 914 / 560;
  container-type: inline-size;
  overflow: hidden;
}

#canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: crosshair;
}

#hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  font-size: clamp(11px, 1.55cqw, 20px);
  font-weight: 700;
}

#hud button {
  pointer-events: auto;
  font-size: 0.85em;
  padding: 0.35em 0.9em;
  background: rgba(255, 255, 255, 0.85);
}

#scores {
  position: absolute;
  top: 1.2cqw;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  /* Leave room for the clock; eight players wrap onto a second row. */
  width: max-content;
  max-width: calc(100% - 14em);
  gap: 0.4em 0.6em;
  white-space: nowrap;
}

/* A crowded game gets smaller chips so they stay off the map's corners. */
#scores.many {
  font-size: 0.8em;
}

.chip {
  display: flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.25em 0.8em;
  background: rgba(255, 255, 255, 0.9);
  border: 0.16em solid var(--c);
  border-radius: 999px;
}

.chip i {
  width: 0.75em;
  height: 0.75em;
  border-radius: 50%;
  background: var(--c);
}

.chip.me {
  box-shadow: 0 0 0 0.18em rgba(255, 255, 255, 0.9);
}

.chip.carry {
  background: #ffe27a;
  animation: pulse 0.5s ease-in-out infinite alternate;
}

.chip small {
  font-size: 0.85em;
  opacity: 0.65;
}

#side {
  position: absolute;
  top: 1.2cqw;
  right: 1.4cqw;
  display: grid;
  justify-items: end;
  gap: 0.4em;
}

#clock {
  padding: 0.25em 0.8em;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-variant-numeric: tabular-nums;
}

/* A guest's line to the host: the round trip, and "relay" when it goes the long way. */
#ping {
  padding: 0.15em 0.7em;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.35);
  color: #c8f5c0;
  font-size: 0.75em;
  font-variant-numeric: tabular-nums;
}

#ping.slow {
  color: #ffd0d0;
}

#clock.overtime {
  background: #e5484d;
  animation: pulse 0.5s ease-in-out infinite alternate;
}

#feed {
  display: grid;
  justify-items: end;
  gap: 0.25em;
  font-size: 0.85em;
}

#feed div {
  padding: 0.2em 0.7em;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.85);
  animation: fade 3.5s forwards;
}

#banner {
  position: absolute;
  top: 6cqw;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.35em 1.1em;
  border-radius: 999px;
  background: rgba(58, 42, 26, 0.88);
  color: #fff;
  font-size: 1.15em;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.25s;
}

#banner.show {
  opacity: 1;
}

#banner.alarm {
  background: rgba(214, 30, 30, 0.94);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.85);
  animation: alarm 0.35s ease-in-out infinite alternate;
}

@keyframes alarm {
  to {
    transform: translateX(-50%) scale(1.07);
  }
}

#big {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 13cqw;
  font-weight: 900;
  color: #fff;
  -webkit-text-stroke: 0.06em var(--ink);
  paint-order: stroke fill;
}

#callout {
  position: absolute;
  top: 24%;
  left: 0;
  right: 0;
  display: grid;
  justify-items: center;
  pointer-events: none;
}

#callout div {
  display: grid;
  justify-items: center;
  line-height: 1.1;
  /* See-through, so a shout never hides the hamsters under it. */
  opacity: 0.75;
  animation: shout 1.3s ease-out forwards;
}

#callout b {
  font-size: 1em;
  -webkit-text-stroke: 0.14em #fff;
  paint-order: stroke fill;
}

#callout span {
  font-size: clamp(17px, 4.2cqw, 44px);
  font-weight: 900;
  color: #fff;
  -webkit-text-stroke: 0.07em var(--ink);
  paint-order: stroke fill;
}

#callout span.super {
  color: #ffd23f;
  font-size: clamp(14px, 3.4cqw, 36px);
}

#big span {
  animation: pop 0.9s ease-out forwards;
}

#hint,
#hintTouch {
  position: absolute;
  bottom: 1.4cqw;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.3em 1em;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 0.9em;
  white-space: nowrap;
  transition: opacity 0.6s;
}

/* Phones have no keyboard, so they get their own line about the touch controls. */
#hintTouch {
  display: none;
  position: fixed;
  left: 50%;
  bottom: max(8px, env(safe-area-inset-bottom));
  max-width: calc(100vw - 330px);
  white-space: normal;
  border-radius: 14px;
  font-size: 13px;
}

#tools {
  position: absolute;
  bottom: 1.4cqw;
  left: 1.4cqw;
  display: flex;
  gap: 0.4em;
}

/* On a wide screen the buttons sit in a row; a tall one folds them behind "⋯". */
#toolsMenu {
  display: contents;
}

#toolsMore {
  display: none;
}

/* A faint ring of four arrow keys, always in the same corner: a doughnut cut in
   quarters, with a small hole in the middle that is no key at all. The thumb's
   angle from the middle picks the key, so a touch a little outside still counts. */
#pad {
  display: none;
  position: fixed;
  left: max(6px, env(safe-area-inset-left));
  bottom: max(2px, env(safe-area-inset-bottom));
  width: 148px;
  height: 148px;
  border-radius: 50%;
  touch-action: none;
}

#pad::before {
  content: '';
  position: absolute;
  inset: -12px;
  border-radius: 50%;
}

#pad svg {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

#pad path {
  fill: rgba(255, 255, 255, 0.2);
  stroke: rgba(255, 255, 255, 0.55);
  stroke-width: 1.2;
  stroke-linejoin: round;
}

#pad .arrow {
  fill: rgba(255, 255, 255, 0.8);
  stroke: none;
}

#pad[data-y='-1'] .u path,
#pad[data-x='-1'] .l path,
#pad[data-x='1'] .r path,
#pad[data-y='1'] .d path {
  fill: rgba(255, 255, 255, 0.8);
}

#pad[data-y='-1'] .u .arrow,
#pad[data-x='-1'] .l .arrow,
#pad[data-x='1'] .r .arrow,
#pad[data-y='1'] .d .arrow {
  fill: var(--ink);
}

.bonk-left #pad {
  left: auto;
  right: max(6px, env(safe-area-inset-right));
}

#bonk {
  display: none;
  position: fixed;
  right: max(22px, env(safe-area-inset-right));
  bottom: max(22px, env(safe-area-inset-bottom));
  width: clamp(84px, 20vmin, 128px);
  height: clamp(84px, 20vmin, 128px);
  padding: 0;
  font-size: clamp(17px, 4.4vmin, 26px);
  background: rgba(255, 180, 0, 0.9);
  border: 3px solid #fff;
  touch-action: none;
}

/* Sits above the bonk button while this player carries a seed. */
#throw {
  display: none;
  position: fixed;
  right: max(22px, env(safe-area-inset-right));
  bottom: calc(max(22px, env(safe-area-inset-bottom)) + clamp(84px, 20vmin, 128px) + 12px);
  width: clamp(84px, 20vmin, 128px);
  padding: 0.5em 0;
  font-size: clamp(14px, 3.6vmin, 20px);
  background: rgba(255, 226, 122, 0.95);
  border: 3px solid #fff;
  touch-action: none;
  /* Over the ground the bonk button claims around itself. */
  z-index: 1;
}

.bonk-left #throw {
  right: auto;
  left: max(22px, env(safe-area-inset-left));
}

#bonk:active {
  transform: scale(0.92);
}

/* Glass has no edge to feel for, so a thumb that lands just off the button still
   counts. */
#bonk::before {
  content: '';
  position: absolute;
  inset: -22px;
  border-radius: 50%;
}

/* The wait until the next swing, wiped off the button like a clock hand: the arc
   under the hamster is too small to read on a phone. */
#bonk::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: conic-gradient(rgba(58, 42, 26, 0.6) calc(var(--cool, 0) * 1turn), transparent 0);
  pointer-events: none;
}

/* No bonking at home. */
#bonk.off {
  opacity: 0.4;
}

.bonk-left #bonk {
  right: auto;
  left: max(22px, env(safe-area-inset-left));
}

.bonk-left #tools,
.bonk-left #gameChat {
  left: auto;
  right: 1.4cqw;
}

#result {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(20, 40, 20, 0.5);
  animation: appear 0.3s;
}

#result .card {
  padding: 22px 30px;
  text-align: center;
  min-width: min(380px, 90%);
}

#result h2 {
  margin: 0 0 12px;
  font-size: clamp(20px, 3.2cqw, 34px);
}

/* The verdict: a win is gold and bouncing, a loss is grey, heavy and sunk. */
#resultTitle.win {
  font-size: clamp(30px, 5.4cqw, 56px);
  font-weight: 900;
  letter-spacing: 0.04em;
  color: #ff9f1a;
  background: linear-gradient(180deg, #ffe066, #ff8a00);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 2px 0 #b35a00) drop-shadow(0 0 10px rgba(255, 190, 40, 0.7));
  animation: pulse 0.5s ease-in-out infinite alternate;
}

#resultTitle.lose {
  font-size: clamp(28px, 5cqw, 52px);
  font-weight: 900;
  letter-spacing: 0.3em;
  /* The spacing trails the last letter too; this keeps the word centred. */
  padding-left: 0.3em;
  color: #6b7280;
  text-shadow: 0 2px 0 #374151;
  filter: grayscale(1);
  transform: rotate(-2deg);
  animation: sink 0.6s ease-out both;
}

@keyframes sink {
  from {
    transform: translateY(-18px) rotate(0deg);
    opacity: 0;
  }
  to {
    transform: translateY(0) rotate(-2deg);
    opacity: 1;
  }
}

#resultWinner {
  margin: 0 0 6px;
  font-size: clamp(15px, 2.2cqw, 22px);
  font-weight: 800;
}

#resultWhy {
  margin: 0 0 12px;
  color: #a07a45;
  font-size: clamp(12px, 1.6cqw, 16px);
  font-weight: 700;
}

#resultWait {
  margin: 0 0 14px;
  color: #a07a45;
  font-size: clamp(12px, 1.6cqw, 16px);
  font-weight: 700;
  animation: pulse 0.8s ease-in-out infinite alternate;
}

.scoreTable {
  width: 100%;
  margin-bottom: 16px;
  border-collapse: collapse;
  font-size: clamp(12px, 1.6cqw, 16px);
}

.scoreTable th {
  color: #a07a45;
  font-weight: 600;
}

.scoreTable th,
.scoreTable td {
  padding: 5px 8px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.scoreTable th:first-child,
.scoreTable td:first-child {
  text-align: left;
  font-weight: 700;
}

.scoreTable tr.winner td {
  background: #ffe9a8;
}

.scoreTable tr.winner td:first-child {
  border-radius: 10px 0 0 10px;
}

.scoreTable tr.winner td:last-child {
  border-radius: 0 10px 10px 0;
}

.row {
  display: flex;
  gap: 10px;
  justify-content: center;
}

@keyframes pulse {
  to {
    transform: scale(1.06);
  }
}

@keyframes fade {
  0%,
  75% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes pop {
  0% {
    transform: scale(0.4);
    opacity: 0;
  }
  25% {
    transform: scale(1.1);
    opacity: 1;
  }
  70% {
    transform: scale(1);
    opacity: 1;
  }
  100% {
    transform: scale(1.3);
    opacity: 0;
  }
}

@keyframes shout {
  0% {
    transform: scale(0.5);
    opacity: 0;
  }
  20% {
    transform: scale(1.08);
    opacity: 0.75;
  }
  65% {
    transform: scale(1);
    opacity: 0.75;
  }
  100% {
    transform: scale(1.1);
    opacity: 0;
  }
}

@keyframes appear {
  from {
    opacity: 0;
  }
}

@media (pointer: coarse) {
  #bonk {
    display: block;
  }

  #throw:not([hidden]) {
    display: block;
  }

  #hint {
    display: none;
  }

  /* Hidden inline in the page so a stale stylesheet cannot show it unstyled. */
  #hintTouch {
    display: block !important;
  }

  /* Gone once the pad has been touched. */
  .played #hintTouch {
    opacity: 0;
  }

  #pad {
    display: grid;
  }

  .touch-only {
    display: inline;
  }
}

@container (max-width: 620px) {
  #scores {
    left: 1.4cqw;
    transform: none;
    justify-content: flex-start;
  }

  /* No room for the dot, but how many wins each has is the whole race. */
  .chip i {
    display: none;
  }

  .chip {
    gap: 0.25em;
  }
}

/* Tall screens get the map turned a quarter so it fills the screen. */
@media (orientation: portrait) {
  #stage {
    align-content: start;
  }

  #field {
    /* The map takes the whole width so the hamsters are as big as they can be; the
       controls lie over its foot, on the burrow floor, where the screen is short. */
    width: min(100vw, calc(var(--app-h, 100dvh) * 560 / 914));
    aspect-ratio: 560 / 914;
  }

  #hud {
    font-size: clamp(14px, 4.2cqw, 24px);
  }

  #big {
    font-size: 22cqw;
  }

  #scores.many {
    font-size: 0.68em;
  }

  #banner {
    top: 12cqw;
  }
}

@media (max-width: 480px) {
  #lobby .card {
    padding: 20px 16px 18px;
  }

  #lobby h1 {
    font-size: 32px;
  }

  #slots li,
  #slotHead {
    grid-template-columns: 46px 1fr 118px;
  }

  #slots li.teamed,
  #slotHead.teamed {
    grid-template-columns: 46px 1fr 78px 96px;
    gap: 6px;
  }

  #slots li.teamed select {
    padding: 0.45em 0.3em;
  }
}

/* On a tall screen the buttons and hints live in the strip under the map. */
@media (orientation: portrait) {
  /* The pad has one corner of the strip and the bonk button the other: the menu
     sits between them. */
  #tools,
  .bonk-left #tools {
    position: fixed;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    bottom: max(14px, env(safe-area-inset-bottom));
    font-size: 19px;
  }

  #tools button {
    min-height: 44px;
    padding: 0.35em 1em;
  }

  /* The strip under the map is too narrow for every button beside the bonk
     button, so they fold into a menu that opens upwards. */
  #toolsMore {
    display: inline-block;
  }

  #toolsMore.unread::after {
    content: '';
    position: absolute;
    top: 4px;
    right: 4px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #e23d3d;
    border: 2px solid #fff;
  }

  #toolsMore {
    position: relative;
  }

  #toolsMenu {
    display: none;
    position: absolute;
    left: 0;
    bottom: calc(100% + 8px);
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    white-space: nowrap;
  }

  #tools.open #toolsMenu {
    display: flex;
  }

  /* Over the map the menu has to read clearly. */
  #tools #toolsMenu button {
    background: rgba(255, 255, 255, 0.92);
  }

  .bonk-left #toolsMenu {
    left: auto;
    right: 0;
  }

  #hint,
  #hintTouch {
    position: fixed;
    left: 50%;
    bottom: calc(max(2px, env(safe-area-inset-bottom)) + 162px);
    width: max-content;
    max-width: 92vw;
    white-space: normal;
    border-radius: 14px;
    font-size: 15px;
  }

  #bonk {
    right: max(14px, env(safe-area-inset-right));
    bottom: max(6px, env(safe-area-inset-bottom));
    width: 100px;
    height: 100px;
    font-size: 22px;
  }

  .bonk-left #bonk {
    left: max(14px, env(safe-area-inset-left));
  }

}

/* On a wide phone the menu runs along the bottom of the map, so the pad sits above it. */
@media (pointer: coarse) and (orientation: landscape) {
  #pad {
    bottom: max(64px, env(safe-area-inset-bottom));
  }
}

/* ---------- chat ---------- */

.chat .chatLog div {
  overflow-wrap: anywhere;
}

.chatForm {
  display: flex;
  gap: 6px;
}

.chatForm input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 14px;
  color: var(--ink);
  padding: 0.4em 0.7em;
  border: 2px solid var(--line);
  border-radius: 10px;
  background: #fff;
}

.chatForm button {
  font-size: 14px;
  padding: 0.3em 0.9em;
}

#lobbyChat {
  margin: -8px 0 18px;
  padding: 10px 12px;
  background: #fff;
  border: 2px solid var(--line);
  border-radius: 14px;
  font-size: 14px;
}

/* No tall empty box: the log takes room only as lines come in. */
#lobbyChat .chatLog {
  max-height: 96px;
  overflow-y: auto;
  margin-bottom: 8px;
  line-height: 1.5;
}

#lobbyChat .chatLog:empty,
#resultChat .chatLog:empty {
  display: none;
}

/* On a phone these boxes are typed into through the bar on the keyboard. */
@media (pointer: coarse) {
  #lobbyChat .chatForm button,
  #resultChat .chatForm button {
    display: none;
  }
}

#gameChat {
  position: absolute;
  left: 1.4cqw;
  bottom: 6cqw;
  width: min(46cqw, 340px);
  font-size: clamp(12px, 1.4cqw, 16px);
  font-weight: 600;
}

#gameChat .chatLog div {
  width: fit-content;
  max-width: 100%;
  margin-top: 0.25em;
  padding: 0.15em 0.7em;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.88);
  animation: fade 14s forwards;
}

/* Typing on a phone, and mid-round anywhere: one bar across the screen, which the
   script seats on top of the keyboard (or on the bottom edge where there is none). */
#chatBar {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  z-index: 20;
  align-items: center;
  gap: 8px;
  padding: 8px max(10px, env(safe-area-inset-right)) 8px max(10px, env(safe-area-inset-left));
  background: rgba(226, 235, 243, 0.97);
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.18);
}

#chatBar input {
  font-size: 16px;
  padding: 0.55em 1em;
  border: 0;
  border-radius: 999px;
}

#chatBar button {
  flex: none;
  width: 40px;
  height: 40px;
  padding: 0;
  font-size: 20px;
  line-height: 1;
  border: 0;
  background: #fbe54d;
}

@media (orientation: portrait) {
  /* Above the pad and the bonk button, which lie over the foot of the map. */
  #gameChat {
    bottom: 46cqw;
    width: 70cqw;
    font-size: 13px;
  }
}

/* Quick chat: one tap sends a ready-made line. */
.quick {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}

.quick button {
  font-size: 13px;
  padding: 0.3em 0.8em;
  background: var(--cream);
}

@media (pointer: coarse) {
  /* iOS zooms the page when a focused field's text is under 16px. */
  input,
  select {
    font-size: 16px !important;
  }

}
}

#lobbyChatBtn {
  display: block;
  margin: -8px 0 18px;
  font-size: 14px;
  padding: 0.4em 1em;
}

#resultChatBtn {
  margin: 0 0 12px;
  font-size: 14px;
  padding: 0.4em 1em;
}

#resultChat {
  margin: 0 0 14px;
  padding: 10px 12px;
  background: #fff;
  border: 2px solid var(--line);
  border-radius: 14px;
  font-size: 14px;
  text-align: left;
}

#resultChat .chatLog {
  max-height: 84px;
  overflow-y: auto;
  margin-bottom: 8px;
  line-height: 1.5;
}

#result .card {
  max-height: 96%;
  overflow-y: auto;
}

/* Scores mid-round: hold Tab, or the chart button on a phone. */
#board {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(20, 40, 20, 0.3);
  z-index: 4;
}

#board .card {
  padding: 14px 20px;
  min-width: min(380px, 90%);
}

#board .scoreTable {
  margin-bottom: 0;
}

/* Running totals sit apart from this round's numbers. */
.scoreTable .total {
  color: #8a6a3a;
}

.scoreTable th {
  white-space: nowrap;
}

.scoreTable .score {
  font-weight: 800;
  color: var(--ink);
}

.scoreTable .rule td {
  padding-top: 10px;
  color: #a07a45;
  font-size: 0.85em;
  font-weight: 600;
  text-align: center;
}

.scoreTable .prize {
  padding-left: 0.2em;
  text-align: left;
}

.scoreTable .prize .mvp {
  margin-left: 0;
}

/* The MVP badge is meant to be loud: gold that shimmers, wobbles and sparkles. */
.mvp {
  position: relative;
  display: inline-block;
  margin-left: 0.45em;
  padding: 0.08em 0.55em;
  border-radius: 999px;
  border: 2px solid #fff;
  background: linear-gradient(110deg, #ff7a00, #ffd23f 25%, #fff6c2 40%, #ffd23f 55%, #ff3d81 80%, #7b5cff);
  background-size: 250% 100%;
  color: #5b2a00;
  font-size: 0.82em;
  font-weight: 900;
  letter-spacing: 0.06em;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
  box-shadow: 0 0 0 2px #ffb300, 0 0 12px 3px rgba(255, 190, 0, 0.75);
  animation: mvpShine 1.4s linear infinite, mvpWobble 0.9s ease-in-out infinite alternate;
}

.mvp::before,
.mvp::after {
  content: '✦';
  position: absolute;
  color: #fff;
  font-size: 0.9em;
  text-shadow: 0 0 6px #ffd23f, 0 0 2px #ff7a00;
  animation: mvpSpark 1.1s ease-in-out infinite;
}

.mvp::before {
  top: -0.75em;
  left: -0.35em;
}

.mvp::after {
  right: -0.4em;
  bottom: -0.7em;
  animation-delay: 0.55s;
}

/* This round's goal scorer: a sunflower-green stamp that bounces. */
.goalBadge {
  display: inline-block;
  margin-left: 0.45em;
  padding: 0.08em 0.55em;
  border-radius: 999px;
  border: 2px solid #fff;
  background: #1f9d55;
  color: #fff;
  font-size: 0.82em;
  font-weight: 900;
  box-shadow: 0 0 0 2px #157a40;
  animation: goalBounce 0.5s ease-in-out infinite alternate;
}

@keyframes goalBounce {
  to {
    transform: translateY(-0.18em) scale(1.08);
  }
}

@keyframes mvpShine {
  to {
    background-position: -250% 0;
  }
}

@keyframes mvpWobble {
  from {
    transform: rotate(-5deg) scale(1);
  }
  to {
    transform: rotate(4deg) scale(1.12);
  }
}

@keyframes mvpSpark {
  0%,
  100% {
    transform: scale(0.3) rotate(0deg);
    opacity: 0;
  }
  50% {
    transform: scale(1.2) rotate(90deg);
    opacity: 1;
  }
}

.scoreTable .split {
  border-left: 2px solid var(--line);
}

.scoreTable .groups th {
  padding-bottom: 0;
  font-size: 0.85em;
  font-weight: 700;
  text-align: center;
}

.scoreTable .groups th:first-child {
  text-align: left;
  white-space: nowrap;
}

/* What all these games are for, under the game's number. */
.scoreTable .groups th small {
  display: block;
  font-weight: 600;
  opacity: 0.7;
}

/* A narrow screen shows this round or the running totals, one at a time. */
.scoreTable caption {
  display: none;
}

@media (max-width: 640px), (orientation: portrait) {
  .scoreTable {
    font-size: 13px;
  }

  .scoreTable caption {
    display: table-caption;
    caption-side: top;
    padding-bottom: 8px;
  }

  .scoreTabs {
    display: flex;
    gap: 6px;
  }

  .scoreTabs button {
    flex: 1;
    padding: 0.35em 0.6em;
    font-size: 14px;
    opacity: 0.6;
    pointer-events: auto;
  }

  .scoreTabs button.on {
    background: #ffd23f;
    opacity: 1;
  }

  .scoreTable[data-view='round'] .total,
  .scoreTable[data-view='total'] .round,
  .scoreTable .groups th.round,
  .scoreTable .groups th.total {
    display: none;
  }

  .scoreTable .split {
    border-left: 0;
  }

  /* The row's other headings are gone here, so it sits beside the number, out
     of the name column's width. */
  .scoreTable .groups th:first-child {
    position: relative;
  }

  .scoreTable .groups th small {
    position: absolute;
    left: 100%;
    bottom: 0;
    margin-left: 0.6em;
    font-size: 1em;
  }

  .scoreTable th {
    white-space: normal;
  }

  .scoreTable th,
  .scoreTable td {
    padding: 4px 3px;
  }
}

/* The result card can be put away to look at the map and reach the other buttons. */
#result .card {
  position: relative;
}

#resultClose {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 46px;
  height: 46px;
  padding: 0;
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
}

/* An empty or closed seat is one big button for the host. */
#slots li.seat {
  cursor: pointer;
}

#slots li.seat input {
  pointer-events: none;
}

/* ---------- championship ---------- */

#champ {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(20, 30, 10, 0.72);
  z-index: 6;
  animation: appear 0.4s;
}

#champ .card {
  padding: 14px 28px 18px;
  text-align: center;
  min-width: min(360px, 92%);
  max-height: 96%;
  overflow-y: auto;
}

#trophy {
  width: min(220px, 46vw);
  aspect-ratio: 300 / 250;
  display: block;
  margin: 0 auto;
}

#champTitle {
  margin: 0 0 8px;
  font-size: clamp(22px, 3.6cqw, 38px);
}

#champNames {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 18px;
  margin-bottom: 10px;
  font-size: clamp(18px, 2.6cqw, 28px);
  font-weight: 800;
}

#champNames div {
  display: flex;
  align-items: center;
  gap: 6px;
}

#champNames canvas {
  width: 52px;
  height: 46px;
}

/* The full record under the trophy. It has many columns: keep it inside the card,
   and let the card scroll sideways on a narrow screen rather than spill out. */
#champ .card {
  box-sizing: border-box;
  max-width: 98%;
  overflow-x: auto;
}

#champStats {
  margin: 4px auto 10px;
  font-size: clamp(11px, 1.35cqw, 15px);
}

#champStats th,
#champStats td {
  padding: 4px 6px;
}

#champNote {
  margin: 0;
  color: #a07a45;
  font-size: 13px;
}

#champ .card {
  position: relative;
}

#champClose {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 46px;
  height: 46px;
  padding: 0;
  font-size: 26px;
  font-weight: 800;
  line-height: 1;
}

#champLobby {
  margin-top: 10px;
}

@media (max-width: 640px), (orientation: portrait) {
  #champ .card {
    padding: 12px 8px 14px;
  }

  #champStats {
    font-size: 11px;
  }

  #champStats th,
  #champStats td {
    padding: 4px 2px;
  }
}

#seasonList {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
}

#seasonList li {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 12px;
  padding: 8px 12px;
  margin-bottom: 6px;
  background: #fff;
  border: 2px solid var(--line);
  border-radius: 12px;
  font-weight: 600;
}

#seasonList b {
  flex-basis: 100%;
  color: #a07a45;
}

#seasonList .champ {
  font-weight: 800;
}

/* ---------- see-through round overlays ----------
   Nothing drawn over a round may hide the map: backgrounds are mostly clear and
   the text carries a halo so it still reads over grass, hedge and burrow. */

#scores .chip,
#feed div,
#gameChat .chatLog div {
  background: rgba(255, 255, 255, 0.32);
  text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 5px #fff;
}

#scores .chip {
  border-color: color-mix(in srgb, var(--c) 70%, transparent);
}

#scores .chip.me {
  box-shadow: 0 0 0 0.18em rgba(255, 255, 255, 0.45);
}

#scores .chip.carry {
  background: rgba(255, 226, 122, 0.55);
}

#scores .chip small {
  opacity: 0.85;
}

#clock,
#hint,
#hintTouch {
  background: rgba(0, 0, 0, 0.22);
  text-shadow: 0 0 3px #000, 0 0 3px #000, 0 1px 4px #000;
}

#clock.overtime {
  background: rgba(229, 72, 77, 0.5);
}

#banner {
  background: rgba(58, 42, 26, 0.4);
  text-shadow: 0 0 3px #000, 0 0 3px #000, 0 1px 5px #000;
}

#banner.alarm {
  background: rgba(214, 30, 30, 0.48);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.45);
}

#tools button {
  background: rgba(255, 255, 255, 0.4);
  border-color: rgba(232, 220, 190, 0.6);
  box-shadow: none;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff;
}

#tools button.primary {
  background: rgba(246, 185, 44, 0.6);
}

/* The mid-round score table: the map stays in view behind the numbers. */
#board {
  background: none;
  pointer-events: none;
}

#board .card {
  background: rgba(255, 248, 230, 0.38);
  border-color: rgba(232, 220, 190, 0.5);
  box-shadow: none;
  pointer-events: auto;
}

#board .scoreTable th,
#board .scoreTable td {
  color: var(--ink);
  font-weight: 700;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 6px #fff, 0 0 6px #fff;
}

#board .scoreTable tr.winner td {
  background: rgba(255, 233, 168, 0.4);
}

#board .scoreTable .split {
  border-left-color: rgba(120, 90, 40, 0.35);
}
