/* The game's own palette, set once (as in Alien Algebra): a pale sage page,
   white paper, spring-teal ink and buttons. Green means right and rose means
   corrected. The three box colors, sky, apricot and plum, stay clear of
   both and of the teal. Box colors are RGB triplets for alpha tints. */
:root {
  --page: #eef3ea;
  --paper: #ffffff;
  --ink: #23362d;
  --muted: #5f7268;
  --line: #dde5dc;
  --accent: #1e5d63;
  --right-ink: #2f6b3f;
  --fixed-ink: #a23a4e;
  --A: 59 130 196;
  --B: 224 135 63;
  --C: 139 90 166;
  /* Tints of the colors above. */
  --band: color-mix(in oklab, var(--page), var(--paper) 45%);
  --meadow: color-mix(in oklab, var(--page), var(--right-ink) 7%);
  --accent-hover: color-mix(in oklab, var(--accent) 80%, black);
  --right-soft: color-mix(in oklab, var(--paper), var(--right-ink) 12%);
  --right-line: color-mix(in oklab, var(--paper), var(--right-ink) 40%);
  --fixed-soft: color-mix(in oklab, var(--paper), var(--fixed-ink) 10%);
  --fixed-line: color-mix(in oklab, var(--paper), var(--fixed-ink) 40%);
  --lift: 0 1px 3px rgb(35 54 45 / 0.09);

  --gk-card: var(--paper);
  --gk-ink: var(--ink);
  --gk-muted: var(--muted);
  --gk-line: var(--line);
  --gk-accent: var(--accent);
  --gk-accent-ink: var(--paper);
  --gk-menu-ink: var(--accent);
}

/* The page color runs under the whole area. */
body {
  background: var(--page);
  color: var(--ink);
}

.frame {
  position: relative;
  max-width: 932px;
  margin: 0 auto;
  padding: 16px 16px 32px;
}

/* The menu buttons sit above the intro and results, lined up on the right. */
.menu-top {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 8px;
}

.kicker {
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
}

/* ---------- buttons ---------- */

/* The main action of a step: a comfortable size on a laptop, the full
   width of the column on a phone. */
.gk-button-primary.wide {
  width: auto;
  min-width: 220px;
}

/* ---------- intro and results ---------- */

.intro {
  max-width: 600px;
  margin: 0 auto;
}

/* The start screen: centered, and on a phone the title and picture sit in
   the middle of the space above Start. */
.intro.start {
  text-align: center;
}

.hero-title {
  margin: 8px 0 12px;
  font-size: 56px;
  line-height: 1;
  color: var(--ink);
}

.hero-title.small {
  font-size: 40px;
  margin-top: 0;
}

.pitch {
  margin: 0 0 18px;
  font-size: 17px;
}

/* The start screen's picture: the three trait boxes and four capybaras. */
.cast {
  display: block;
  width: 100%;
  max-width: 360px;
  margin: 28px auto 36px;
}

.cast .box {
  stroke-width: 2;
}

.cast .box-A {
  fill: rgb(var(--A) / 0.12);
  stroke: rgb(var(--A));
}

.cast .box-B {
  fill: rgb(var(--B) / 0.14);
  stroke: rgb(var(--B));
}

.cast .box-C {
  fill: rgb(var(--C) / 0.12);
  stroke: rgb(var(--C));
}

/* A fourth box, gold, only on the start screen. */
.cast .box-D {
  fill: rgb(196 152 30 / 0.14);
  stroke: rgb(196 152 30);
}

.cast .shadow {
  fill: rgb(0 0 0 / 0.1);
}

/* Results: every round on one card. */
.rounds {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  background: var(--paper);
  border-radius: 16px;
  box-shadow: var(--lift);
  overflow: hidden;
}

.rounds > li + li {
  border-top: 1px solid var(--line);
}

/* Each round's row opens to its review. */
.rounds summary {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto 14px;
  column-gap: 10px;
  align-items: baseline;
  padding: 10px 16px;
  font-size: 15px;
  line-height: 1.45;
  list-style: none;
  cursor: pointer;
}

.rounds summary::-webkit-details-marker {
  display: none;
}

.rounds summary::after {
  content: "›";
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  transition: transform 0.15s;
}

.rounds details[open] summary::after {
  transform: rotate(90deg);
}

