/*
 * The One. One stylesheet, no build step — Propshaft serves this file directly.
 *
 * Tier colours mirror the emoji in config/game.yml so the on-screen pips and the
 * pasted share grid read as the same scale: white, green, blue, purple, gold.
 */

:root {
  --parchment: #f7f3ea;
  --parchment-deep: #efe7d7;
  --ink: #23201b;
  --ink-soft: #6b6456;
  --rule: #ddd3bf;
  --gold: #c08a2e;

  --tier-none: #b9b1a1;
  --tier-common: #e4ddcc;
  --tier-uncommon: #5d9b61;
  --tier-rare: #4572a7;
  --tier-very-rare: #7c5aa6;
  --tier-the-one: var(--gold);

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;

  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --parchment: #1b1917;
    --parchment-deep: #242020;
    --ink: #f0e9dc;
    --ink-soft: #a89f8e;
    --rule: #3a342c;
    --tier-common: #4a443a;
  }
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--parchment);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

.shell {
  max-width: 34rem;
  margin: 0 auto;
  padding: 1.5rem 1rem 3rem;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- masthead ------------------------------------------------------------- */

.masthead { text-align: center; margin-bottom: 1.5rem; }

.masthead__title {
  font-family: var(--serif);
  font-size: 1.6rem;
  letter-spacing: 0.01em;
  color: var(--ink);
  text-decoration: none;
}

.masthead__one { color: var(--gold); font-style: italic; }

.masthead__meta {
  margin: 0.25rem 0 0;
  font-size: 0.8rem;
  color: var(--ink-soft);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.main { flex: 1; }

.footer {
  margin-top: 2.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-size: 0.78rem;
  color: var(--ink-soft);
  text-align: center;
}
.footer p { margin: 0; }

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

.round__prompt {
  font-family: var(--serif);
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.3;
  margin: 0 0 1.25rem;
}

/* How hard the prompt is, as a small colored box above it, in the prompt's serif. */
.round__difficulty {
  display: inline-block;
  margin: 0 0 0.6rem;
  padding: 0.15rem 0.6rem;
  border-radius: 2px;
  font-family: var(--serif);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.4;
}
.round__difficulty--easy { background: #5cbf6a; color: #10260f; }
.round__difficulty--medium { background: #f2cf4a; color: #2e2405; }
.round__difficulty--hard { background: #e0524a; color: #ffffff; }
.round__difficulty--extreme { background: #8e5bd6; color: #ffffff; }

/* Sits snug under the prompt, so the prompt gives up its bottom margin. */
.round__prompt:has(+ .round__hint) { margin-bottom: 0.35rem; }

.round__hint {
  margin: 0 0 1.25rem;
  font-size: 0.85rem;
  font-style: italic;
  color: rgba(243, 247, 240, 0.65);
}

.round__form { display: flex; gap: 0.5rem; }

.round__input {
  flex: 1;
  min-width: 0;
  padding: 0.7rem 0.85rem;
  font-size: 1rem;
  font-family: inherit;
  color: var(--ink);
  background: var(--parchment-deep);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.round__input:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}

.round__input:disabled { opacity: 0.6; }

.round__note {
  margin: 0.85rem 0 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.round__note--miss strong { color: var(--ink); }
.round__note--warn { color: #b4452f; }

.round__timeout { display: none; }

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

.button {
  display: inline-block;
  padding: 0.7rem 1.1rem;
  font: inherit;
  font-size: 0.95rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
}

.button--primary { background: var(--ink); color: var(--parchment); }
.button--primary:hover { background: var(--ink-soft); }

.button--quiet {
  background: transparent;
  color: var(--ink-soft);
  border-color: var(--rule);
  font-size: 0.85rem;
  padding: 0.5rem 0.9rem;
}
.button--quiet:hover { color: var(--ink); }

/* button_to wraps in a form; keep them inline with their neighbours */
.button_to { display: contents; }

.link { color: var(--ink-soft); }

/* --- the reveal ----------------------------------------------------------- */

/* Centred, one line each: the rarity, what the player typed, what it earned,
   and the running total. Bigger to smaller, so it reads top to bottom. */
.reveal { text-align: center; }

.reveal__tier {
  margin: 0;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(2rem, 9vw, 3.2rem);
  letter-spacing: 0.18em;
  text-indent: 0.18em;
  text-transform: uppercase;
}

.reveal__guess { margin: 0.9rem 0 0; font-size: 1.35rem; }

.reveal__earned {
  margin: 1rem 0 0;
  font-size: 1.25rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.reveal__total {
  margin: 0.6rem 0 0;
  font-size: 0.9rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.reveal--uncommon .reveal__tier { color: #8fd694; }
.reveal--rare .reveal__tier { color: #8cb8ee; }
.reveal--very_rare .reveal__tier { color: #c3a5ea; }
.reveal--the_one .reveal__tier { color: #ffd874; }

/* --- results -------------------------------------------------------------- */

.results { text-align: center; }

.results__grid {
  font-size: 1.6rem;
  letter-spacing: 0.1em;
  margin: 0 0 0.75rem;
}

.results__total {
  font-family: var(--serif);
  font-size: 2.6rem;
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.results__unit {
  display: block;
  font-family: var(--sans);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-soft);
}

.results__landmark { margin: 0.75rem 0 0; color: var(--ink-soft); font-size: 0.95rem; }
.results__streak { margin: 1rem 0 0; font-size: 0.95rem; }
.results__best { color: var(--ink-soft); font-size: 0.85rem; }

.results__rows {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  text-align: left;
  border-top: 1px solid var(--rule);
}

.results__row {
  display: flex;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--rule);
}

.results__row-text { flex: 1; min-width: 0; }

.results__row-prompt {
  display: block;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.results__row-answer { display: block; font-size: 0.95rem; }

.results__row-cubits {
  font-variant-numeric: tabular-nums;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.results__actions { margin-top: 2rem; }
.results__copied { margin: 0.6rem 0 0; font-size: 0.85rem; color: var(--ink-soft); }
.results__nav { margin-top: 1.5rem; font-size: 0.85rem; }

/* --- empty state ---------------------------------------------------------- */

.empty { text-align: center; padding: 3rem 0; }
.empty__title { font-family: var(--serif); font-size: 1.6rem; margin: 0 0 0.5rem; }
.empty__body { color: var(--ink-soft); margin: 0 0 1.5rem; }
.empty__hint { font-size: 0.85rem; color: var(--ink-soft); }

.empty__hint code {
  background: var(--parchment-deep);
  padding: 0.15rem 0.35rem;
  border-radius: 4px;
}

/* --- the pasture ---------------------------------------------------------- */
/*
 * A side-scroller fixed behind everything. It never scrolls with the page and
 * never re-renders — it is turbo-permanent — and the pasture controller moves
 * its layers with transforms as the sheep covers ground.
 *
 * --px is the pixel-art unit. Fixed in screen pixels rather than scaled to the
 * viewport, because a pixel that changes size between breakpoints stops reading
 * as pixel art.
 */

:root {
  --px: 5px;
  --horizon: 56%;
  /* The answer dock's height. The animals stand clear of it on every screen,
     not just during a round, so the sheep never hops as the dock comes and goes. */
  --dock-height: 6rem;
  --ground-line: max(15%, calc(var(--dock-height) + 1.25rem));
  /* Where the animals stand. The sheep is fixed here and the world moves; the
     shepherd starts just behind it and is left behind as the run begins. */
  --sheep-at: 25%;
  --shepherd-at: 14%;
}

@media (max-width: 40rem) {
  :root {
    --px: 4px;
    --horizon: 52%;
    --ground-line: max(13%, calc(var(--dock-height) + 1rem));
    --sheep-at: 40%;
    --shepherd-at: 14%;
  }
}

body { min-height: 100svh; }

.pasture {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: #4f8c4c;
  pointer-events: none;
}

.pasture__sky {
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--horizon);
  background: linear-gradient(to bottom, #7cc4e8 0%, #b8e0f2 60%, #dff0f7 100%);
}

.pasture__ground {
  position: absolute;
  inset: var(--horizon) 0 0 0;
  background: #4f8c4c;
}

.pasture__sun {
  position: absolute;
  top: 8%;
  right: 8%;
  width: calc(8 * var(--px));
  height: calc(8 * var(--px));
  opacity: 0.9;
}

/*
 * A scrolling layer is one tile wider than the screen, so shifting it left by
 * anything up to a whole tile never uncovers its right edge. The controller
 * takes the offset modulo the tile, so the layer is endless.
 */
.pasture__layer {
  position: absolute;
  left: 0;
  width: calc(100% + var(--tile, 0px));
  will-change: transform;
}

.pasture__layer--clouds { top: 0; height: 90px; }

/* Straddles the horizon, so the hills rise into the sky and the nearest band
   merges into the ground, which is why that band is the ground's own green. */
.pasture__layer--hills {
  top: calc(var(--horizon) - 96px);
  height: 150px;
}

.pasture__layer--tufts {
  top: calc(var(--horizon) + 2rem);
  bottom: 0;
}

/* --- the living scene ------------------------------------------------------ */
/*
 * Ambient motion that runs whether or not the sheep is moving. The camera owns
 * each layer's transform, so anything that moves on its own does it on a
 * wrapper (the cloud drift) or on elements inside a layer (the grain, the far
 * flock), never on the layer itself.
 */

/* One cloud tile (1800px) every four minutes: slow enough to notice only when
   you look up from a question. */
.pasture__drift {
  position: absolute;
  inset: 0 0 auto 0;
  height: 90px;
  animation: cloud-drift 240s linear infinite;
  will-change: transform;
}

@keyframes cloud-drift {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(-1800px, 0, 0); }
}

/* The fields stand on the middle hills, their feet tucked behind the front band. */
.pasture__layer--fields {
  top: calc(var(--horizon) - 50px);
  height: 56px;
}

.pasture__ears--leaning { opacity: 0; }
.pasture__ears--still { animation: frame-a 2.8s steps(1) infinite var(--sway-delay, 0s); }
.pasture__ears--leaning { animation: frame-b 2.8s steps(1) infinite var(--sway-delay, 0s); }

/* Mostly heads up, now and then a mouthful. */
.pasture__far-sheep--down { opacity: 0; }
.pasture__far-sheep--up { animation: graze-up var(--graze-time, 6s) steps(1) infinite var(--graze-delay, 0s); }
.pasture__far-sheep--down { animation: graze-down var(--graze-time, 6s) steps(1) infinite var(--graze-delay, 0s); }

.pasture__far-shepherd { animation: shepherd-pace 16s steps(8) infinite var(--pace-delay, 0s); }

@keyframes frame-a {
  0%, 59% { opacity: 1; }
  60%, 100% { opacity: 0; }
}

@keyframes frame-b {
  0%, 59% { opacity: 0; }
  60%, 100% { opacity: 1; }
}

@keyframes graze-up {
  0%, 54% { opacity: 1; }
  55%, 100% { opacity: 0; }
}

@keyframes graze-down {
  0%, 54% { opacity: 0; }
  55%, 100% { opacity: 1; }
}

@keyframes shepherd-pace {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(10px); }
}

/* Birds fly in the band of sky above the hills and behind them. Each bird is
   placed and timed by the birds controller through custom properties. */
.pasture__birds {
  position: absolute;
  inset: 0 0 auto 0;
  height: calc(var(--horizon) - 60px);
  overflow: hidden;
}

.pasture__bird {
  position: absolute;
  left: 0;
  top: var(--y, 20%);
  width: var(--size, 15px);
  aspect-ratio: 5 / 3;
  opacity: var(--alpha, 0.85);
  animation: bird-cross var(--duration, 14s) linear var(--delay, 0s) both;
}

.pasture__bird.is-westward { animation-direction: reverse; }

/* A gentle rise and fall on top of the crossing, so a flock doesn't fly on rails. */
.pasture__bird svg {
  display: block;
  width: 100%;
  height: 100%;
  animation: bird-glide 2.4s ease-in-out infinite alternate var(--delay, 0s);
}

.pasture__wings--down { opacity: 0; }
.pasture__wings--up { animation: frame-flap-a 0.4s steps(1) infinite; }
.pasture__wings--down { animation: frame-flap-b 0.4s steps(1) infinite; }

@keyframes bird-cross {
  from { transform: translate3d(-40px, 0, 0); }
  to { transform: translate3d(calc(100vw + 40px), 0, 0); }
}

@keyframes bird-glide {
  from { transform: translateY(-3px); }
  to { transform: translateY(3px); }
}

@keyframes frame-flap-a {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@keyframes frame-flap-b {
  0%, 49% { opacity: 0; }
  50%, 100% { opacity: 1; }
}

/* --- the flock ------------------------------------------------------------ */

.pasture__shepherd {
  position: absolute;
  left: var(--shepherd-at);
  bottom: var(--ground-line);
  width: calc(10 * var(--px));
  height: calc(16 * var(--px));
  will-change: transform;
}

.pasture__shepherd svg,
.pasture__sheep svg { display: block; width: 100%; height: 100%; }

/* The rest of the flock, milling about round the shepherd. Each layer spans
   the screen so the ewes can be placed against it; the camera owns the layer's
   transform and the flock controller owns each ewe's --wander. */
.pasture__flock {
  position: absolute;
  inset: 0;
  will-change: transform;
}

.pasture__ewe {
  position: absolute;
  left: calc(var(--sheep-at) * var(--at));
  bottom: calc(var(--ground-line) + var(--rise) * var(--px));
  width: calc(14 * var(--px));
  height: calc(11 * var(--px));
  transform: translateX(calc(var(--wander, 0) * var(--px)));
  transition: transform var(--amble, 0s) linear;
}

.pasture__ewe-sprite { display: block; width: 100%; height: 100%; overflow: visible; }
.pasture__ewe.is-facing-left .pasture__ewe-sprite { transform: scaleX(-1); }

.pasture__ewe-head--down { opacity: 0; }
.pasture__ewe[data-state="graze"] .pasture__ewe-head--up { opacity: 0; }
.pasture__ewe[data-state="graze"] .pasture__ewe-head--down {
  opacity: 1;
  animation: antic-chew 0.4s steps(1) infinite;
}

/* An amble: the same stride as the sheep's walk, a little slower. */
.pasture__ewe[data-state="walk"] { animation: ewe-bob 0.6s steps(2) infinite; }
.pasture__ewe[data-state="walk"] .pasture__legs--stride { animation: sheep-stride 0.6s steps(1) infinite; }
.pasture__ewe[data-state="walk"] .pasture__legs--gather { animation: sheep-gather 0.6s steps(1) infinite; }

/* Bobs with translate, which stacks on the transform carrying her along. */
@keyframes ewe-bob {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 calc(-0.5 * var(--px)); }
}

.pasture__sheep {
  position: absolute;
  left: var(--sheep-at);
  bottom: var(--ground-line);
  width: calc(14 * var(--px));
  height: calc(11 * var(--px));
  transform: translateX(-50%);
}

/* The two leg frames sit on top of each other; a gait animation cross-fades
   them with steps(1), which reads as a stride rather than a dissolve. */
.pasture__legs--gather { opacity: 0; }
.pasture__legs--stride { opacity: 1; }

@keyframes sheep-stride {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@keyframes sheep-gather {
  0%, 49% { opacity: 0; }
  50%, 100% { opacity: 1; }
}

@keyframes sheep-bob {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(calc(-0.5 * var(--px))); }
}

@keyframes sheep-leap {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  35% { transform: translateX(-50%) translateY(calc(-3.5 * var(--px))); }
  70% { transform: translateX(-50%) translateY(calc(-1 * var(--px))); }
}

@keyframes sheep-graze {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(calc(0.25 * var(--px))); }
}

/* Each gait is a leg cadence plus a body motion. Faster cadence reads as a
   faster animal more than the travel time does. */
.pasture__sheep.is-grazing { animation: sheep-graze 2.6s ease-in-out infinite; }

.pasture__sheep.is-walking { animation: sheep-bob 0.5s steps(2) infinite; }
.pasture__sheep.is-walking .pasture__legs--stride { animation: sheep-stride 0.5s steps(1) infinite; }
.pasture__sheep.is-walking .pasture__legs--gather { animation: sheep-gather 0.5s steps(1) infinite; }

.pasture__sheep.is-trotting { animation: sheep-bob 0.3s steps(2) infinite; }
.pasture__sheep.is-trotting .pasture__legs--stride { animation: sheep-stride 0.3s steps(1) infinite; }
.pasture__sheep.is-trotting .pasture__legs--gather { animation: sheep-gather 0.3s steps(1) infinite; }

.pasture__sheep.is-running { animation: sheep-bob 0.18s steps(2) infinite; }
.pasture__sheep.is-running .pasture__legs--stride { animation: sheep-stride 0.18s steps(1) infinite; }
.pasture__sheep.is-running .pasture__legs--gather { animation: sheep-gather 0.18s steps(1) infinite; }

.pasture__sheep.is-leaping { animation: sheep-leap 0.62s ease-in-out infinite; }
.pasture__sheep.is-leaping .pasture__legs--stride { animation: sheep-stride 0.16s steps(1) infinite; }
.pasture__sheep.is-leaping .pasture__legs--gather { animation: sheep-gather 0.16s steps(1) infinite; }

/* --- shadow and the grass underfoot --------------------------------------- */
/*
 * Both sit outside the sheep, so the gait's bob and leap don't carry them off
 * the ground, and both read the gait from the sheep's classes with :has().
 * --stride is the leg cadence of the current gait, the same numbers the leg
 * animations above use, so the grass is pushed about in step with the hooves.
 */
.pasture:has(.pasture__sheep.is-walking) { --stride: 0.5s; }
.pasture:has(.pasture__sheep.is-trotting) { --stride: 0.3s; }
.pasture:has(.pasture__sheep.is-running) { --stride: 0.18s; }
.pasture:has(.pasture__sheep.is-leaping) { --stride: 0.16s; }

/* Centred under the body rather than the whole sprite (the head sticks out in
   front), and nudged back a touch, away from the sun. */
.pasture__shadow {
  position: absolute;
  left: var(--sheep-at);
  bottom: calc(var(--ground-line) - 1.5 * var(--px));
  width: calc(16 * var(--px));
  height: calc(3 * var(--px));
  transform: translateX(calc(-50% - 1.5 * var(--px)));
  opacity: 0.4;
}

.pasture__shadow svg {
  display: block;
  width: 100%;
  height: 100%;
  transform-origin: 50% 50%;
}

/* In the air the shadow shrinks and fades, and grows back as the sheep comes
   down, on the same beat as the leap and the pronk. */
.pasture:has(.pasture__sheep.is-leaping) .pasture__shadow svg {
  animation: shadow-leap 0.62s ease-in-out infinite;
}
.pasture:has(.pasture__sheep:is([data-antic="pronk"], [data-antic="hop"])) .pasture__shadow svg {
  animation: shadow-pronk 1.6s ease-in-out forwards;
}

@keyframes shadow-leap {
  0%, 100% { transform: scaleX(1); opacity: 1; }
  35% { transform: scaleX(0.6); opacity: 0.45; }
  70% { transform: scaleX(0.9); opacity: 0.85; }
}

@keyframes shadow-pronk {
  0%, 10%, 45%, 55%, 90%, 100% { transform: scaleX(1); opacity: 1; }
  27% { transform: scaleX(0.55); opacity: 0.4; }
  72% { transform: scaleX(0.65); opacity: 0.5; }
}

/* Laid over the hooves and centred on the sheep. Its bottom row sits just
   under the ground line so the bases of the blades are in the field. */
.pasture__ruffle {
  position: absolute;
  left: var(--sheep-at);
  bottom: calc(var(--ground-line) - var(--px));
  width: calc(20 * var(--px));
  height: calc(3 * var(--px));
  transform: translateX(-50%);
}

.pasture__ruffle svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.pasture__blades--back,
.pasture__blades--fore,
.pasture__kick { opacity: 0; }

/* On the move, the standing frame gives way to the two flattened ones, which
   swap on every stride. Inside the svg, 1px is one pixel of the sprite. */
.pasture:has(.pasture__sheep:is(.is-walking, .is-trotting, .is-running, .is-leaping)) .pasture__blades--still { opacity: 0; }
.pasture:has(.pasture__sheep:is(.is-walking, .is-trotting, .is-running, .is-leaping)) .pasture__blades--back { animation: sheep-stride var(--stride) steps(1) infinite; }
.pasture:has(.pasture__sheep:is(.is-walking, .is-trotting, .is-running, .is-leaping)) .pasture__blades--fore { animation: sheep-gather var(--stride) steps(1) infinite; }
.pasture:has(.pasture__sheep:is(.is-walking, .is-trotting, .is-running, .is-leaping)) .pasture__kick { opacity: 1; }

.pasture__kick-bit {
  opacity: 0;
  animation: grass-kick calc(var(--stride, 0.5s) * 2) steps(1) infinite paused;
}
.pasture__kick-bit:nth-child(2) { animation-delay: calc(var(--stride, 0.5s) * -0.5); }
.pasture__kick-bit:nth-child(3) { animation-delay: calc(var(--stride, 0.5s) * -1); }
.pasture__kick-bit:nth-child(4) { animation-delay: calc(var(--stride, 0.5s) * -1.5); }

.pasture:has(.pasture__sheep:is(.is-walking, .is-trotting, .is-running, .is-leaping)) .pasture__kick-bit {
  animation-play-state: running;
}

/* Flicked up and back off a hoof, then dropped behind the sheep. Backwards,
   because the field is running past it from right to left. */
@keyframes grass-kick {
  0%, 24% { transform: translate(0, 0); opacity: 1; }
  25%, 49% { transform: translate(-1px, -2px); opacity: 1; }
  50%, 74% { transform: translate(-3px, -3px); opacity: 1; }
  75%, 99% { transform: translate(-4px, -1px); opacity: 0.6; }
  100% { transform: translate(-5px, 0); opacity: 0; }
}

/* --- antics: what the sheep gets up to while the player thinks ------------ */
/*
 * The pasture controller sets data-antic on the sheep for a few seconds at a
 * time during a question. The gait animation keeps running on the outer box
 * (it owns the translateX that centres the sheep), so antics move the svg
 * inside it, or the parts drawn in the svg. Inside the svg, 1px is one pixel
 * of the sprite; on the svg itself it is a screen pixel, so those use --px.
 */
.pasture__sheep svg {
  overflow: visible;
  transform-origin: 50% 50%;
}

.pasture__antic { display: none; }
.pasture__sheep[data-antic] svg,
.pasture__sheep[data-antic] svg g { transform-box: fill-box; }

/* Graze: head down, and the tuft in front of it goes in three bites. */
.pasture__sheep[data-antic="graze"] .pasture__body--up { display: none; }
.pasture__sheep[data-antic="graze"] .pasture__body--down,
.pasture__sheep[data-antic="graze"] .pasture__tuft { display: inline; }
.pasture__sheep[data-antic="graze"] .pasture__tuft {
  transform-origin: 50% 100%;
  animation: antic-tuft 3.2s steps(1) forwards;
}
.pasture__sheep[data-antic="graze"] .pasture__body--down {
  animation: antic-chew 0.4s steps(1) infinite;
}

@keyframes antic-tuft {
  0%, 30% { transform: scaleY(1); }
  31%, 55% { transform: scaleY(0.67); }
  56%, 80% { transform: scaleY(0.34); }
  81%, 100% { transform: scaleY(0); }
}

@keyframes antic-chew {
  0%, 49% { transform: translateY(0); }
  50%, 100% { transform: translateY(0.25px); }
}

/* Glance back at the shepherd, then carry on. */
.pasture__sheep[data-antic="glance"] svg { animation: antic-glance 2.4s steps(1) forwards; }

@keyframes antic-glance {
  0%, 15% { transform: scaleX(1); }
  16%, 80% { transform: scaleX(-1); }
  81%, 100% { transform: scaleX(1); }
}

/* Baa: a bubble pops up over the head, and the head gives a little toss. */
.pasture__sheep[data-antic="bleat"] .pasture__bubble {
  display: inline;
  animation: antic-bubble 2s steps(1) forwards;
}
.pasture__sheep[data-antic="bleat"] svg { animation: antic-toss 2s steps(1) forwards; }

@keyframes antic-bubble {
  0%, 9% { opacity: 0; }
  10%, 85% { opacity: 1; }
  86%, 100% { opacity: 0; }
}

@keyframes antic-toss {
  0%, 9% { transform: translateY(0); }
  10%, 19% { transform: translateY(calc(-0.5 * var(--px))); }
  20%, 100% { transform: translateY(0); }
}

/* A wool shake, nose to tail, like coming out of the rain. */
.pasture__sheep[data-antic="shake"] svg { animation: antic-shake 1.2s steps(1) forwards; }

@keyframes antic-shake {
  0%, 100% { transform: translateX(0); }
  10%, 30%, 50%, 70% { transform: translateX(calc(-0.5 * var(--px))) rotate(-3deg); }
  20%, 40%, 60%, 80% { transform: translateX(calc(0.5 * var(--px))) rotate(3deg); }
  90% { transform: translateX(0); }
}

/* Pronk: two springy hops straight up, legs tucked, the way lambs do. */
.pasture__sheep:is([data-antic="pronk"], [data-antic="hop"]) svg { animation: antic-pronk 1.6s ease-in-out forwards; }
.pasture__sheep:is([data-antic="pronk"], [data-antic="hop"]) .pasture__legs--stride { animation: antic-legs-tuck-a 1.6s steps(1) forwards; }
.pasture__sheep:is([data-antic="pronk"], [data-antic="hop"]) .pasture__legs--gather { animation: antic-legs-tuck-b 1.6s steps(1) forwards; }

@keyframes antic-pronk {
  0%, 10%, 45%, 55%, 90%, 100% { transform: translateY(0); }
  27% { transform: translateY(calc(-4 * var(--px))); }
  72% { transform: translateY(calc(-3 * var(--px))); }
}

@keyframes antic-legs-tuck-a {
  0%, 11%, 44%, 56%, 89%, 100% { opacity: 1; }
  12%, 43%, 57%, 88% { opacity: 0; }
}

@keyframes antic-legs-tuck-b {
  0%, 11%, 44%, 56%, 89%, 100% { opacity: 0; }
  12%, 43%, 57%, 88% { opacity: 1; }
}

/* Roll: over onto its back, a good wriggle with the legs kicking at the sky,
   and on round the rest of the way back to its feet. Stepped so it turns like
   a sprite, not a vector. */
.pasture__sheep[data-antic="roll"] svg { animation: antic-roll 3.6s steps(1) forwards; }
.pasture__sheep[data-antic="roll"] .pasture__legs--stride { animation: sheep-stride 0.24s steps(1) infinite; }
.pasture__sheep[data-antic="roll"] .pasture__legs--gather { animation: sheep-gather 0.24s steps(1) infinite; }

@keyframes antic-roll {
  0%, 7% { transform: rotate(0deg); }
  8%, 13% { transform: translateY(calc(-0.5 * var(--px))) rotate(-45deg); }
  14%, 19% { transform: translateY(calc(-1 * var(--px))) rotate(-90deg); }
  20%, 25% { transform: translateY(calc(-0.5 * var(--px))) rotate(-135deg); }
  26%, 35% { transform: rotate(-180deg); }
  36%, 43% { transform: rotate(-172deg); }
  44%, 51% { transform: rotate(-188deg); }
  52%, 59% { transform: rotate(-172deg); }
  60%, 69% { transform: rotate(-180deg); }
  70%, 75% { transform: translateY(calc(-0.5 * var(--px))) rotate(-225deg); }
  76%, 81% { transform: translateY(calc(-1 * var(--px))) rotate(-270deg); }
  82%, 87% { transform: translateY(calc(-0.5 * var(--px))) rotate(-315deg); }
  88%, 100% { transform: rotate(-360deg); }
}

/* Nap: lies down, legs folded away, eyes shut, z's drifting up. */
.pasture__sheep[data-antic="nap"] .pasture__legs { visibility: hidden; }
.pasture__sheep[data-antic="nap"] .pasture__body--up { transform: translateY(3px); }
.pasture__sheep[data-antic="nap"] .pasture__eyelid,
.pasture__sheep[data-antic="nap"] .pasture__zzz { display: inline; }
.pasture__sheep[data-antic="nap"] .pasture__zzz { transform: translateY(3px); }
.pasture__sheep[data-antic="nap"] .pasture__z { opacity: 0; animation: antic-z 2s steps(4) infinite; }
.pasture__sheep[data-antic="nap"] .pasture__z--2 { animation-delay: 1s; }

@keyframes antic-z {
  0% { opacity: 0; transform: translate(0, 0); }
  25% { opacity: 1; }
  100% { opacity: 0; transform: translate(1px, -3px); }
}

/* --- pokes: what the sun and the sheep do when they're clicked ------------- */
/*
 * The pasture lets clicks fall through it everywhere except these, and the
 * stage above it lets them through everywhere except its cards, so the scene
 * can be clicked anywhere a card isn't. touch-action keeps a tap a tap on a
 * phone, with no double-tap zoom in the way.
 */
.stage { pointer-events: none; }
.stage > * { pointer-events: auto; }

.pasture__sun,
.pasture__sheep,
.pasture__ewe {
  pointer-events: auto;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* The sun dances: a hop and a sway from side to side, with a grin and its
   rays flashing on and off. Stepped, like everything else up there. */
.pasture__sun { overflow: visible; transform-origin: 50% 50%; }
.pasture__sun-face,
.pasture__sun-rays { display: none; }
.pasture__sun[data-dancing] { animation: sun-dance 2s steps(1) forwards; }
.pasture__sun[data-dancing] .pasture__sun-face { display: inline; }
.pasture__sun[data-dancing] .pasture__sun-rays { display: inline; animation: sun-rays 0.5s steps(1) infinite; }

@keyframes sun-dance {
  0%, 100% { transform: none; }
  8% { transform: translateY(calc(-1 * var(--px))) rotate(-15deg); }
  16% { transform: rotate(0deg); }
  24% { transform: translateY(calc(-1 * var(--px))) rotate(15deg); }
  32% { transform: rotate(0deg); }
  40% { transform: translateX(calc(-1 * var(--px))) rotate(-15deg); }
  48% { transform: translateX(calc(1 * var(--px))) rotate(15deg); }
  56% { transform: translateX(calc(-1 * var(--px))) rotate(-15deg); }
  64% { transform: translateX(calc(1 * var(--px))) rotate(15deg); }
  72% { transform: translateY(calc(-2 * var(--px))); }
  80% { transform: translateY(calc(-2 * var(--px))) rotate(45deg); }
  88% { transform: translateY(calc(-1 * var(--px))) rotate(90deg); }
  96% { transform: none; }
}

@keyframes sun-rays {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* Belly up: over onto its back with its legs kicking at the sky, a wriggle
   while it waits for a rub, and back up onto its feet. Hop is the pronk. */
.pasture__sheep[data-antic="belly"] svg { animation: antic-belly 3.4s steps(1) forwards; }
.pasture__sheep[data-antic="belly"] .pasture__legs--stride { animation: sheep-stride 0.3s steps(1) infinite; }
.pasture__sheep[data-antic="belly"] .pasture__legs--gather { animation: sheep-gather 0.3s steps(1) infinite; }

@keyframes antic-belly {
  0%, 5% { transform: rotate(0deg); }
  6%, 11% { transform: translateY(calc(-0.5 * var(--px))) rotate(-90deg); }
  12%, 24% { transform: rotate(-180deg); }
  25%, 34% { transform: rotate(-172deg); }
  35%, 44% { transform: rotate(-188deg); }
  45%, 54% { transform: rotate(-172deg); }
  55%, 64% { transform: rotate(-188deg); }
  65%, 82% { transform: rotate(-180deg); }
  83%, 90% { transform: translateY(calc(-0.5 * var(--px))) rotate(-90deg); }
  91%, 100% { transform: rotate(0deg); }
}

/* The flock pokes. The ewe's own transform carries her wander and her sprite's
   carries which way she faces, so these use translate and rotate, which stack
   on top of both. */
.pasture__ewe[data-poke="hop"] .pasture__ewe-sprite { animation: ewe-hop 1.6s ease-in-out forwards; }
.pasture__ewe[data-poke="hop"] .pasture__legs--stride { animation: antic-legs-tuck-a 1.6s steps(1) forwards; }
.pasture__ewe[data-poke="hop"] .pasture__legs--gather { animation: antic-legs-tuck-b 1.6s steps(1) forwards; }

.pasture__ewe[data-poke="belly"] .pasture__ewe-sprite { transform-origin: 50% 50%; animation: ewe-belly 3.4s steps(1) forwards; }
.pasture__ewe[data-poke="belly"] .pasture__legs--stride { animation: sheep-stride 0.3s steps(1) infinite; }
.pasture__ewe[data-poke="belly"] .pasture__legs--gather { animation: sheep-gather 0.3s steps(1) infinite; }

@keyframes ewe-hop {
  0%, 10%, 45%, 55%, 90%, 100% { translate: 0 0; }
  27% { translate: 0 calc(-4 * var(--px)); }
  72% { translate: 0 calc(-3 * var(--px)); }
}

@keyframes ewe-belly {
  0%, 5% { rotate: 0deg; translate: 0 0; }
  6%, 11% { rotate: -90deg; translate: 0 calc(-0.5 * var(--px)); }
  12%, 24% { rotate: -180deg; translate: 0 0; }
  25%, 34% { rotate: -172deg; }
  35%, 44% { rotate: -188deg; }
  45%, 54% { rotate: -172deg; }
  55%, 64% { rotate: -188deg; }
  65%, 82% { rotate: -180deg; translate: 0 0; }
  83%, 90% { rotate: -90deg; translate: 0 calc(-0.5 * var(--px)); }
  91%, 100% { rotate: 0deg; translate: 0 0; }
}

/* A heart floats up off whichever sheep was poked: once for a hop, twice
   while one lies there waiting for its belly rub. */
.pasture__heart {
  position: absolute;
  width: calc(3 * var(--px));
  height: calc(3 * var(--px));
  opacity: 0;
  pointer-events: none;
}
.pasture__heart svg { display: block; width: 100%; height: 100%; }

.pasture > .pasture__heart {
  left: calc(var(--sheep-at) + 2 * var(--px));
  bottom: calc(var(--ground-line) + 11 * var(--px));
}
.pasture__ewe .pasture__heart {
  left: calc(50% - 1.5 * var(--px));
  bottom: 100%;
}

.pasture:has(.pasture__sheep[data-antic="hop"]) > .pasture__heart,
.pasture__ewe[data-poke="hop"] .pasture__heart { animation: heart-float 1.6s steps(8) forwards; }
.pasture:has(.pasture__sheep[data-antic="belly"]) > .pasture__heart,
.pasture__ewe[data-poke="belly"] .pasture__heart { animation: heart-float 1.7s steps(8) 2; }

@keyframes heart-float {
  0% { opacity: 0; transform: translateY(0); }
  15% { opacity: 1; }
  75% { opacity: 1; }
  100% { opacity: 0; transform: translateY(calc(-3 * var(--px))); }
}

@keyframes heart-still {
  0%, 10% { opacity: 0; }
  11%, 85% { opacity: 1; }
  86%, 100% { opacity: 0; }
}

/* Scanlines. Decorative only. */
.pasture__scanlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(to bottom, rgba(0,0,0,0.10) 0 1px, transparent 1px 3px);
  mix-blend-mode: multiply;
  opacity: 0.5;
}

@media (prefers-contrast: more) { .pasture__scanlines { display: none; } }

/* Reduced motion: the camera jumps to the new distance instead of scrolling
   (handled in the controller), and the bobbing, the leap and the leg cycle stop. */
/* --- the rescue: the shepherd brings the lost sheep home ------------------ */
/*
 * Played once, on the way to the results. The pasture controller steps
 * data-rescue on the scene through run (out to the sheep), lift (a beat at her
 * side), carry (walking her home on his shoulders, the camera rolling back,
 * behind the results by now) and return (back at his staff, her set down and
 * trotting to her place by --sheep-dx), and places him through
 * --rescuer-x. The legs reuse the sheep's two-frame stride at --rescue-stride.
 */
.pasture__rescuer {
  display: none;
  position: absolute;
  left: 0;
  bottom: var(--ground-line);
  width: calc(15 * var(--px));
  height: calc(16 * var(--px));
  transform: translate3d(var(--rescuer-x, 0px), 0, 0);
  will-change: transform;
}

.pasture:is([data-rescue="run"], [data-rescue="lift"], [data-rescue="carry"]) .pasture__rescuer { display: block; }
.pasture:is([data-rescue="run"], [data-rescue="lift"], [data-rescue="carry"]) .pasture__shepherd-body { visibility: hidden; }

/* Set down by his staff, she makes her own way back to her place. */
.pasture[data-rescue="return"] > :is(.pasture__sheep, .pasture__shadow, .pasture__ruffle, .pasture__heart) {
  translate: var(--sheep-dx, 0px) 0;
}

.pasture__rescuer svg { display: block; width: 100%; height: 100%; overflow: visible; }
.pasture[data-rescue="carry"] .pasture__rescuer svg { transform: scaleX(-1); }

.pasture__rescuer-carry { display: none; }
.pasture[data-rescue="carry"] .pasture__rescuer-run { display: none; }
.pasture[data-rescue="carry"] .pasture__rescuer-carry { display: inline; }

/* Up on his shoulders, she isn't on the grass any more. */
.pasture[data-rescue="carry"] :is(.pasture__sheep, .pasture__shadow) { visibility: hidden; }

.pasture:is([data-rescue="run"], [data-rescue="carry"]) .pasture__rescuer svg {
  animation: rescuer-bob var(--rescue-stride, 0.3s) steps(2) infinite;
}
.pasture:is([data-rescue="run"], [data-rescue="carry"]) .pasture__rescuer .pasture__legs--stride {
  animation: sheep-stride var(--rescue-stride, 0.3s) steps(1) infinite;
}
.pasture:is([data-rescue="run"], [data-rescue="carry"]) .pasture__rescuer .pasture__legs--gather {
  animation: sheep-gather var(--rescue-stride, 0.3s) steps(1) infinite;
}

/* translate, so the bob stacks on the flip. */
@keyframes rescuer-bob {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 calc(-0.5 * var(--px)); }
}

/* A heart as he lifts her up. */
.pasture__rescuer .pasture__heart {
  left: calc(6 * var(--px));
  bottom: calc(100% + 0.5 * var(--px));
}
.pasture[data-rescue="carry"] .pasture__rescuer .pasture__heart { animation: heart-float 1.6s steps(8) forwards; }

/* The reveal card steps aside so the rescue can be watched; the dock stays,
   its button now the way to skip it. */
.play-screen.is-rescuing .card {
  animation: card-leave 260ms ease-in both;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .pasture__sheep,
  .pasture__sheep .pasture__legs { animation: none !important; }
  .pasture__legs--gather { opacity: 0; }

  /* No antics either; the controller never starts them, and this is the
     backstop if the setting changes mid-question. */
  .pasture__sheep svg,
  .pasture__sheep svg g { animation: none !important; transform: none !important; }
  .pasture__sheep .pasture__antic { display: none !important; }
  .pasture__sheep .pasture__body--up { display: inline !important; }
  .pasture__sheep .pasture__legs { visibility: visible !important; }

  /* The scene holds still: no drift, no sway, no grazing. The birds controller
     doesn't release any birds either. */
  .pasture__drift,
  .pasture__ears > g,
  .pasture__far-sheep > g,
  .pasture__far-shepherd { animation: none !important; }
  .pasture__ears--leaning,
  .pasture__far-sheep--down { opacity: 0; }

  /* The flock stays as drawn: no wandering, no chewing, no stride. */
  .pasture__ewe,
  .pasture__ewe g,
  .pasture__ewe-sprite { animation: none !important; transition: none !important; }

  /* A poke still gets an answer, just not a moving one: the sun puts on its
     grin and rays, and a heart shows over the sheep for a moment. */
  .pasture__sun { animation: none !important; }
  .pasture__sun-rays { animation: none !important; }
  .pasture__heart { animation-name: heart-still !important; }

  /* The shadow stays put and the grass stands still, whatever the gait. */
  .pasture__shadow svg,
  .pasture__blades,
  .pasture__kick-bit { animation: none !important; transform: none !important; }
  .pasture__blades--still { opacity: 1 !important; }
  .pasture__blades--back,
  .pasture__blades--fore,
  .pasture__kick { opacity: 0 !important; }
}

/* --- the stage: cards that sit on the pasture ----------------------------- */

.stage {
  position: relative;
  z-index: 1;
  display: block;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1rem;
  /* Clear of the ground line, so a card never covers the sheep. */
  padding-bottom: calc(var(--ground-line) + 10rem);
}

.card {
  width: 100%;
  max-width: 32rem;
  text-align: center;
  animation: card-enter 320ms ease-out both;
}

.card--title { max-width: 36rem; }

@keyframes card-enter {
  from { opacity: 0; transform: translateY(0.75rem); }
  to { opacity: 1; transform: none; }
}

/* Pressing Start fades the title out while the pasture stays put. */
.card.is-leaving {
  animation: card-leave 260ms ease-in both;
  pointer-events: none;
}

@keyframes card-leave {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateY(-0.5rem); }
}

@media (prefers-reduced-motion: reduce) {
  .card, .card.is-leaving { animation: none; }
  .card.is-leaving { opacity: 0; }
}

/* Anything a player has to read sits on its own plate: the pasture behind it
   is light sky in one place and dark grass in another, so the text cannot rely
   on the background for contrast. */
.card--round,
.card--reveal,
.card--results,
.card--credits,
.card--empty {
  padding: 1.5rem 1.4rem 1.75rem;
  text-align: left;
  background: rgba(22, 38, 26, 0.86);
  border: 2px solid rgba(247, 243, 234, 0.22);
  box-shadow: 0 8px 0 rgba(16, 30, 20, 0.35);
  color: #f3f7f0;
  backdrop-filter: blur(2px);
}

.card--results { text-align: center; }

.card--round .round__prompt,
.card--reveal .reveal__guess,
.card--empty .empty__title { color: #ffffff; }

.dock .round__input {
  background: rgba(10, 20, 12, 0.5);
  border-color: rgba(247, 243, 234, 0.3);
  color: #f7f3ea;
}

.dock .round__input::placeholder { color: rgba(243, 247, 240, 0.45); }

.dock .button--primary,
.card--results .button--primary {
  background: #f7f3ea;
  color: #1d3322;
}

.card--round .button--quiet {
  color: rgba(243, 247, 240, 0.75);
  border-color: rgba(247, 243, 234, 0.3);
}

.card--reveal .reveal__total,
.card--results .results__landmark { color: rgba(243, 247, 240, 0.8); }

.card--results .results__rows { border-color: rgba(247, 243, 234, 0.2); }
.card--results .results__row { border-color: rgba(247, 243, 234, 0.14); }
.card--results .results__row-prompt,
.card--results .results__row-cubits,
.card--results .results__unit,
.card--results .results__best { color: rgba(243, 247, 240, 0.7); }

.card--empty .empty__body,
.card--empty .empty__hint { color: rgba(243, 247, 240, 0.78); }
.card--empty .empty__hint code { background: rgba(10, 20, 12, 0.5); }

/* --- title card ----------------------------------------------------------- */

.card__wordmark-wrap { margin: 0; }

.wordmark {
  display: block;
  width: min(78vw, 32rem);
  margin: 0 auto;
  height: auto;
  /* CRT misregistration in screen pixels, so it stays a fringe at every size,
     plus a hard drop shadow — never a blur, which would soften pixel edges. */
  filter:
    drop-shadow(-2px 0 0 #ff5d73)
    drop-shadow(2px 0 0 #4fd8e8)
    drop-shadow(0 4px 0 rgba(20, 40, 25, 0.45));
}

.card__tagline {
  margin: 0.9rem 0 0;
  font-size: clamp(0.75rem, 2.6vw, 1rem);
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  text-transform: uppercase;
  color: #eaf7ef;
  text-shadow: 0 2px 0 rgba(20, 40, 25, 0.5);
}

.card__rules {
  margin: 0.5rem auto 0;
  max-width: 26rem;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(0.68rem, 2.1vw, 0.85rem);
  letter-spacing: 0.08em;
  line-height: 1.7;
  color: #eef8f2;
  text-shadow: 0 1px 0 rgba(20, 40, 25, 0.7);
}

.card__rules span { white-space: nowrap; }

.start-button {
  margin-top: 1.8rem;
  display: inline-block;
  min-width: min(74vw, 22rem);
  padding: 1rem 2.5rem;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(1rem, 3.4vw, 1.4rem);
  font-weight: 700;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
  text-decoration: none;
  color: #f7f3ea;
  background: #26402c;
  /* Blocky and offset — a rounded corner would be the one non-pixel edge. */
  border: 3px solid #f7f3ea;
  border-radius: 0;
  box-shadow: 0 5px 0 rgba(20, 40, 25, 0.55);
  cursor: pointer;
  transition: transform 90ms steps(2), box-shadow 90ms steps(2), background-color 90ms;
}

.start-button:hover { background: #32543a; }

.start-button:active {
  transform: translateY(4px);
  box-shadow: 0 1px 0 rgba(20, 40, 25, 0.55);
}

.start-button:focus-visible { outline: 3px solid #ffe08a; outline-offset: 3px; }

.card__meta {
  margin: 1.6rem 0 0;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.26em;
  text-indent: 0.26em;
  text-transform: uppercase;
  color: #f3faf5;
}

@media (prefers-reduced-motion: reduce) { .start-button { transition: none; } }

/* Sits over sky on a short screen and hillside on a tall one, so it carries its
   own plate rather than trusting whatever is behind it. Block, not inline-block:
   the Start button above it is an inline-block, and two of those share a line. */
.card__meta {
  display: block;
  width: fit-content;
  margin-inline: auto;
  padding: 0.3rem 0.75rem;
  background: rgba(20, 40, 25, 0.45);
}

/* --- round and reveal on the pasture: a card, and a dock below ---------- */

/* During a round the card rides at the top of the screen instead of the
   middle, leaving the sky and the sheep in view between question and answer.
   The reveal stays centred. */
.stage:has(.round) {
  align-items: flex-start;
  padding-bottom: calc(var(--dock-height) + 2rem);
}

.play-screen { width: 100%; max-width: 32rem; }

.dock {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 2;
  min-height: var(--dock-height);
  display: flex;
  align-items: center;
  padding: 0.9rem 1rem calc(0.9rem + env(safe-area-inset-bottom));
  background: rgba(16, 30, 20, 0.92);
  border-top: 2px solid rgba(247, 243, 234, 0.22);
  color: #f3f7f0;
}

.dock__inner {
  width: 100%;
  max-width: 40rem;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.round__answer { flex: 1; min-width: 0; }

/* Between prompts the dock holds one wide button where the answer bar was. */
.dock__button { flex: 1; padding-block: 0.85rem; }

/* A ring that empties clockwise, with the seconds in the middle. */
.round__clock {
  flex: none;
  width: 3.4rem;
  height: 3.4rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background:
    radial-gradient(closest-side, rgb(16, 30, 20) 78%, transparent 80%),
    conic-gradient(#f7f3ea var(--remaining, 100%), rgba(247, 243, 234, 0.18) 0);
}

.round__clock-count {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 1.05rem;
  color: #f7f3ea;
}

.round__clock-bar {
  margin-top: 0.5rem;
  height: 0.3rem;
  border-radius: 999px;
  background: rgba(247, 243, 234, 0.18);
  position: relative;
  overflow: hidden;
}

.round__clock-bar::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--draining, 100%);
  background: #f7f3ea;
  transition: width 1s linear, background-color 0.3s ease;
}

.round.is-urgent .round__clock-bar::after { background: #e0664c; }
.round.is-urgent .round__clock {
  background:
    radial-gradient(closest-side, rgb(16, 30, 20) 78%, transparent 80%),
    conic-gradient(#e0664c var(--remaining, 100%), rgba(247, 243, 234, 0.18) 0);
}
.round.is-urgent .round__clock-count { color: #ffb4a3; }

@media (prefers-reduced-motion: reduce) {
  .round__clock-bar::after { width: var(--remaining, 100%); transition: none; }
}

/* --- results: flock curve, field log, rubric, logbook ----------------------- */

/* Brighter cousins of the tier colours, for marks drawn on the dark plate. */
.card--results {
  max-width: 36rem;
  --plate-none: #b9b1a1;
  --plate-common: #f3eedf;
  --plate-uncommon: #8fd18f;
  --plate-rare: #86b6ee;
  --plate-very-rare: #bfa2ea;
  --plate-the-one: #f2c55c;
  --plate-soft: rgba(243, 247, 240, 0.7);
  --plate-faint: rgba(243, 247, 240, 0.25);
}

.card--results .tier--none { --tier-mark: var(--plate-none); }
.card--results .tier--common { --tier-mark: var(--plate-common); }
.card--results .tier--uncommon { --tier-mark: var(--plate-uncommon); }
.card--results .tier--rare { --tier-mark: var(--plate-rare); }
.card--results .tier--very_rare { --tier-mark: var(--plate-very-rare); }
.card--results .tier--the_one { --tier-mark: var(--plate-the-one); }

.results__section { margin-top: 2rem; text-align: left; }

.results__heading {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0 0 0.75rem;
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #f3f7f0;
}

.results__heading span { color: var(--plate-soft); font-weight: 400; }

.results__heading::after {
  content: "";
  flex: 1;
  border-top: 1px dashed var(--plate-faint);
  transform: translateY(-0.2em);
}

.flock__chart,
.field__chart { display: block; width: 100%; height: auto; overflow: visible; }

.flock__area { fill: rgba(143, 209, 143, 0.18); }
.flock__line { fill: none; stroke: var(--plate-uncommon); stroke-width: 2; stroke-linejoin: round; }
.flock__axis { stroke: var(--plate-faint); }
.flock__tick { fill: var(--plate-soft); font-size: 9px; font-variant-numeric: tabular-nums; }
.flock__you-stem { stroke: var(--plate-the-one); stroke-width: 2; }
.flock__you-dot { fill: var(--plate-the-one); }
.flock__you-label { fill: var(--plate-the-one); font-size: 9px; font-weight: 700; letter-spacing: 0.12em; }

.flock__verdict { margin: 0.6rem 0 0; font-size: 0.95rem; }
.flock__verdict strong { color: var(--plate-the-one); }
.flock__verdict span { color: var(--plate-soft); font-size: 0.85rem; }

.field__guide { stroke: var(--plate-faint); stroke-dasharray: 3 4; }
.field__guide-label { fill: var(--plate-soft); font-size: 8px; font-variant-numeric: tabular-nums; }
.field__ground { stroke: rgba(143, 209, 143, 0.6); stroke-width: 2; }
.field__stem { stroke: var(--tier-mark); stroke-width: 2; opacity: 0.7; }
.field__pip { fill: var(--tier-mark); stroke: rgba(16, 30, 20, 0.8); stroke-width: 1.5; }
.field__miss { fill: none; stroke: var(--plate-faint); stroke-width: 1.5; stroke-dasharray: 2 2; }
.field__index { fill: var(--plate-soft); font-size: 9px; }

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

.rubric__row {
  display: grid;
  grid-template-columns: 1.6rem 4.6rem 1fr;
  gap: 0.5rem;
  align-items: baseline;
  padding: 0.55rem 0;
  border-top: 1px solid rgba(247, 243, 234, 0.12);
  font-size: 0.88rem;
  color: var(--plate-soft);
}

.rubric__row:first-child { border-top: 0; }
.rubric__range { color: var(--tier-mark); font-variant-numeric: tabular-nums; }
.rubric__text strong { color: var(--tier-mark); font-weight: 600; }
.rubric__row.is-earned { color: #ffffff; }
.rubric__row:not(.is-earned) { opacity: 0.6; }

.results__recap .results__rows { margin-top: 0; }
.results__row-verse {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.82rem;
  font-style: italic;
  line-height: 1.4;
  color: var(--plate-soft);
  quotes: "\201C" "\201D";
}
.results__row-verse mark {
  font-style: normal;
  font-weight: 600;
  color: inherit;
  background: rgba(240, 200, 90, 0.32);
  border-radius: 3px;
  padding: 0 0.15em;
}
.results__row-same { display: block; margin-top: 0.15rem; font-size: 0.8rem; color: var(--plate-soft); }
.results__row-same strong { color: var(--plate-uncommon); font-variant-numeric: tabular-nums; }

/* "Should this have counted?" under a guess that did not score. */
.results__report { display: block; margin-top: 0.15rem; font-size: 0.8rem; color: var(--plate-soft); }
.results__report-form { display: inline; }
.results__report-button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

/* --- results: every answer a prompt accepted ------------------------------ */

/* The prompt line in "Your answers" opens the list. */
.results__explore {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.82rem;
  text-align: left;
  cursor: pointer;
}
.results__explore:hover { color: #ffffff; }
.results__explore:focus-visible { outline: 2px solid #ffe08a; outline-offset: 2px; }
.results__explore-cue {
  margin-left: 0.35rem;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--plate-the-one);
}

/* The dialog sits in the top layer but still inherits the results plate's
   colours from where it lives in the page. Stepped corners, like the
   did-you-mean panel. */
.answer-key {
  --answer-key-top: max(1rem, 8dvh);
  width: min(36rem, calc(100vw - 2rem));
  max-height: none;
  /* Pinned from the top rather than centred, so switching filters moves only
     the bottom edge and the chips stay under the finger. */
  margin: var(--answer-key-top) auto auto;
  overflow: hidden;
  padding: 0;
  border: 0;
  background: rgb(16, 30, 20);
  color: #f3f7f0;
  text-align: left;
  box-shadow: inset 0 0 0 2px rgba(247, 243, 234, 0.22);
  clip-path: polygon(
    0 8px, 4px 8px, 4px 4px, 8px 4px, 8px 0,
    calc(100% - 8px) 0, calc(100% - 8px) 4px, calc(100% - 4px) 4px, calc(100% - 4px) 8px, 100% 8px,
    100% calc(100% - 8px), calc(100% - 4px) calc(100% - 8px), calc(100% - 4px) calc(100% - 4px),
    calc(100% - 8px) calc(100% - 4px), calc(100% - 8px) 100%,
    8px 100%, 8px calc(100% - 4px), 4px calc(100% - 4px), 4px calc(100% - 8px), 0 calc(100% - 8px)
  );
}
.answer-key[open] { display: flex; animation: answer-key-in 160ms steps(3); }
.answer-key::backdrop { background: rgba(10, 20, 12, 0.7); }

@keyframes answer-key-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .answer-key[open] { animation: none; } }

.answer-key__panel {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-height: min(40rem, calc(100dvh - var(--answer-key-top) - 1rem));
  padding: 1.1rem 1.2rem 0.4rem;
}

/* Only the list scrolls. The header and chips keep their size however long
   the list is; left shrinkable, a long list squeezes them flat. */
.answer-key__header { position: relative; flex-shrink: 0; padding-right: 2.2rem; }
.answer-key__prompt { margin: 0; font-size: 1.05rem; line-height: 1.35; color: #ffffff; }
.answer-key__close-form { position: absolute; top: -0.3rem; right: -0.4rem; margin: 0; }
.answer-key__close {
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 2px solid rgba(247, 243, 234, 0.3);
  border-radius: 0;
  background: none;
  color: #f3f7f0;
  font: inherit;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.answer-key__close:hover { background: rgba(247, 243, 234, 0.1); }

/* One row of chips. Phones drop the words and keep the symbols; the row
   scrolls sideways rather than wrapping if it still does not fit. */
.answer-key__filters {
  display: flex;
  flex-shrink: 0;
  gap: 0.25rem;
  margin: 0.9rem 0 0.6rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.answer-key__chip {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: 0.25rem;
  white-space: nowrap;
  padding: 0.2rem 0.35rem;
  border: 2px solid var(--tier-mark, rgba(247, 243, 234, 0.4));
  border-radius: 0;
  background: none;
  color: var(--tier-mark, #f3f7f0);
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.64rem;
  letter-spacing: 0;
  cursor: pointer;
  transition: transform 90ms steps(2);
}
@media (max-width: 40rem) {
  .answer-key__chip-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
.answer-key__chip:hover { background: rgba(247, 243, 234, 0.08); }
.answer-key__chip:active { transform: translateY(2px); }
.answer-key__chip:focus-visible { outline: 2px solid #ffe08a; outline-offset: 2px; }
.answer-key__chip[aria-pressed="true"] {
  background: var(--tier-mark, #f3f7f0);
  color: rgb(16, 30, 20);
}
.answer-key__chip-count { opacity: 0.7; font-variant-numeric: tabular-nums; }

.answer-key__list {
  flex: 1 1 auto;
  min-height: 0;
  list-style: none;
  margin: 0;
  padding: 0 0 0.6rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-top: 1px dashed var(--plate-faint);
}
.answer-key__answer {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.5rem 0.2rem;
  border-bottom: 1px solid rgba(247, 243, 234, 0.1);
  font-size: 0.9rem;
}
.answer-key__answer[hidden] { display: none; }
.answer-key__answer.is-yours { background: rgba(240, 200, 90, 0.12); }
.answer-key__text { flex: 1; min-width: 0; }
.answer-key__name strong { color: #ffffff; font-weight: 600; }
.answer-key__reference { color: var(--plate-soft); font-size: 0.82rem; }
.answer-key__fact {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 0.1rem;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--plate-soft);
}
.answer-key__tier {
  flex-shrink: 0;
  text-align: right;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tier-mark);
}
.answer-key__yours { display: block; color: var(--plate-the-one); }

.logbook {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
  margin: 0;
}

.logbook__stat dt {
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--plate-soft);
}

.logbook__stat dd {
  margin: 0;
  font-family: var(--serif);
  font-size: 1.4rem;
  font-variant-numeric: tabular-nums;
}

/* --- did you mean --------------------------------------------------------- */

/* Floats just above the dock, centred over the answer box. The dock is fixed,
   so it is the positioning parent; the panel never pushes the input around.
   Stepped corners instead of a radius, to match the pixel pasture. */
.round__suggestion {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 0.75rem);
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100vw - 2rem);
  padding: 0.85rem 1.6rem 0.9rem;
  text-align: center;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  background: rgb(16, 30, 20);
  box-shadow:
    inset 0 0 0 2px rgba(247, 243, 234, 0.22),
    0 6px 0 rgba(16, 30, 20, 0.45);
  clip-path: polygon(
    0 8px, 4px 8px, 4px 4px, 8px 4px, 8px 0,
    calc(100% - 8px) 0, calc(100% - 8px) 4px, calc(100% - 4px) 4px, calc(100% - 4px) 8px, 100% 8px,
    100% calc(100% - 8px), calc(100% - 4px) calc(100% - 8px), calc(100% - 4px) calc(100% - 4px),
    calc(100% - 8px) calc(100% - 4px), calc(100% - 8px) 100%,
    8px 100%, 8px calc(100% - 4px), 4px calc(100% - 4px), 4px calc(100% - 8px), 0 calc(100% - 8px)
  );
  animation: suggestion-in 160ms steps(3);
}

.round__suggestion-pair {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0.2rem 0.75rem;
  font-size: clamp(1rem, 4vw, 1.35rem);
  font-weight: 700;
  letter-spacing: 0.06em;
}

.round__suggestion-typed { color: rgba(243, 247, 240, 0.55); }
.round__suggestion-arrow { color: #f3f7f0; }
.round__suggestion-name { color: #ffe08a; text-shadow: 0 2px 0 rgba(0, 0, 0, 0.35); }

.round__suggestion-hint {
  margin: 0.55rem 0 0;
  font-size: clamp(0.66rem, 2.4vw, 0.8rem);
  letter-spacing: 0.16em;
  color: rgba(243, 247, 240, 0.7);
}

@keyframes suggestion-in {
  from { opacity: 0; transform: translate(-50%, 6px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

@media (prefers-reduced-motion: reduce) { .round__suggestion { animation: none; } }

/* --- progress: one segment per prompt, and the score, pinned to the top -- */
/*
 * A thin pixel strip across the very top of the screen, above the sky, so it
 * never covers the scene. Square ends and a hard edge, like the dock and the
 * sound toggle. Answered prompts are filled cream, the one on screen (or up
 * next) is gold, and the rest are dark. The running score sits at the right.
 */

.progress {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: calc(30px + env(safe-area-inset-top));
  /* Room at the left for the sound toggle, which moves into the strip. */
  padding: env(safe-area-inset-top) 0.6rem 0 calc(0.75rem + 30px);
  background: rgba(16, 30, 20, 0.92);
  border-bottom: 2px solid rgba(247, 243, 234, 0.22);
  color: #f3f7f0;
}

.progress__track {
  flex: 1;
  display: flex;
  gap: 3px;
}

.progress__segment {
  flex: 1;
  height: 6px;
  background: rgba(247, 243, 234, 0.14);
}

.progress__segment--done { background: #f7f3ea; }
.progress__segment--current {
  background: var(--gold);
  animation: progress-glint 1.6s steps(2, jump-none) infinite alternate;
}

@keyframes progress-glint {
  from { background: var(--gold); }
  to { background: #f2c55c; }
}

.progress__score {
  flex: none;
  margin: 0;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
  line-height: 1;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
}

.progress__score-value {
  display: inline-block;
  color: #f2c55c;
  font-weight: 700;
}

.progress__score-value.is-bumped { animation: score-bump 260ms steps(3, end); }

@keyframes score-bump {
  50% { transform: translateY(-3px) scale(1.15); }
}

.progress__score-unit {
  color: rgba(243, 247, 240, 0.7);
  text-transform: uppercase;
  font-size: 0.68rem;
}

@media (prefers-reduced-motion: reduce) {
  .progress__segment--current,
  .progress__score-value.is-bumped { animation: none; }
}

/* While the strip is showing, the sound toggle shrinks into its left end
   rather than hanging over the card, and the card starts below the strip. */
body:has(.progress) .sound-toggle {
  top: calc(3px + env(safe-area-inset-top));
  padding: 3px;
  border-width: 1px;
}

body:has(.progress) .sound-toggle svg { width: 18px; height: 14px; }

.stage:has(.progress) { padding-top: calc(2rem + 30px + env(safe-area-inset-top)); }

/* --- ad rails ------------------------------------------------------------- */
/*
 * A 160x600 banner either side of the field, each in its own gutter. On wide
 * screens the pasture, the cards and the dock all draw between the gutters, so
 * a banner never covers the sheep or the flock; the art itself is unchanged,
 * the field is just a little narrower. Below that width there are no rails and
 * no gutters. Ad-free players get neither (the rails are not rendered at all).
 */

.ad-rail { display: none; }

@media (min-width: 80rem) {
  body:has(> .ad-rail) {
    --rail-gutter: calc(160px + 2rem);
    background: #16261a;
  }

  body:has(> .ad-rail) .pasture { inset: 0 var(--rail-gutter); }
  body:has(> .ad-rail) .stage { margin-inline: var(--rail-gutter); }
  body:has(> .ad-rail) .dock,
  body:has(> .ad-rail) .progress { inset-inline: var(--rail-gutter); }
  body:has(> .ad-rail) .sound-toggle { left: calc(var(--rail-gutter) + 0.75rem); }

  .ad-rail {
    position: fixed;
    top: max(1rem, calc(50% - 300px));
    z-index: 1;
    display: block;
    width: 160px;
    height: 600px;
  }

  .ad-rail--left { left: 1rem; }
  .ad-rail--right { right: 1rem; }
}

.ad-rail__slot { display: block; width: 160px; height: 600px; }

.ad-rail__slot--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  color: rgba(247, 243, 234, 0.75);
  background: rgba(16, 30, 20, 0.35);
  border: 2px dashed rgba(247, 243, 234, 0.45);
}

/* --- sound toggle --------------------------------------------------------- */

.sound-toggle {
  position: fixed;
  top: calc(0.75rem + env(safe-area-inset-top));
  left: 0.75rem;
  z-index: 3;
  padding: 8px;
  line-height: 0;
  background: #26402c;
  border: 2px solid #f7f3ea;
  border-radius: 0;
  cursor: pointer;
}

.sound-toggle svg { width: 27px; height: 21px; }
.sound-toggle:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
.sound-toggle[aria-pressed="true"] .sound-toggle__off,
.sound-toggle[aria-pressed="false"] .sound-toggle__on { display: none; }

/* --- credits -------------------------------------------------------------- */

.credits__title { margin: 0 0 0.5rem; font-size: 1.5rem; color: #ffffff; }
.credits__heading {
  margin: 1.2rem 0 0.4rem;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(243, 247, 240, 0.75);
}
.credits__list { margin: 0; padding-left: 1.1rem; font-size: 0.92rem; }
.credits__list li + li { margin-top: 0.4rem; }
.card--credits a { color: #f6d58e; }
.credits__back { margin: 1.5rem 0 0; }

.credits-link {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.7rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(243, 250, 245, 0.85);
  text-shadow: 0 1px 0 rgba(20, 40, 25, 0.7);
}
.credits-link:hover { color: #ffffff; }
.card__credits { margin: 1rem 0 0; }
.card__credits .credits-link + .credits-link { margin-left: 1.25rem; }

/* --- reading pages: how to play, about, contact, the archive ------------- */

.card--page { max-width: 40rem; }
.card--page p { margin: 0.6rem 0; font-size: 0.95rem; line-height: 1.6; }
.card--page .credits__list { line-height: 1.55; }
.card--page h3.credits__heading { font-weight: 400; }

.site-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.25rem;
  margin: 1.25rem 0 0;
}
.card--page .site-links { justify-content: flex-start; }
.card--page .site-links .credits-link { color: rgba(243, 250, 245, 0.85); }
.card--page .site-links .credits-link:hover { color: #ffffff; }

.title-guide__tiers {
  display: grid;
  gap: 0.3rem;
  margin: 0.4rem 0 0.8rem;
  padding: 0;
  list-style: none;
  font-size: 0.92rem;
}
.title-guide__tiers li {
  display: grid;
  grid-template-columns: 1.6rem 1fr auto;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.25rem 0;
  border-bottom: 1px solid rgba(247, 243, 234, 0.12);
}
.title-guide__tiers li span:last-child {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem;
  color: rgba(243, 247, 240, 0.75);
}

.page__faq { margin: 0.4rem 0 0; font-size: 0.95rem; line-height: 1.55; }
.page__faq dt { margin-top: 0.9rem; font-weight: 700; color: #ffffff; }
.page__faq dd { margin: 0.25rem 0 0; }

/* The how-to under the title card. Outside the stage frame, so it starts below
   the first screen and the title still opens exactly as it always has. Once
   Start swaps the title card out of the frame, the guide goes with it. */
.title-guide {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  padding: 0 1rem calc(4rem + env(safe-area-inset-bottom));
  scroll-margin-top: 1rem;
}
.stage:not(:has(.card--title)) ~ .title-guide { display: none; }
.title-guide__more { margin-top: 1.2rem !important; }

/* Over sky or hillside depending on the screen, so the links carry their own
   plate, like the flock number above them. */
.card--title .site-links {
  width: fit-content;
  max-width: 100%;
  margin: 0.9rem auto 0;
  padding: 0.35rem 0.85rem;
  background: rgba(20, 40, 25, 0.55);
}
ol.credits__list { list-style: decimal; }

/* the archive */

.archive__list { margin: 1rem 0 0; padding: 0; list-style: none; }
.archive__item { padding: 0.75rem 0; border-top: 1px solid rgba(247, 243, 234, 0.14); }
.archive__name { margin: 0; font-size: 1.05rem; }
.archive__date {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  color: rgba(243, 247, 240, 0.7);
}
.archive__name .archive__date { margin-left: 0.5rem; }
.card--page p.archive__prompts { margin: 0.3rem 0 0; font-size: 0.85rem; color: rgba(243, 247, 240, 0.8); }
.card--page p.archive__crumbs { margin: 0 0 0.4rem; font-size: 0.8rem; }
.card--page p.archive__date { margin: 0 0 0.6rem; }
.archive__play span { color: rgba(243, 247, 240, 0.65); font-size: 0.85rem; }

.archive__prompt { margin-top: 1.4rem; padding-top: 1rem; border-top: 1px solid rgba(247, 243, 234, 0.18); }
.archive__prompt-text { margin: 0 0 0.4rem; font-size: 1.1rem; color: #ffffff; }
.archive__position { color: rgba(243, 247, 240, 0.6); }

.archive__the-one {
  margin: 0.6rem 0;
  padding: 0.5rem 0.8rem;
  background: rgba(246, 213, 142, 0.08);
  border-left: 3px solid #f6d58e;
}
.archive__verse { margin: 0.4rem 0 0.2rem; font-style: italic; }
.card--page .archive__verse p { margin: 0; font-size: 0.92rem; }
.archive__verse footer {
  margin-top: 0.2rem;
  font-style: normal;
  font-size: 0.75rem;
  color: rgba(243, 247, 240, 0.65);
}

.archive__answers { margin-top: 0.6rem; font-size: 0.9rem; }
.archive__answers summary { cursor: pointer; color: #f6d58e; }
.archive__answer-list { margin: 0.5rem 0 0; padding: 0; list-style: none; }
.archive__answer-list li { padding: 0.3rem 0; border-bottom: 1px solid rgba(247, 243, 234, 0.1); }
.archive__reference,
.archive__tier { color: rgba(243, 247, 240, 0.65); }
.archive__fact { display: block; margin-top: 0.15rem; font-size: 0.85rem; color: rgba(243, 247, 240, 0.8); }

.archive__pager { display: flex; justify-content: space-between; margin-top: 1.5rem; }

/* Long reading pages start at the top, below the sound toggle, not centred. */
.stage:has(.card--page) {
  align-items: flex-start;
  padding-top: calc(4.25rem + env(safe-area-inset-top));
}

/* --- the round with the phone keyboard open ------------------------------- */
/*
 * A phone's keyboard covers about half the screen, and the browser slides the
 * page up until the answer box clears it, which takes the progress strip and
 * the question with it. The keyboard controller measures what is still visible
 * and these rules pin the strip, the card and the dock inside it, so the
 * question stays in view while the player types.
 *
 * Chrome on Android shrinks the page itself (interactive-widget in the viewport
 * meta), so there only the short-screen rule below applies.
 */
html[data-keyboard="open"] .progress,
html[data-keyboard="open"] body:has(.progress) .sound-toggle { translate: 0 var(--vv-top, 0px); }

html[data-keyboard="open"] .dock { bottom: var(--vv-bottom, 0px); }

html[data-keyboard="open"] .card--round {
  position: fixed;
  z-index: 1;
  top: calc(var(--vv-top, 0px) + 30px + env(safe-area-inset-top) + 1rem);
  inset-inline: 1rem;
  width: auto;
  margin-inline: auto;
  /* Never under the dock: what is left between the strip and the dock. */
  max-height: calc(100% - var(--vv-top, 0px) - var(--vv-bottom, 0px)
                   - 30px - env(safe-area-inset-top) - var(--dock-height) - 2rem);
  overflow-y: auto;
}

/* The dock's safe-area padding is for the home bar, which the keyboard covers. */
html[data-keyboard="open"] .dock { padding-bottom: 0.9rem; }

/* On the shortest screens the hint gives its room to the question. */
html[data-keyboard-short] .round__hint { display: none; }
html[data-keyboard-short] .round__prompt { margin-bottom: 0; }

@media (max-width: 40rem) and (max-height: 300px) {
  .round__hint { display: none; }
  .round__prompt:has(+ .round__hint) { margin-bottom: 0; }
}