.rounds summary:hover {
  background: var(--band);
}

.rounds-hint {
  margin: -8px 0 10px;
  font-size: 13px;
  color: var(--muted);
}

.review {
  padding: 4px 16px 16px 46px;
  font-size: 15px;
}

.review .group-label {
  margin: 10px 0 4px;
}

.review-premises {
  list-style: none;
  margin: 0;
  padding: 0;
}

.review-premises li {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  column-gap: 10px;
  padding: 3px 0;
  line-height: 1.5;
}

.review .conclusion {
  font-size: 17px;
}

.review-line {
  margin: 10px 0 0;
  font-size: 14px;
  color: var(--muted);
}

.review-line b {
  color: var(--ink);
}

.why-label {
  margin: 14px 0 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}

.review .why {
  margin: 0;
}

.review .line {
  margin: 8px 0 0;
  font-size: 14px;
}

.rounds .mark {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
}

.rounds .mark svg {
  display: block;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rounds .ok .mark {
  color: var(--right-ink);
}

.rounds .no .mark {
  color: var(--fixed-ink);
}

.rounds .skipped .mark {
  color: var(--muted);
}

.rounds .kind {
  display: block;
  font-size: 12px;
  color: var(--muted);
}

.rounds .earned {
  font-weight: 600;
  white-space: nowrap;
}

/* ---------- round ---------- */

/* Count on the left, points and the menu on the right, then a bar for the
   whole run under them. */
.bar {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 32px;
  font-size: 14px;
}

.bar .count {
  color: var(--muted);
  white-space: nowrap;
}

/* Skip round, after the count; once pressed it asks in place, and the
   points step aside to make room on a phone. */
.bar .skip,
.bar .skip-no {
  padding: 0;
  font: inherit;
  color: var(--accent);
  background: none;
  border: 0;
  cursor: pointer;
}

.bar .skip {
  margin-left: 12px;
  text-decoration: underline;
  text-decoration-color: color-mix(in oklab, var(--accent) 35%, transparent);
  text-underline-offset: 3px;
}

.bar .skip:hover,
.bar .skip-no:hover {
  color: var(--accent-hover);
}

.skip-ask {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  color: var(--ink);
}

.bar .skip-yes {
  padding: 4px 12px;
  font: inherit;
  font-weight: 700;
  color: var(--paper);
  background: var(--accent);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.bar .skip-no {
  padding: 4px 2px;
  font-weight: 600;
}

.bar.asking .score {
  display: none;
}

.bar.asking .menu {
  margin-left: auto;
}

.score {
  margin-left: auto;
  font-weight: 600;
  white-space: nowrap;
}

.score b {
  display: inline-block;
}

.marks {
  display: flex;
  gap: 5px;
  margin: 8px 0 16px;
}

.pip {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: var(--line);
}

.pip.right {
  background: var(--right-line);
}

.pip.wrong {
  background: var(--fixed-line);
}

.pip.now {
  background: var(--accent);
}

.pip.skipped {
  background: color-mix(in oklab, var(--muted), var(--paper) 50%);
}

/* Narrow screens: argument, answer or feedback, then the board, one under
   the other. */
.play {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "statement" "below" "board";
  gap: 14px;
  justify-items: center;
}

.play > * {
  width: 100%;
  max-width: 900px;
}

.statement {
  grid-area: statement;
}

/* Building, one column: the board right after the argument, then the
   status line and Submit. The coach card, when it shows, sits between the
   argument and the board. */
.play.building {
  grid-template-areas: "statement" "board" "below";
}

.play.building.coaching {
  grid-template-areas: "statement" "coach" "board" "below";
}

.coach-host {
  grid-area: coach;
}

.coach-host:empty {
  display: none;
}

.coach-host .coach {
  margin: 0;
}

/* ---------- argument ---------- */

/* The premises sit on a tinted band as the givens; a dark rule, then the
   proposed conclusion on white paper. */
.argument {
  background: var(--paper);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: var(--lift);
}

.given {
  background: var(--band);
  padding: 12px 18px 10px;
}

.proposed {
  border-top: 1.5px solid var(--ink);
  border-radius: 0 0 16px 16px;
  padding: 10px 18px 14px;
}

.group-label {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}

.group-label span {
  font-weight: 400;
}

.premises {
  list-style: none;
  margin: 0;
  padding: 0;
}

.premise {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  column-gap: 10px;
  row-gap: 4px;
  margin: 0 -10px;
  padding: 5px 10px;
  border-radius: 10px;
  transition:
    background-color 0.25s,
    box-shadow 0.25s;
}

.premise + .premise {
  margin-top: 4px;
}

/* With the board in view, every statement shows its truth on the board:
   rose while false, green once true, each with a thin outline so the soft
   green still shows against the sage. Board starts make both premises
   false. */
.premise.fails,
.proposed.fails {
  background: var(--fixed-soft);
  box-shadow: inset 0 0 0 1.5px var(--fixed-line);
}

.premise.holds,
.proposed.holds {
  background: var(--right-soft);
  box-shadow: inset 0 0 0 1.5px var(--right-line);
}

.proposed {
  transition:
    background-color 0.25s,
    box-shadow 0.25s;
}

.premise.fails .num {
  background: var(--fixed-ink);
  box-shadow: none;
  color: var(--paper);
}

.num {
  grid-row: 1 / span 2;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--line);
  font-size: 12px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}

.premise.holds .num {
  background: var(--right-ink);
  box-shadow: none;
  color: var(--paper);
}

.sentence {
  font-size: 16px;
  line-height: 1.5;
}

.conclusion {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.45;
}

/* Once answered, the argument and the explanation mark their parts: each
   quantifier as a dark chip, each clause tinted with its box's fill. While
   the player works, the text is plain. */
.q {
  white-space: nowrap;
}

.marked .q {
  font-weight: 600;
  color: var(--paper);
  background: var(--ink);
  border-radius: 5px;
  padding: 1px 6px;
}

.marked .term {
  border-radius: 4px;
  padding: 0 3px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.marked .term-A {
  background: rgb(var(--A) / 0.2);
}

.marked .term-B {
  background: rgb(var(--B) / 0.22);
}

.marked .term-C {
  background: rgb(var(--C) / 0.2);
}

/* ---------- board ---------- */

.board {
  grid-area: board;
  display: block;
  width: 100%;
  max-width: 900px;
  height: auto;
  border-radius: 14px;
  box-shadow: var(--lift);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

/* A meadow for the animals to stand in. */
.board .meadow {
  fill: var(--meadow);
}

.board .animal {
  pointer-events: none;
  transition: opacity 0.12s;
}

/* Animals outside every box step back, so the ones wearing props stand out. */
.board .animal.outside {
  opacity: 0.38;
}

.board .shadow {
  fill: rgb(0 0 0 / 0.1);
}

.board .box {
  stroke-width: 2.5;
  pointer-events: none;
}

.board .body-hit,
.board .badge-hit {
  fill: transparent;
  cursor: grab;
}

/* The selected box: a heavier outline; the other boxes' handles fade. */
.board .box.selected {
  stroke-width: 3.5;
}

.board .handle.dim {
  opacity: 0.4;
}

.board.locked .box,
.board.locked .handle-hit {
  cursor: default;
}

.board .box-A {
  fill: rgb(var(--A) / 0.18);
  stroke: rgb(var(--A));
}

.board .box-B {
  fill: rgb(var(--B) / 0.2);
  stroke: rgb(var(--B));
}

.board .box-C {
  fill: rgb(var(--C) / 0.18);
  stroke: rgb(var(--C));
}

.board .handle,
.board .badge {
  pointer-events: none;
}

.board .handle-A {
  fill: rgb(var(--A));
}

.board .handle-B {
  fill: rgb(var(--B));
}

.board .handle-C {
  fill: rgb(var(--C));
}

/* A badge: a white circle ringed in the box's color, with the prop inside. */
.board .badge circle {
  fill: var(--paper);
  stroke-width: 2.5;
}

.board .badge-A circle {
  stroke: rgb(var(--A));
}

.board .badge-B circle {
  stroke: rgb(var(--B));
}

.board .badge-C circle {
  stroke: rgb(var(--C));
}

.board .handle-hit,
.board .edge-hit {
  fill: transparent;
}

.board [data-mode="n"],
.board [data-mode="s"] {
  cursor: ns-resize;
}

.board [data-mode="e"],
.board [data-mode="w"] {
  cursor: ew-resize;
}

.board [data-mode="nw"],
.board [data-mode="se"] {
  cursor: nwse-resize;
}

.board [data-mode="ne"],
.board [data-mode="sw"] {
  cursor: nesw-resize;
}

.board.locked [data-mode] {
  cursor: default;
}

/* ---------- answer ---------- */

.below {
  grid-area: below;
}

/* The two answers are tall cards, numbered for the keyboard. Once answered
   they stay where they are, marked "Your pick" and "Correct answer". */
.answers {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px;
}

.answer {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 64px;
  padding: 10px 16px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  text-align: left;
  color: var(--ink);
  background: var(--paper);
  border: 1.5px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--lift);
  cursor: pointer;
}

.answer:hover:not(:disabled) {
  border-color: var(--accent);
}

.answer:disabled {
  cursor: default;
}

.answer .key {
  flex: none;
  width: 22px;
  height: 22px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* No keyboard (a phone, or the app), no key hints. */
@media not ((hover: hover) and (pointer: fine)) {
  .answer .key {
    display: none;
  }
}

.answer small {
  display: block;
  font-size: 12px;
  font-weight: 600;
}

.answer.correct {
  background: var(--right-soft);
  border-color: var(--right-line);
}

.answer.correct small {
  color: var(--right-ink);
}

.answer.mine {
  background: var(--fixed-soft);
  border-color: var(--fixed-line);
}

.answer.mine small {
  color: var(--fixed-ink);
}

.answer.other {
  opacity: 0.55;
}

.feedback {
  margin-top: 4px;
}

.tally {
  margin: 14px 0 6px;
  font-size: 22px;
  line-height: 1.25;
}

.tally.right {
  color: var(--right-ink);
}

.tally.wrong {
  color: var(--fixed-ink);
}

.tally .points {
  margin-left: 8px;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--right-ink);
  white-space: nowrap;
}

.task,
.line {
  margin: 0 0 14px;
  font-size: 15px;
}

/* What the board still needs, kept up to date as the boxes move: muted
   while building, teal once the board shows the answer, rose after a
   submit that fell short. It shakes on each miss. */
.board-status {
  margin: 0 0 12px;
  padding: 8px 12px;
  font-size: 14px;
  color: var(--muted);
  background: var(--paper);
  border-radius: 10px;
  box-shadow: inset 0 0 0 1px var(--line);
}

/* Ready: teal on pale teal, so Submit stays the one solid button. */
.board-status.ready {
  font-weight: 600;
  color: var(--accent);
  background: color-mix(in oklab, var(--accent) 10%, transparent);
  box-shadow: none;
}

/* Submit's pulse as the board becomes ready. */
.submit.pulse {
  animation: ready-pulse 0.7s ease-out;
}

@keyframes ready-pulse {
  0% {
    box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 45%, transparent);
  }
  100% {
    box-shadow: 0 0 0 14px color-mix(in oklab, var(--accent) 0%, transparent);
  }
}

/* Below the wide layout, the status line and Submit share a row, so Submit
   is always in view right under the board. */
@media (max-width: 1099px) {
  .board-status-row {
    display: flex;
    align-items: center;
    gap: 10px;
  }

  .board-status {
    flex: 1;
    margin: 0;
  }

  .board-status-row .gk-button-primary.submit {
    display: inline-block;
    flex: none;
    width: auto;
  }
}

.board-status.missed {
  color: var(--fixed-ink);
  background: var(--fixed-soft);
  box-shadow: none;
}

.board-status.shake {
  animation: shake 0.36s ease-in-out both;
}

/* The coach: a teal card in the panel; the part it talks about stays bright
   and the rest of the round steps back. */
.coach {
  margin: 0 0 14px;
  padding: 14px 16px;
  color: var(--paper);
  background: var(--accent);
  border-radius: 14px;
  box-shadow: var(--lift);
}

/* The card's arrow, on the edge facing what it talks about: down to the
   board below it on a phone (left to the board beside the panel on a wide
   screen), up to the argument above it, down to the status line below. */
.coach {
  position: relative;
}

.coach::after {
  content: "";
  position: absolute;
  left: 28px;
  border: 10px solid transparent;
}

.coach.to-board::after,
.coach.to-status::after {
  top: 100%;
  border-top-color: var(--accent);
}

.coach.to-premises::after,
.coach.to-conclusion::after {
  bottom: 100%;
  border-bottom-color: var(--accent);
}

@media (min-width: 1100px) {
  .coach.to-board::after {
    top: 28px;
    left: auto;
    right: 100%;
    border-top-color: transparent;
    border-right-color: var(--accent);
  }
}

.coach-steps {
  display: flex;
  gap: 5px;
  margin-bottom: 8px;
}

.coach-steps span {
  width: 18px;
  height: 3px;
  border-radius: 2px;
  background: color-mix(in oklab, var(--paper) 35%, transparent);
}

.coach-steps span.on {
  background: var(--paper);
}

.coach-text {
  margin: 0 0 12px;
  font-size: 15px;
  line-height: 1.5;
}

.coach-actions {
  display: flex;
  gap: 8px;
}

.coach-actions button {
  flex: 1;
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  min-height: 40px;
  border-radius: 10px;
  cursor: pointer;
}

.coach-skip {
  color: var(--paper);
  background: transparent;
  border: 1px solid rgb(255 255 255 / 0.45);
}

.coach-next {
  color: var(--accent);
  background: var(--paper);
  border: none;
}

.coaching .board,
.coaching .given,
.coaching .proposed,
.coaching .board-status-row {
  transition: opacity 0.2s;
}

.coaching .board:not(.coach-target),
.coaching .given:not(.coach-target),
.coaching .proposed:not(.coach-target),
.coaching .board-status-row:not(.coach-target) {
  opacity: 0.3;
}

.coaching .coach-target {
  border-radius: 12px;
  box-shadow:
    0 0 0 3px var(--accent),
    var(--lift);
}

/* Inside the argument card, which clips to its corners, the ring is drawn
   inside and follows the card's corners. */
.coaching .given.coach-target,
.coaching .proposed.coach-target {
  box-shadow: inset 0 0 0 3px var(--accent);
}

.coaching .given.coach-target {
  border-radius: 16px 16px 0 0;
}

/* While building, the conclusion's label says "make it false" in teal in a
   round that doesn't have to be true. */
.group-label .aim-false {
  font-weight: 600;
  color: var(--accent);
}

/* After a miss, the way out sits at the end of the status line. */
.board-status .show-me {
  display: inline;
  padding: 0;
  margin: 0 0 0 4px;
  font: inherit;
  font-weight: 600;
  color: inherit;
  background: none;
  border: none;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

/* The feedback's reason, folded: a title that opens and closes it. */
.why-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  margin: 2px 0 10px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  background: none;
  border: none;
  cursor: pointer;
}

.why-toggle::after {
  content: "›";
  font-size: 18px;
  line-height: 1;
  transition: transform 0.15s;
}

.why-toggle.open::after {
  transform: rotate(90deg);
}

.why-toggle + .why {
  margin-top: 0;
}

.why-link {
  padding: 0;
  margin: 0 0 14px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  background: none;
  border: none;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* The explanation reads as plain prose with a teal rule down its left:
   only the quantifiers stand out, in bold. The marks stay on the argument
   above. */
.why {
  margin: 0 0 16px;
  padding: 2px 0 2px 14px;
  font-size: 15px;
  line-height: 1.6;
  border-left: 3px solid var(--accent);
}

.why .q {
  font-weight: 700;
}

/* Wide screens: the board on the left, the argument and the answer in a
   panel beside it. JS uses the same breakpoint to size the field. */
@media (min-width: 1100px) {
  .frame {
    max-width: 1300px;
  }

  .play {
    grid-template-columns: minmax(0, 1fr) 360px;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "board statement"
      "board below";
    column-gap: 22px;
    row-gap: 16px;
    align-items: start;
  }

  .play.building {
    grid-template-areas:
      "board statement"
      "board below";
  }

  /* Wide, coaching: the card in the panel, between the argument and the
     status line. */
  .play.building.coaching {
    grid-template-rows: auto auto 1fr;
    grid-template-areas:
      "board statement"
      "board coach"
      "board below";
  }

  .play > * {
    max-width: none;
  }

  .board {
    max-width: 900px;
  }
}

@media (max-width: 520px) {
  /* Room for "Round 8 of 8 · Skip round" and a four-digit score. */
  .bar {
    gap: 8px;
  }

  .bar .dot {
    margin: 0 5px;
  }

  .hero-title {
    font-size: 44px;
  }

  .cast {
    max-width: 320px;
    margin: 20px auto 24px;
  }

  .given,
  .proposed {
    padding-left: 14px;
    padding-right: 14px;
  }

  .answers {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The question, then its feedback, before the board: the argument and the
   answers (or the verdict) in one centered column, on every screen. */
.play.column {
  grid-template-columns: minmax(0, 600px);
  grid-template-rows: none;
  grid-template-areas: "statement" "below";
  justify-content: center;
  row-gap: 16px;
}

.play.column .sentence {
  font-size: 17px;
}

.play.column .conclusion {
  font-size: 21px;
}

/* On a phone the main action takes the full width. In the app, where the
   game is the whole window, the column also fills the height and its
   buttons sit at the bottom, in reach of a thumb. Never on a laptop, where
   that leaves the buttons far from the text. */
@media (max-width: 640px) {
  .gk-button-primary.wide {
    display: block;
    width: 100%;
  }

  html.gk-window .frame {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    padding-top: calc(16px + var(--gk-inset-top, 0px));
    padding-bottom: calc(16px + var(--gk-inset-bottom, 0px));
  }

  html.gk-window #game,
  html.gk-window .intro {
    display: flex;
    flex: 1;
    flex-direction: column;
    width: 100%;
  }

  html.gk-window .play.column {
    display: flex;
    flex: 1;
    flex-direction: column;
  }

  html.gk-window .intro.start .hero {
    display: flex;
    flex: 1;
    flex-direction: column;
    justify-content: center;
  }

  html.gk-window .play.column .below,
  html.gk-window .intro > .gk-button-primary {
    margin-top: auto;
  }

  html.gk-window .play.column .below {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }
}

/* Once answered, the boxes can't move, so the handles go away. */
.board.locked .handle {
  display: none;
}

/* ---------- moments ---------- */

/* A pressed answer: it dips and stays lit through the beat; the other one
   steps back. */
.answer {
  transition:
    transform 0.15s,
    opacity 0.15s,
    border-color 0.15s;
}

.answer:active {
  transform: scale(0.97);
}

.answer.picked:disabled {
  opacity: 1;
  border-color: var(--accent);
  box-shadow:
    var(--lift),
    0 0 0 4px color-mix(in oklab, var(--accent) 18%, transparent);
  animation: picked 0.42s ease-out both;
}

.answer.passed:disabled {
  opacity: 0.4;
}

@keyframes picked {
  0% {
    transform: scale(1);
  }
  30% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1.02);
  }
}

/* The reveal: the verdict pops (right) or shakes (wrong), the score bumps,
   and this round's bar pops. The board rises in when the player goes to
   it. */
.moment-board .board {
  animation: rise 0.28s ease-out both;
}

.moment-right .tally {
  transform-origin: left center;
  animation: pop 0.36s ease-out both;
}

.moment-wrong .tally,
.moment-missed .tally {
  animation: shake 0.36s ease-in-out both;
}

.moment-right .score b,
.moment-shown .score b {
  animation: bump 0.36s ease-out;
}

.moment-right .pip.this,
.moment-wrong .pip.this {
  animation: pip-pop 0.36s ease-out;
}

/* Shown: the animals in the boxes hop in a wave, then the explanation
   comes up. */
.board .animal.hop {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: hop 0.52s ease-out var(--delay, 0ms) both;
}

.moment-shown .feedback .why-link,
.moment-shown .feedback .why,
.moment-shown .feedback .line,
.moment-shown .feedback .next {
  animation: rise 0.28s ease-out 0.25s both;
}

/* Building: a prop pops in or shrinks away, its animal gives a small hop,
   and a premise's number or the conclusion's pill pops when it gets where
   the board needs it. */
.board .prop.pop {
  transform-box: fill-box;
  transform-origin: 50% 60%;
  animation: prop-pop 0.16s ease-out;
}

.board .prop.unpop {
  transform-box: fill-box;
  transform-origin: 50% 60%;
  animation: prop-out 0.1s ease-in forwards;
}

.board .animal.perk {
  transform-box: fill-box;
  animation: perk 0.18s ease-out;
}

.num.flip {
  animation: bump 0.36s ease-out;
}

@keyframes prop-pop {
  0% {
    opacity: 0.4;
    transform: scale(0.6);
  }
  70% {
    opacity: 1;
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes prop-out {
  to {
    opacity: 0;
    transform: scale(0.6);
  }
}

@keyframes perk {
  0%,
  100% {
    transform: translateY(0);
  }
  45% {
    transform: translateY(-2px);
  }
}

/* Leaving: the boxes fade, and every animal hops and runs off the right
   edge. */
.board.leaving .zones,
.board.leaving .overlay {
  transition: opacity 0.25s;
  opacity: 0;
}

.board .animal.leave {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: leave 0.6s ease-in var(--delay, 0ms) both;
}

@keyframes leave {
  0% {
    transform: translate(0, 0);
  }
  25% {
    transform: translate(4px, -16px);
  }
  45% {
    transform: translate(18px, 0);
  }
  100% {
    transform: translate(var(--exit), 0);
  }
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes pop {
  0% {
    opacity: 0;
    transform: scale(0.9);
  }
  60% {
    opacity: 1;
    transform: scale(1.05);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes shake {
  0%,
  100% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(-6px);
  }
  40% {
    transform: translateX(6px);
  }
  60% {
    transform: translateX(-3px);
  }
  80% {
    transform: translateX(3px);
  }
}

@keyframes bump {
  0%,
  100% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.4);
  }
}

@keyframes pip-pop {
  0%,
  100% {
    transform: scaleY(1);
  }
  40% {
    transform: scaleY(2.2);
  }
}

@keyframes hop {
  0%,
  100% {
    transform: translateY(0);
  }
  35% {
    transform: translateY(-14px);
  }
  60% {
    transform: translateY(0);
  }
  78% {
    transform: translateY(-4px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .answer,
  .answer.picked:disabled,
  .moment-board .board,
  .moment-right .tally,
  .moment-wrong .tally,
  .moment-missed .tally,
  .board-status.shake,
  .submit.pulse,
  .moment-right .score b,
  .moment-shown .score b,
  .moment-right .pip.this,
  .moment-wrong .pip.this,
  .board .animal.hop,
  .board .animal.leave,
  .board .prop.pop,
  .board .prop.unpop,
  .board .animal.perk,
  .num.flip,
  .moment-shown .feedback .why-link,
  .moment-shown .feedback .why,
  .moment-shown .feedback .line,
  .moment-shown .feedback .next {
    animation: none;
    transition: none;
  }
}

/* ---------- phones: a round on one screen ----------
   On a phone each step should fit a typical screen (390 by about 700)
   without scrolling: text and padding tighten, the two answers sit side by side, and while building the
   status line and Submit share a row. */
@media (max-width: 520px) {
  .frame {
    padding: 6px 12px 8px;
  }

  .bar {
    min-height: 28px;
  }

  .marks {
    margin: 4px 0 8px;
  }

  .play,
  .play.column {
    row-gap: 10px;
  }

  .kicker {
    margin-bottom: 6px;
  }

  .given {
    padding: 8px 12px 6px;
  }

  .proposed {
    padding: 8px 12px 10px;
  }

  .group-label {
    margin-bottom: 2px;
    font-size: 11px;
  }

  .premise {
    display: block;
    position: relative;
    padding: 3px 10px 3px 40px;
  }

  .premise .num {
    position: absolute;
    left: 10px;
    top: 5px;
  }

  .sentence,
  .play.column .sentence {
    display: inline;
    font-size: 15px;
    line-height: 1.38;
  }

  .conclusion,
  .play.column .conclusion {
    display: inline;
    font-size: 16px;
    line-height: 1.38;
  }

  .answers {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px;
  }

  .answer {
    min-height: 54px;
    padding: 8px 12px;
    font-size: 15px;
  }

  .tally {
    margin: 10px 0 4px;
    font-size: 19px;
  }

  .task,
  .line {
    margin-bottom: 10px;
    font-size: 14px;
  }

  .board-status-row {
    gap: 8px;
  }

  .board-status {
    padding: 6px 10px;
    font-size: 13px;
  }

  .board-status-row .submit {
    min-width: 0;
    min-height: 44px;
    padding: 10px 16px;
    font-size: 15px;
  }
}
