/* The Split — "Green & Gold".
 *
 * Colour discipline, and the reason most of this file is monochrome:
 *   gold       = money, or you. Nothing else.
 *   terracotta = refusal and destruction. Nothing else.
 *   ivory      = every other piece of information, at one of four opacities.
 *
 * Type discipline: every numeral is the serif, every label is the mono.
 */

:root {
  /* ground */
  --bg:          #0A241C;
  --bg-grad:     linear-gradient(168deg, #0F3328, #0A241C 58%, #071A14);
  --bg-glow:     radial-gradient(62% 48% at 78% 4%, rgba(214, 178, 92, .14), transparent 60%);
  --bg-deep:     #071A14;

  /* type */
  --fg:          #F2EFE2;
  --muted:       rgba(242, 239, 226, .45);
  --dim:         rgba(242, 239, 226, .34);
  --faint:       rgba(242, 239, 226, .28);

  /* structure */
  --line:        rgba(242, 239, 226, .08);
  --line-strong: rgba(242, 239, 226, .16);
  --track:       rgba(242, 239, 226, .15);

  /* gold */
  --gold:        #D6B25C;
  --gold-bright: #F0DFA8;
  --gold-deep:   #A67F32;
  --gold-grad:   linear-gradient(90deg, #D6B25C, #A67F32);
  --gold-btn:    linear-gradient(180deg, #E0C177, #B78E3C);

  /* terracotta */
  --reject:      #D9694F;
  --reject-btn:  linear-gradient(180deg, #E07C61, #B8503A);
  --reject-ink:  #2A0D06;   /* text on a solid terracotta button */

  --serif: 'Instrument Serif', 'Iowan Old Style', 'Palatino Linotype',
           Palatino, Georgia, serif;
  --mono:  'DM Mono', ui-monospace, 'SF Mono', SFMono-Regular, Menlo,
           Consolas, monospace;

  --ease: cubic-bezier(.22, .61, .36, 1);

  /* Drives both the ✓/✗ glyph and the height its row reserves, so the two can
   * never drift apart and shift the figures above them. */
  --mark-size: 32px;

  /* One type ramp shared by every screen outside the round — menu, rules,
   * rankings, setup — so they all read at the same size.
   *
   * Height-led, because height is the axis that runs out first on a desktop
   * window; but capped by width too, or a tall narrow phone (812 high, 375
   * wide) would size the type off the height it has plenty of and push the
   * controls off the edge it does not. Whichever axis is tighter wins. */
  --t-eyebrow: clamp(.62rem, min(1.5vh, 2.7vw), .88rem);   /* gold headings */
  --t-label:   clamp(.62rem, min(1.62vh, 2.9vw), .95rem);  /* labels, keys */
  --t-body:    clamp(.95rem, min(2.25vh, 4.2vw), 1.35rem); /* serif prose */
  --t-body-sm: clamp(.85rem, min(1.95vh, 3.6vw), 1.12rem); /* secondary serif */
  --t-lead:    clamp(1.15rem, min(3vh, 5.4vw), 1.85rem);   /* setup sentence */
  --t-btn:     clamp(.74rem, min(1.75vh, 3.1vw), 1.05rem); /* buttons */

  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body { height: 100%; }

body {
  background: var(--bg-glow), var(--bg-grad), var(--bg);
  background-attachment: fixed;
  color: var(--fg);
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}

/* ------------------------------------------------------------- screens -- */

.screen {
  position: fixed;
  inset: 0;
  display: none;
  flex-direction: column;
  padding: max(1.25rem, env(safe-area-inset-top)) 1.25rem
           max(1.25rem, env(safe-area-inset-bottom));
}

.screen.is-active {
  display: flex;
  animation: screen-in .45s var(--ease) both;
}

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

/* The way out, in the same corner on every screen that has one — and outside
 * the scrolling content, so it is never something you have to scroll down to
 * find. The game's QUIT sits in the same place and reads the same way. */
/* The menu's one persistent control, mirroring .nav-back in the far corner. */
/* Fixed, not absolute: it lives outside every screen and must stay in the same
 * corner whatever is scrolling underneath it. */
/* Opposite corner to BACK, so the two never have to be measured against each
 * other and nothing has to move when a label changes width. */
.nav-sound {
  position: fixed;
  top: max(1.25rem, env(safe-area-inset-top));
  right: 1.25rem;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: .45rem;
  border: 0;
  background: transparent;
  cursor: pointer;
}

/* A gear says "settings" faster than the word does, and takes a fraction of the
 * room. Dimmed to sit with the other chrome, full white on hover. */
.gear {
  display: block;
  width: clamp(20px, min(3.2vh, 5.6vw), 26px);
  height: auto;
  opacity: .45;
  transition: opacity .2s var(--ease), transform .3s var(--ease);
}

/* Muted is drawn, not spelled: the word is struck through and dimmed. The strike
 * is the state, so the label stays "sound" either way. Below
 * --faint (.28) so the dim reads as a change, but not hidden — a control you
 * cannot find is not a toggle. */
.nav-sound[aria-pressed="false"],
.hud-btn[aria-pressed="false"] {
  color: rgba(242, 239, 226, .2);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-skip-ink: none;
}

@media (hover: hover) {
  .nav-sound:hover .gear { opacity: 1; transform: rotate(35deg); }
}
.nav-sound[aria-expanded="true"] .gear { opacity: 1; }
.nav-sound:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* `display: flex` above would otherwise beat the browser's own `[hidden]`
 * rule, and the gear would keep rendering on the round screen while its
 * attribute claimed it was gone. */
.nav-sound[hidden] { display: none; }

/* Screen bodies scroll when a window is too short for them, and the native bar
 * is a wide pale slab against a dark panel — on the tournament finale it lands
 * directly beside the standings. Hidden in both engines; the scrolling itself is
 * untouched, since every one of these keeps `overflow-y: auto` and so only
 * scrolls when the content really is taller.
 *
 * Listed explicitly rather than applied to `.screen` or `*`: these are the five
 * containers that scroll a whole screen's content. `.menu-inner` and `.board`
 * are deliberately left out — they show a 3px hairline, which is the house
 * style wherever a scroll cue is actually wanted. */
.howto,
.ranks,
.setup,
.gate,
.tourney {
  scrollbar-width: none;        /* Firefox */
  -ms-overflow-style: none;     /* legacy Edge / IE */
}

.howto::-webkit-scrollbar,
.ranks::-webkit-scrollbar,
.setup::-webkit-scrollbar,
.gate::-webkit-scrollbar,
.tourney::-webkit-scrollbar { width: 0; height: 0; }   /* Chrome, Safari, Edge */

.nav-back {
  align-self: flex-start;
  flex: 0 0 auto;
  margin-bottom: .25rem;
  padding: .4rem .6rem .4rem 0;
  border: 0;
  background: transparent;
  font: 400 clamp(.8rem, min(1.75vh, 3.1vw), 1.02rem)/1 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--faint);
  cursor: pointer;
  transition: color .2s var(--ease);
}

.nav-back::before { content: '\2190\00a0\00a0'; }   /* ← */

@media (hover: hover) { .nav-back:hover { color: var(--fg); } }
.nav-back:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* The name of the screen — set large enough to be the first thing read, and
 * given room of its own beneath it. Mono, because it is a label, not a figure. */
.screen-title {
  font: 400 clamp(1.3rem, min(3.4vh, 6vw), 2.4rem)/1 var(--mono);
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(242, 239, 226, .58);
  margin-bottom: clamp(.6rem, 1.8vh, 1.4rem);
}

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

.btn {
  font: 400 .75rem/1 var(--mono);
  letter-spacing: .22em;
  text-transform: uppercase;
  padding: .875rem 2rem;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--fg);
  cursor: pointer;
  white-space: nowrap;
  transition: color .2s var(--ease), border-color .2s var(--ease),
              filter .2s var(--ease), transform .12s var(--ease);
}

.btn[hidden] { display: none; }

.btn-primary {
  background: var(--gold-btn);
  color: #0A241C;
}

.btn-lead { padding: 1rem 3.9rem; }

.btn-ghost {
  border: 1px solid var(--line-strong);
  color: rgba(242, 239, 226, .6);
  padding: .7rem 1.4rem;
}

/* Refusing is an answer, not a way out, so it carries the same weight as
 * accepting — solid, in the one colour that means destruction. */
.btn-refuse {
  background: var(--reject-btn);
  color: var(--reject-ink);
  border: 0;
}

@media (hover: hover) {
  .btn-primary:hover,
  .btn-refuse:hover { filter: brightness(1.07); }
  .btn-ghost:hover { border-color: var(--fg); color: var(--fg); }
}

.btn:active { transform: translateY(1px) scale(.985); }

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

/* --------------------------------------------------------------- mark --- */

/* The 70/30 rule: the game's only ornament, and the same shape that divides
 * the money on every round screen. */
.emblem { display: flex; gap: 3px; width: min(340px, 100%); }
.emblem span { height: 5px; }
.emblem-keep { flex: 70; background: var(--gold-grad); }
.emblem-give { flex: 30; background: var(--track); }

/* --------------------------------------------------------------- start -- */

/* The menu holds the wordmark and the three panels in one screenful — the whole
 * pitch without a scroll. It can still scroll if the window is genuinely too
 * short, which is what the inner block is for: `min-height` centring rather
 * than `margin: auto`, because an auto-margin-centred flex item that outgrows
 * its scroller overflows past the top edge where nothing can bring it back.
 * Scoped to `.is-active` so the plain `.screen` display rules still hide it. */
#screen-start.is-active {
  display: block;
  overflow-y: auto;
  scrollbar-width: thin;
}

.menu-inner {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* The menu is sized against viewport *height*, not width — it has to fill a big
 * screen without ever pushing the panels off a small one, and height is the
 * axis that runs out first. */
.start {
  margin: 0 auto;
  width: 100%;
  max-width: 34rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1rem, 2.2vh, 1.8rem);
  text-align: center;
}

.title {
  font: 400 clamp(2.9rem, min(11vh, 19vw), 6.4rem)/1 var(--serif);
  letter-spacing: -.01em;
  color: var(--fg);
}

/* The mark scales with the wordmark it sits under. */
.start .emblem { width: min(28rem, 100%); margin-top: -1.1rem; }
.start .emblem span { height: 6px; }

.blurb {
  display: flex;
  flex-direction: column;
  font: 400 clamp(.58rem, min(1.3vh, 2.4vw), .78rem)/2.15 var(--mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.blurb-lead { color: var(--gold); }

.menu-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(.8rem, 1.8vh, 1.3rem);
}

/* A shared min-width rather than equal grid columns, so the two stay the same
 * size as each other whether RANKINGS is showing or still hidden. */
.menu-secondary {
  display: flex;
  justify-content: center;
  gap: .7rem;
}

/* The way into the game, so it carries weight the in-page buttons do not. */
.menu-actions .btn {
  font-size: var(--t-btn);
  font-weight: 500;
}

/* Wider than the two beneath it on every screen size — a short label must not
 * make the primary action the smallest button on the page. */
.btn-lead {
  min-width: min(13.5rem, 64vw);
  letter-spacing: .24em;
  padding: clamp(.9rem, min(1.95vh, 3.6vw), 1.25rem)
           clamp(2.4rem, min(7vh, 12vw), 4.6rem);
}

/* Quieter than START: smaller, and equal to each other. */
.menu-secondary .btn {
  min-width: min(9.5rem, 40vw);
  font-size: calc(var(--t-btn) * .86);
  padding: clamp(.62rem, min(1.35vh, 2.5vw), .85rem) .75rem;
  text-align: center;
}

/* ---------------------------------------------------------- menu steps -- */

/* Three panels under the fold explaining the game in one pass. */
/* The squares are the tallest thing on the page, so the whole strip is capped
 * against viewport height: at three columns each image is about a third of
 * this, which is what keeps the menu inside one screen as the window shrinks. */
.steps {
  flex: 0 0 auto;
  width: 100%;
  max-width: min(66rem, 92vw, 112vh);
  margin: clamp(1rem, 2.4vh, 2rem) auto 0;
  padding-top: clamp(1rem, 2.4vh, 2rem);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.1rem, 2.6vh, 2.1rem);
}

.step { text-align: center; min-width: 0; }

/* The heading leads, so each panel reads as a titled step rather than a caption
 * hung off the bottom of a picture. */
.step h2 {
  font: 400 var(--t-eyebrow)/1 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: clamp(.6rem, 1.4vh, 1rem);
}

.step-art {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  margin-bottom: clamp(.7rem, 1.6vh, 1.15rem);
  border: 1px solid var(--line);
  border-radius: 7px;
  background: rgba(242, 239, 226, .03);
}

.step p {
  font: 400 var(--t-body)/1.45 var(--serif);
  color: rgba(242, 239, 226, .62);
  max-width: 24ch;
  margin: 0 auto;
}

/* ---------------------------------------------------------- how to play -- */

.howto {
  margin: auto;
  width: 100%;
  max-width: 46rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(.9rem, 2.1vh, 1.7rem);
  padding: 1.5rem 0;
  overflow-y: auto;
}

/* Larger than the shared eyebrow token: this is the one screen given over to
 * long-form reading, so its headings have to hold their own against the prose
 * rather than label it. */
.howto-block h3 {
  font: 400 clamp(.82rem, min(2.05vh, 3.6vw), 1.22rem)/1 var(--mono);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .7rem;
}

.howto-block p {
  font: 400 var(--t-body)/1.55 var(--serif);
  color: rgba(242, 239, 226, .85);
}

.howto-block em { font-style: italic; color: var(--fg); }

/* ------------------------------------------------------------ rankings -- */

.ranks {
  margin: auto;
  width: 100%;
  max-width: 42rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(1rem, 2.4vh, 1.9rem);
  padding: 1.5rem 0;
  overflow-y: auto;
}

.ranks-body {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: clamp(1.4rem, 3.2vh, 2.5rem);
}

/* Sized off .howto-block h3, not the eyebrow ramp: these are section headings
 * doing the same job on the same footing, and they read as an afterthought at
 * the smaller size. */
.ranks-head {
  font: 400 clamp(.82rem, min(2.05vh, 3.6vw), 1.22rem)/1 var(--mono);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .8rem;
}

.ranks-empty { font: 400 var(--t-body)/1.5 var(--serif); color: var(--muted); }

.stat {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: clamp(.5rem, 1.25vh, .85rem) 0;
  border-bottom: 1px solid var(--line);
}

.stat:last-child { border-bottom: 0; }

.stat-key {
  font: 400 var(--t-label)/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}

.stat-val { font: 400 var(--t-body)/1 var(--serif); color: var(--fg); }

/* Wins are the only figure here worth gold. */
.stat.is-gold .stat-val { color: var(--gold); }

/* --------------------------------------------------------------- setup -- */

/* Stacked rather than inline, so each is a comfortable target on a phone. */
.legal-links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .55rem;
}

.legal-links a {
  font: 400 var(--t-body-sm)/1.4 var(--mono);
  letter-spacing: .04em;
  color: var(--gold);
  text-decoration: none;
  border-bottom: 1px solid rgba(214, 178, 92, .35);
  padding: .15rem 0;
}

@media (hover: hover) {
  .legal-links a:hover { color: var(--gold-bright); border-bottom-color: var(--gold-bright); }
}
.legal-links a:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* ---------------------------------------------------- gate / tournament -- */

.gate,
.tourney {
  margin: auto;
  width: 100%;
  max-width: 50rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.1rem, 2.6vh, 2rem);
  padding: 1.5rem 0;
  overflow-y: auto;
}

/* The scrolling half of the tournament screen. `min-height: 0` is what lets it
 * actually scroll inside the column flex rather than growing past it.
 *
 * The finale can outgrow a short window — a podium plus twelve rows — so it has
 * to scroll, but the native bar is a wide pale slab landing directly beside the
 * standings. It is hidden in both engines while the scrolling itself is left
 * completely alone: `overflow-y` stays `auto`, so the box only scrolls when the
 * content really is taller, and the buttons sit outside it so nothing can be
 * stranded below the fold.
 *
 * Scoped to this one container on purpose. It is the only element on the screen
 * that scrolls — verified: the `.board` inside it never does, because this box
 * gives it all the height it asks for — and the page itself never scrolls,
 * since `body` is `overflow: hidden`. */
.tourney { flex: 1 1 auto; min-height: 0; margin: 0 auto; }

/* Sized off the setup screen's PLAY, so the way forward carries the same weight
 * wherever it appears. Centred under the legs, which on the bracket is the last
 * thing above it. */
.tourney-actions {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: .75rem;
  padding-top: clamp(.4rem, 1.2vh, .9rem);
}

/* Both buttons, not just the primary one: side by side, a full-sized READY next
 * to a small ABANDON read as a mistake. `min-width` is what makes them equal,
 * since the two labels are different lengths. */
.tourney-actions .btn {
  min-width: min(15rem, 70vw);
  font-weight: 500;
  font-size: clamp(.95rem, min(2.3vh, 4vw), 1.3rem);
  padding: clamp(1rem, min(2.3vh, 4vw), 1.45rem) clamp(1.6rem, min(4vh, 7vw), 2.6rem);
}

/* ABANDON carries a 1px border and READY does not, which made the two boxes
 * differ by exactly that. Matched with an invisible one rather than by trimming
 * the padding, so the two stay level if either is ever restyled. */
.tourney-actions .btn-primary { border: 1px solid transparent; }

/* Two 15rem buttons cannot sit side by side on a phone, and stacked they push
 * ABANDON off the bottom. Sharing the row keeps both on screen and still equal,
 * since they flex from the same basis. */
@media (max-width: 560px) {
  .tourney-actions .btn {
    min-width: 0;
    flex: 1 1 0;
    padding-left: .8rem;
    padding-right: .8rem;
  }
}

.gate-opts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .9rem;
  width: min(44rem, 100%);
}

/* The picture carries the card; the frame does not. No border and no fill —
 * an outlined box around an image reads as a form control, which is what made
 * the first version of this screen look cheap. */
.gate-card {
  display: flex;
  flex-direction: column;
  gap: .7rem;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--fg);
  text-align: center;
  cursor: pointer;
}

.gate-art {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 10px;
  /* Holds the shape if the file is missing, so the row degrades to an empty
   * panel rather than a broken-image glyph. Deliberately not an onerror swap:
   * one transient 404 used to rewrite a working src permanently. */
  background: rgba(242, 239, 226, .04);
  /* The art is dim by design so the gold label reads over it; it lifts on
   * hover, which is the whole hover state. */
  filter: brightness(.72) saturate(.9);
  transition: filter .25s var(--ease), transform .25s var(--ease);
}

.gate-name {
  font: 400 var(--t-btn)/1 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold);
}

/* `min-height` reserves two lines whether or not this one needs them, so the two
 * cards stay level however each caption happens to wrap. */
.gate-note {
  font: 400 var(--t-body-sm)/1.55 var(--mono);
  color: var(--muted);
  text-transform: none;
  letter-spacing: .04em;
  max-width: 32ch;
  min-height: 3.1em;
  margin: 0 auto;
}

@media (hover: hover) {
  .gate-card:hover .gate-art {
    filter: brightness(1) saturate(1);
    transform: translateY(-2px);
  }
  .gate-card:hover .gate-name { color: var(--gold-bright); }
}
.gate-card:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
.gate-card:active .gate-art { transform: translateY(0) scale(.995); }

/* Wide enough that each of the two sentences holds its own line at desktop
 * width — the break between them is explicit, so a measure that wrapped them
 * again turned two lines into four. A phone still wraps, which is fine. */
.tourney-lead {
  font: 400 var(--t-body)/1.5 var(--serif);
  text-align: center;
  max-width: 68ch;
  color: rgba(242, 239, 226, .9);
}

.legs {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: .6rem;
  width: min(42rem, 100%);
}

/* Four columns of header — number, name, placing, points — with the description
 * and the leg's own rules spanning underneath. The rules line is the point: it
 * is where the tournament explains how it works, instead of the player having
 * to infer the cuts and the scoring from three results. */
.leg {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: baseline;
  column-gap: .9rem;
  row-gap: .3rem;
  padding: clamp(.75rem, 1.9vh, 1.15rem) clamp(.9rem, 2vw, 1.25rem);
  border: 1px solid var(--line);
  border-radius: 8px;
}

/* The leg's position in the run, as a figure you count rather than read. */
.leg-num {
  font: 400 1.5em/1 var(--serif);
  color: var(--faint);
  min-width: 1.1em;
}

.leg-name {
  font: 400 var(--t-label)/1 var(--mono);
  letter-spacing: .18em;
  text-transform: uppercase;
}

.leg-out {
  font: 400 var(--t-label)/1 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

/* Gold, because points are what the tournament is scored on. */
.leg-pts[hidden] { display: none; }

.leg-pts {
  font: 400 1.15em/1 var(--serif);
  color: var(--gold);
  white-space: nowrap;
  min-width: 3.2em;
  text-align: right;
}

.leg-desc {
  grid-column: 2 / -1;
  font: 400 var(--t-body-sm)/1.45 var(--serif);
  color: rgba(242, 239, 226, .78);
}

.leg-meta {
  grid-column: 2 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .1rem .5rem;
  font: 400 var(--t-eyebrow)/1.4 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
}

.leg-sep { color: rgba(242, 239, 226, .18); }

/* Its own line, third in the card, so it always sits where the eye expects it
 * rather than wrapping off the end of the row above. */
.leg-score {
  grid-column: 2 / -1;
  font: 400 var(--t-eyebrow)/1.4 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
}

.leg-won {
  grid-column: 2 / -1;
  font: 400 var(--t-body-sm)/1.4 var(--serif);
  font-style: italic;
  color: var(--muted);
}
.leg-won.is-you { color: var(--gold); font-style: normal; }

/* The stage you are about to play is the only one that carries the accent. */
.leg.is-next { border-color: var(--gold); background: rgba(214, 178, 92, .08); }
.leg.is-next .leg-name,
.leg.is-next .leg-out,
.leg.is-next .leg-num { color: var(--gold-bright); }
.leg.is-next .leg-pts { color: var(--gold-bright); }
.leg.is-todo { opacity: .45; }
.leg.is-done .leg-name { color: var(--muted); }
.leg.is-done .leg-out { color: var(--fg); }

/* Below 560px four columns squeeze the name to nothing, so the points stay on
 * the header row and only the placing drops beneath it. */
@media (max-width: 560px) {
  .leg { grid-template-columns: auto 1fr auto; }
  .leg-pts { grid-column: 3; grid-row: 1; min-width: 0; }
  .leg-out { grid-column: 2; grid-row: 2; justify-self: start; }
  .leg-desc, .leg-meta, .leg-score, .leg-won { grid-column: 1 / -1; }
}

.tourney-final {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1rem, 2.4vh, 1.6rem);
  width: min(38rem, 100%);
}
.tourney-final[hidden] { display: none; }

/* This is the finale, so it is the biggest thing on the screen — the legs above
 * were made smaller precisely to pay for it. */
.podium-pts { width: min(30rem, 100%); }
.podium-pts .pod-name { font-size: 1.15em; }
.podium-pts .pod-score { letter-spacing: .06em; font-size: 1.25em; }
.podium-pts .pod-block { min-height: 3.4rem; }

/* Where the tournament stands after this game — the figure that matters once a
 * run is on, so it sits over the table it describes rather than beside the
 * result of a single game. */
.final-stage {
  font: 400 clamp(1rem, min(2.3vh, 4vw), 1.32rem)/1.45 var(--mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--gold);
  text-align: right;
}
.final-stage[hidden] { display: none; }

.final-board-title {
  font: 400 var(--t-label)/1 var(--mono);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: right;
}
.final-board-title[hidden] { display: none; }

.final-unlock {
  font: 400 var(--t-body-sm)/1.5 var(--mono);
  letter-spacing: .04em;
  color: var(--gold-bright);
  max-width: 40ch;
}
.final-unlock[hidden] { display: none; }

/* Sits under the notice it belongs to, set apart from PLAY AGAIN and MENU so
 * it reads as part of the announcement rather than a third way out. */
.final-try {
  align-self: flex-start;
  margin-top: .7rem;
  padding: .6rem 1.6rem;
  border-color: var(--gold);
  color: var(--gold);
}
.final-try[hidden] { display: none; }

@media (hover: hover) {
  .final-try:hover { border-color: var(--gold-bright); color: var(--gold-bright); }
}

#podium[hidden] { display: none; }

@media (max-width: 560px) {
  /* Stacked, so a square panel each would push the second option off the
   * screen. Both have to be visible at once — the whole screen is a choice
   * between them. `cover` crops rather than squashes. */
  .gate-opts { grid-template-columns: 1fr; }
  .gate-art { aspect-ratio: 16 / 10; max-height: 24vh; }
  .gate-note { max-width: none; }
}

.setup {
  margin: auto;
  width: 100%;
  max-width: 50rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.1rem, 2.6vh, 2rem);
  padding: 1.5rem 0;
  overflow-y: auto;
}

.mode {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1rem, 2.4vh, 1.8rem);
  width: 100%;
}

/* Plain English, regenerated on every change — the setup explains itself
 * without anyone having to open it. Sits under the three modes, describing
 * whichever one is selected.
 *
 * Two lines are reserved: every setup phrases itself at roughly the same
 * length, and the floor catches any that still come up short, so picking a
 * different mode never shifts the PLAY button underneath it. */
.mode-caption {
  font: 400 var(--t-lead)/1.4 var(--serif);
  text-align: center;
  max-width: 52ch;
  min-height: 2.8em;
  color: rgba(242, 239, 226, .9);
}

.mode-caption em { font-style: italic; color: var(--gold); }

.mode-opts {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: .55rem;
  width: min(38rem, 100%);   /* three across, PERSONALISED on one line */
}

.mode-btn {
  font: 400 var(--t-label)/1 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  padding: clamp(.8rem, 1.85vh, 1.15rem) 1rem;
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  background: transparent;
  color: rgba(242, 239, 226, .6);
  cursor: pointer;
  transition: color .2s var(--ease), background .2s var(--ease),
              border-color .2s var(--ease);
}

.mode-btn[aria-pressed="true"] {
  background: var(--gold);
  border-color: var(--gold);
  color: #0A241C;
}

.mode-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

@media (hover: hover) {
  .mode-btn:not([aria-pressed="true"]):hover { color: var(--fg); border-color: var(--fg); }
}

/* The presets are a shortcut, not the main choice, so the active one is a
 * tinted outline rather than a fill — it never competes with the row above. */
.mode-opts-sub { width: auto; gap: .4rem; }

.mode-opts-sub .mode-btn {
  font-size: clamp(.58rem, 1.4vh, .8rem);
  letter-spacing: .18em;
  padding: clamp(.55rem, 1.3vh, .8rem) clamp(.9rem, 2.2vh, 1.3rem);
  border-color: rgba(242, 239, 226, .12);
}

.mode-opts-sub .mode-btn[aria-pressed="true"] {
  background: rgba(214, 178, 92, .16);
  border-color: var(--gold);
  color: var(--gold);
}

.options {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
}

#custom-options[hidden] { display: none; }

.opt-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--line);
}

.opt-groups {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: 3rem;
}

.opt-group { display: flex; flex-direction: column; gap: .85rem; }

/* The four picker rows share one grid, so the option groups are all the width
 * of the widest (rounds, at five options) instead of each shrinking to its own
 * content. `max-content` does the measuring, so it keeps holding as the type
 * scales or an option is added. */
.opt-group-rows {
  display: grid;
  grid-template-columns: auto max-content;
  column-gap: .9rem;
  row-gap: .85rem;
  align-items: center;
}

.opt-group-rows .opt-head { grid-column: 1 / -1; }

/* Lets each row's label and options become items of the shared grid. */
.opt-group-rows .choice { display: contents; }

.opt-group-rows .choice-opts { width: 100%; }
.opt-group-rows .choice-btn { flex: 1; }

.opt-head {
  font: 400 var(--t-eyebrow)/1 var(--mono);
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .15rem;
}

.opt-note {
  margin-top: .5rem;
  font: 400 var(--t-body-sm)/1.45 var(--serif);
  color: rgba(242, 239, 226, .45);
}

.choice { display: flex; align-items: center; gap: .9rem; }

/* Two-word labels ("they play", "you open") must stay on one line, so the
 * column grows with the type and the text is not allowed to break regardless. */
.choice-label {
  flex: 0 0 clamp(80px, 13vh, 116px);
  font: 400 var(--t-label)/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--muted);
}

.choice-name { flex: 1 1 auto; }
.choice-name .choice-label { flex-basis: auto; }

.name-input {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 18rem;
  font: 400 var(--t-body-sm)/1.3 var(--serif);
  color: var(--fg);
  background: transparent;
  border: 0;
  border-bottom: 1px dashed rgba(242, 239, 226, .28);
  border-radius: 0;
  padding: .15rem 0;
}

.name-input::placeholder { color: var(--faint); }
.name-input:focus { outline: none; border-bottom-color: var(--gold); }

@media (hover: hover) { .name-input:hover { border-bottom-color: var(--muted); } }

/* A segmented group: one outlined box, the choice filled inside it. */
.choice-opts {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid rgba(242, 239, 226, .14);
  border-radius: 7px;
}

.choice-btn {
  font: 400 var(--t-label)/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: clamp(.5rem, 1.2vh, .8rem) clamp(.85rem, 2vh, 1.3rem);
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: rgba(242, 239, 226, .55);
  cursor: pointer;
  transition: color .2s var(--ease), background .2s var(--ease);
}

.choice-btn[aria-pressed="true"] { background: var(--gold); color: #0A241C; }
.choice-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

@media (hover: hover) {
  .choice-btn:not([aria-pressed="true"]):hover { color: var(--fg); }
}

.switch {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  text-align: left;
}

.switch-track {
  position: relative;
  flex: 0 0 34px;
  width: 34px;
  height: 18px;
  border-radius: 99px;
  background: rgba(242, 239, 226, .09);
  transition: background .22s var(--ease);
}

.switch-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 12px;
  height: 12px;
  border-radius: 99px;
  background: rgba(242, 239, 226, .3);
  transition: left .22s var(--ease), background .22s var(--ease);
}

.switch[aria-checked="true"] .switch-track { background: rgba(214, 178, 92, .3); }
.switch[aria-checked="true"] .switch-knob { left: 18px; background: var(--gold); }

/* The switch states itself, so the label never has to. */
.switch-label {
  font: 400 var(--t-body-sm)/1.3 var(--serif);
  color: rgba(242, 239, 226, .4);
  transition: color .22s var(--ease);
}

.switch[aria-checked="true"] .switch-label { color: var(--fg); }
.switch:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: 4px; }

.actions { display: flex; align-items: center; gap: .75rem; }

/* Every button outside the round shares the menu's weight and ramp. */
.setup > .actions .btn {
  font-size: var(--t-btn);
  font-weight: 500;
  padding: clamp(.8rem, 1.85vh, 1.15rem) clamp(1.6rem, 4vh, 2.4rem);
}

/* Set apart from the controls above it and sized past them, so the way to
 * start the game is unmistakably the loudest thing on the screen. */
.setup > .actions { margin-top: clamp(1.2rem, 3.2vh, 2.6rem); gap: .85rem; }

/* A quiet line under PLAY. Deliberately the softest thing on the screen: it is
 * there to be noticed on the way past, not to compete with the setup. */
.setup-tip {
  margin-top: clamp(.9rem, 2.2vh, 1.5rem);
  max-width: 46ch;
  font: 400 var(--t-body)/1.5 var(--serif);
  font-style: italic;
  text-align: center;
  color: rgba(242, 239, 226, .58);
  /* Two lines held open. Every tip happens to run to two at both ends of the
   * range, but reserving it means a shorter one added later cannot pull PLAY
   * down the screen with it. */
  min-height: 3em;
}

/* The scale the tournament's buttons are matched to, so the label size and the
 * invisible border are both kept in step with `.tourney-actions .btn` above.
 * Scoped to this screen rather than added to `.btn-primary`: the in-round
 * buttons reserve a fixed row height, and 2px there moves the figures above. */
.setup > .actions .btn-primary {
  border: 1px solid transparent;
  min-width: min(15rem, 70vw);
  font-size: clamp(.95rem, min(2.3vh, 4vw), 1.3rem);
  padding: clamp(1rem, min(2.3vh, 4vw), 1.45rem) clamp(3rem, min(7.5vh, 13vw), 5rem);
}

/* ------------------------------------------------------- table surface -- */

/* The felt, and only where a hand is actually being played. Every other screen
 * keeps the plain ground: the table belongs to the round, and putting it behind
 * the menu or the rules would make it wallpaper instead of a place.
 *
 * `background-attachment` is left at its default. On a scrollable element that
 * pins the image to the element's own box rather than to the content, so on a
 * phone the standings scroll over a table that stays put — which is what
 * `fixed` would be reached for, without its iOS repaint problems.
 *
 * The scrim is part of the same shorthand rather than an overlay element: the
 * artwork is dark but not uniformly, and the money figures and the standings
 * are the whole screen. One flat wash keeps their contrast the same wherever
 * the felt happens to be lit.
 *
 * Only the image matching the viewport's orientation is ever fetched, because
 * the other lives inside a media query that does not apply. */
#screen-game.is-active {
  background-image:
    linear-gradient(rgba(7, 26, 20, .62), rgba(7, 26, 20, .62)),
    url('images/horizontal.png');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
}

/* Taller than wide — phones held upright, and any window in that shape. */
@media (orientation: portrait) {
  #screen-game.is-active {
    background-image:
      linear-gradient(rgba(7, 26, 20, .62), rgba(7, 26, 20, .62)),
      url('images/vertical.png');
  }
}

/* ----------------------------------------------------------------- hud -- */

/* Same columns as .game-body below, so the round lands hard against the right
 * edge of the stage — immediately left of the standings, where the eye already
 * goes for the score. */
.hud {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 310px;
  gap: 1.75rem;
  align-items: center;
  flex: 0 0 auto;
  font: 400 .75rem/1 var(--mono);
  letter-spacing: .20em;
  text-transform: uppercase;
  color: var(--muted);
}

/* No sidebar, no column to line up with. */
body:not(.is-live) .hud { grid-template-columns: minmax(0, 1fr) auto; }

/* Hidden totals and no sidebar leaves the right column empty, but the grid gap
 * survives it and the round stops 1.75rem short of the stage edge it should
 * meet. Only this one combination is affected: SPIRIT hides the totals but keeps
 * the sidebar, so its column still has a width to line up with. */
body.is-blind:not(.is-live) .hud { gap: 0; }

.hud-side {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.1rem;
  min-width: 0;
}

.hud-right { justify-content: flex-end; }

/* The three controls sit together at the far left, away from the standings.
 * They are the screen's furniture, not its information — grouping them frees the
 * right-hand column for the money alone. */
.hud-tools { display: flex; align-items: center; gap: 1.1rem; }

/* Which round it is drives every judgement you make, so it is read at a glance
 * rather than hunted for. The one label in the game set in sentence case with a
 * numeral — "Round 3 of 10" is counted, not read. */
#hud-round {
  font-size: 1.05rem;
  letter-spacing: .1em;
  text-transform: none;
  color: var(--fg);
  white-space: nowrap;
}
/* What you hold and where it puts you — read as often as the round number, so
 * sized with it rather than under it. */
.hud-totals {
  display: flex;
  align-items: baseline;
  gap: .8rem;
  font-size: clamp(1rem, min(2.6vh, 4.4vw), 1.45rem);
  letter-spacing: .06em;
  color: var(--fg);
}
.hud-sep { color: var(--faint); }

/* Your own money is already in your row of the standings, so the HUD does not
 * repeat it — but only when that row is actually on screen. With the sidebar
 * turned off and the money left on, the HUD is the one place you can read your
 * own total, and hiding it there would take the figure away entirely. The
 * separator goes with it or it dangles in front of the rank. */
body.is-live #hud-total,
body.is-live .hud-sep { display: none; }
/* The rank trails the money rather than matching it: one is the figure, the
 * other is what the figure bought. */
#hud-rank { font-size: .82em; letter-spacing: .12em; color: var(--muted); }

/* QUIT is this screen's back button, so it is sized to be found, not hidden. */
.hud-btn {
  font: 400 clamp(.8rem, min(1.75vh, 3.1vw), 1.02rem)/1 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  padding: .2rem 0;
  border: 0;
  background: transparent;
  color: var(--faint);
  cursor: pointer;
  transition: color .2s var(--ease);
}

.hud-btn.is-armed { color: var(--reject); }
.hud-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

@media (hover: hover) { .hud-btn:hover { color: var(--fg); } }

/* The menu's panel hangs under its own button in the opposite corner, so each
 * panel opens from the control that owns it. */
/* Compound on purpose: `.config-panel` is defined after this and would
 * otherwise win on source order and drop it to the foot of the screen. */
/* Hangs under the gear, so the two read as one control. */
.config-panel.options-panel {
  position: fixed;
  top: max(3.4rem, calc(env(safe-area-inset-top) + 2.2rem));
  right: 1.25rem;
  left: auto;
  z-index: 6;
}

/* Rows that answer to a click, inside a panel of rows that mostly do not. */
.config-toggle {
  cursor: pointer;
  border-radius: 4px;
  margin: 0 -.4rem;
  padding-left: .4rem;
  padding-right: .4rem;
  transition: background .18s var(--ease);
}

@media (hover: hover) {
  .config-toggle:hover { background: rgba(242, 239, 226, .06); }
  .config-toggle:hover .config-key { color: var(--fg); }
}
.config-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* A row that leads somewhere reads as a destination, not a state: no gold, no
 * strike, and a chevron to say it goes. */
.config-action .config-val { color: var(--muted); }
.config-action .config-val::after { content: '\00a0\203A'; }

@media (hover: hover) {
  .config-action:hover .config-val { color: var(--fg); }
}

/* On is gold, because it is a live setting; off is struck through, matching how
 * the sound control has always shown itself. */
.config-toggle[aria-pressed="true"] .config-val { color: var(--gold); }
.config-toggle[aria-pressed="false"] .config-val {
  color: rgba(242, 239, 226, .2);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-skip-ink: none;
}

/* The name field, sized to sit in a panel row rather than a settings screen. */
.config-name { align-items: center; }

.config-input {
  width: 9.5rem;
  text-align: right;
  font: 400 inherit/1 var(--mono);
  font-size: .63rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  padding: .2rem 0;
}
.config-input:focus { outline: none; border-bottom-color: var(--gold); }
.config-input::placeholder { color: var(--faint); }

/* Separates what you can change from what this game already is. */
.config-rule {
  height: 1px;
  margin: .55rem 0;
  background: var(--line);
}

/* Anchored to the left edge because its trigger moved there — a panel that opens
 * on the far side of the screen from the button reads as unrelated to it. */
.config-panel {
  position: absolute;
  top: calc(100% + .6rem);
  left: 0;
  z-index: 5;
  min-width: 15rem;
  padding: .85rem 1rem;
  background: var(--bg-deep);
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  animation: pop .4s var(--ease) both;
}

.config-panel[hidden] { display: none; }

@keyframes pop {
  from { opacity: 0; transform: translateY(-5px); }
  to   { opacity: 1; transform: none; }
}

.config-row {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  padding: .28rem 0;
  font-size: .63rem;
  letter-spacing: .16em;
  text-transform: uppercase;
}

.config-key { color: var(--muted); }
.config-val { color: var(--fg); }

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

.game-body {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: 1.75rem;
}

/* The round is one choice, so it reads as one compact object in the middle of
 * the column rather than a page-height spread. */
.stage {
  position: relative;   /* anchors the REFUSED stamp */
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 1.5rem 0;
}

.stage > * { width: 100%; max-width: 48rem; }

/* The sentence. Replaces the old eyebrow — it says who you are facing and
 * what is at stake, in words rather than a label. */
.eyebrow {
  position: relative;   /* anchors the REFUSED stamp beside the line */
  font: 400 clamp(1.25rem, 2.6vw, 1.65rem)/1.45 var(--serif);
  text-align: center;
  color: rgba(242, 239, 226, .9);
  min-height: 2.9em;
}

.eyebrow .nm-hl { font-style: italic; color: var(--gold); }

.eyebrow.is-accept { color: var(--gold-bright); }
.eyebrow.is-reject { color: var(--reject); }

/* A refused line is terracotta throughout — the name is neither money nor you,
 * so it never keeps the gold here. */
.eyebrow.is-reject .nm-hl { color: inherit; }

/* Destruction reads on the figures themselves — but only once they have
 * actually run down to nothing. Driven by a class rather than by the sibling
 * selector it used to use, so the strike lands at the end of the count instead
 * of the instant the answer is known. */
.split.is-void .amount {
  opacity: .4;
  text-decoration: line-through;
  text-decoration-color: rgba(217, 105, 79, .7);
  animation: strike-out .34s var(--ease) both;
}

/* The half you just banked, landing. A transform and a glow only — nothing that
 * changes the figure's box, or the rule beneath it would shift as it plays. */
.amount.is-banked { animation: banked .5s var(--ease) both; }

@keyframes banked {
  0%   { transform: scale(1);    text-shadow: none; }
  35%  { transform: scale(1.05); text-shadow: 0 0 22px rgba(214, 178, 92, .55); }
  100% { transform: scale(1);    text-shadow: none; }
}

@keyframes strike-out {
  from { opacity: .85; transform: scale(1.03); }
  to   { opacity: .4;  transform: scale(1); }
}

/* While the pot is burning the figures take the colour of what is happening to
 * them; the strike arrives after. */
.eyebrow.is-reject ~ .split .amount { color: var(--reject); }

/* Both outcomes land as a stamp on the deal. It sits at the right end of the
 * block, level with the line — a result line is always short ("X said no.",
 * "X accepted your offer.") so the space beside it is free.
 *
 * They lean opposite ways, so which one landed reads before you have parsed
 * either the word or the colour. */
.eyebrow.is-result::after {
  position: absolute;
  top: -.5rem;
  right: 0;
  font: 500 1.4rem/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  border: 3px double currentColor;
  border-radius: 4px;
  padding: 11px 24px;
}

.eyebrow.is-reject::after {
  content: 'refused';
  color: var(--reject);
  transform: rotate(-7deg);
  animation: stamp-reject .26s var(--ease) both;
}

/* Gold, not green: it is the colour this game already uses for money kept and
 * for you, and the palette deliberately has no third accent. */
.eyebrow.is-accept::after {
  content: 'accepted';
  color: var(--gold);
  transform: rotate(6deg);
  animation: stamp-accept .26s var(--ease) both;
}

@keyframes stamp-reject {
  from { opacity: 0; transform: rotate(-14deg) scale(1.25); }
  to   { opacity: 1; transform: rotate(-7deg) scale(1); }
}

@keyframes stamp-accept {
  from { opacity: 0; transform: rotate(13deg) scale(1.25); }
  to   { opacity: 1; transform: rotate(6deg) scale(1); }
}

/* --------------------------------------------------------------- split -- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: start;
  gap: clamp(1rem, 4vw, 2.25rem);
  margin-top: .4rem;
}

.side { min-width: 0; text-align: center; }

/* The hairline between the two names. Deliberately faint — it separates the
 * two sides without competing with the gold rule below. */
.split-rule {
  align-self: center;
  width: 1px;
  height: 5.8rem;
  background: linear-gradient(to bottom, transparent,
              var(--line-strong) 22%, var(--line-strong) 78%, transparent);
}

.amount {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.2rem, 6.5vw, 3.95rem);
  line-height: 1.1;
  transition: color .35s var(--ease), opacity .35s var(--ease);
}

/* Gold is always the figure you receive, on both the propose and the answer
 * screen — the eye never has to re-learn where to look. The colour carries
 * that, so the two figures can stay the same size and sit level. */
.amount-input {
  display: block;
  width: 100%;
  text-align: center;
  color: var(--gold-bright);
  background: transparent;
  border: 0;
  border-bottom: 1px dashed rgba(240, 223, 168, .35);
  border-radius: 0;
  padding: 0 0 .08em;
  -webkit-appearance: none;
  appearance: none;
}

.amount-opp {
  color: rgba(242, 239, 226, .38);
  white-space: nowrap;
  padding-bottom: calc(.08em + 1px);   /* sits level with the input's underline */
}

.amount.is-zero { color: var(--dim); }

/* Read-only while you are the one answering, so the underline comes off. */
.amount-input:read-only { border-bottom-color: transparent !important; cursor: default; }

@media (hover: hover) {
  .amount-input:not(:read-only):hover { border-bottom-color: rgba(240, 223, 168, .6); }
}

.amount-input:not(:read-only):focus {
  outline: none;
  border-bottom-style: solid;
  border-bottom-color: var(--gold);
}

.amount-input::selection { background: rgba(214, 178, 92, .3); }

/* ----------------------------------------------------------------- bar -- */

.bar-wrap { position: relative; width: 100%; margin-top: 1.75rem; }

.bar { position: relative; height: 5px; background: var(--track); }

.bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 50%;
  background: var(--gold-grad);
  transition: width .28s var(--ease), background .5s var(--ease);
}

/* When the deal dies the gold drains out of the rule. */
.bar-fill.is-dead { background: rgba(217, 105, 79, .25); }

/* The tick at the seam is the drag handle, and doubles as the 2px gap
 * between the two halves of the rule. */
.bar-handle {
  position: absolute;
  top: -7px;
  bottom: -7px;
  left: 50%;
  width: 2px;
  background: var(--fg);
  transform: translateX(-50%);
  transition: left .28s var(--ease), opacity .2s var(--ease);
  pointer-events: none;
}

.bar-input {
  position: absolute;
  left: 0;
  width: 100%;
  height: 44px;
  top: 50%;
  transform: translateY(-50%);
  margin: 0;
  opacity: 0;
  cursor: ew-resize;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
}

.bar-input::-webkit-slider-thumb { -webkit-appearance: none; width: 28px; height: 44px; }
.bar-input::-moz-range-thumb { width: 28px; height: 44px; border: 0; }
.bar-input:active { cursor: ew-resize; }

.bar:has(.bar-input:focus-visible) .bar-handle {
  box-shadow: 0 0 0 2px var(--gold);
}

/* Locked while the opponent decides, and after the result. */
.bar-wrap.is-locked .bar-handle { opacity: 0; }
.bar-wrap.is-locked .bar-input { display: none; }
.bar-wrap.is-locked .ticks { opacity: 0; }

.ticks {
  position: relative;
  height: 4px;
  margin-top: 8px;
  transition: opacity .2s var(--ease);
}

.tick {
  position: absolute;
  top: 0;
  width: 1px;
  height: 4px;
  background: rgba(242, 239, 226, .12);
  transform: translateX(-50%);
}

.tick.is-on { background: var(--gold); }

/* --------------------------------------------------------- who and form -- */

.who {
  margin-top: .8rem;
  font: 400 .95rem/1 var(--mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* You are gold everywhere. */
.side:first-child .who { color: var(--gold); }

.holds {
  margin-top: .45rem;
  font: 400 .82rem/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dim);
  white-space: nowrap;
}

/* How this opponent has answered their last few offers. Hidden entirely when
 * the last-actions channel is off — the bots lose it at the same moment. */
/* Holds its height whether or not there is a record to show, so the figures
 * above sit at the same place on a propose round and an answer round. */
.form {
  position: relative;
  display: flex;
  gap: 13px;
  margin-top: .8rem;
  min-height: var(--mark-size);
  justify-content: center;
}

/* One shared label under the row rather than one per mark: centred on the whole
 * group it can never be clipped by the edge of a narrow screen, which a tooltip
 * hanging off the last mark always was. `data-tip` is set by ui.js for both
 * hover and tap. */
.form[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  padding: .5rem .7rem;
  font: 400 .72rem/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--fg);
  background: var(--bg-deep);
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  pointer-events: none;
}

/* Dim the rest so it is obvious which mark the label belongs to. */
.form[data-tip] .mark:not(.is-on) { opacity: .3; }

body:not(.is-form) .form { display: none; }

/* Running totals are an information channel: when they are off, they are off
 * everywhere, for you and for the table. */
body.is-blind .holds,
body.is-blind .hud-totals { display: none; }

/* One glyph per remembered decision. This is the only read you get on how an
 * opponent answers, so it is sized to be read, not decorated. Full gold rather
 * than the pale cream — it has to carry colour against the terracotta cross,
 * without introducing a third accent to the palette. */
.mark {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
  cursor: pointer;
  transition: opacity .18s var(--ease);
}

.mark-glyph { font-size: var(--mark-size); line-height: 1; }

/* Hidden where hovering already answers the question. It only earns its space
 * on touch, where reading the row would otherwise mean tapping five marks one
 * at a time — which nobody does mid-round. */
.mark-amt { display: none; }

.mark.is-yes { color: var(--gold); }
.mark.is-no  { color: var(--reject); }

/* -------------------------------------------------------------- result -- */

/* Everything below the rule reserves its full height whether it is filled or
 * not. A round resolving empties the buttons and fills the memo — without
 * these, the figures and the rule would jump every time you answered. */
.memo {
  margin-top: 1.35rem;
  font: 400 .78rem/1.9 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  text-align: center;
  color: var(--fg);
  min-height: 3.8em;          /* the two lines a refusal prints */
}

/* The answer to the round, dead centre and the loudest thing under the rule.
 * 500 is the heaviest weight DM Mono ships. */
.act-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
}

.stage .actions {
  justify-content: center;
  align-items: center;
  gap: 1.1rem;
  /* One button, whether or not one is showing. Must clear the tallest the
   * button can get, or the figures and the rule above shift between phases. */
  min-height: 3.7rem;
}

/* The three answers of the round, so they are set to be read at a glance rather
 * than at chrome size. Weight 500 is not a shortfall: DM Mono ships 300/400/500
 * and nothing heavier, so 700 would only get a synthesised faux-bold — the size
 * and the tightened tracking are what carry the weight instead. */
.stage .actions .btn {
  font-size: clamp(.92rem, min(2.1vh, 3.7vw), 1.18rem);
  font-weight: 500;
  letter-spacing: .16em;
  padding: 1.15rem 3rem;
}

.hint {
  font: 400 .7rem/1.9 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  text-align: center;
  color: var(--dim);
}

/* Only the first game shows the line, so only the first game reserves room. */
body.is-coaching .hint { min-height: 1.9em; }

.thinking {
  font: 400 .69rem/1 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--muted);
  animation: breathe 1.15s ease-in-out infinite;
}

@keyframes breathe { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }

/* ---------------------------------------------------------- live panel -- */

.live {
  position: relative;
  flex: 0 0 310px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Short top padding so the list gets the height. The rows carry their own
   * .7rem inset for the highlight fill, so this stops short of it. */
  padding: .9rem 0 .25rem 1.05rem;
  border-left: 1px solid var(--line);
}

body:not(.is-live) .live { display: none; }

.live-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: .5rem;
  padding: 0 .7rem 10px;   /* lines up with the row content below */
  font: 400 .76rem/1 var(--mono);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Sized on the title alone, not on .live-head, so the rank delta beside it keeps
 * the small label scale. Tighter tracking than the head's .22em because the word
 * is now long enough that the old spacing would run it into the delta. */
.live-title {
  font-size: clamp(1.05rem, min(2.75vh, 4.6vw), 1.5rem);
  letter-spacing: .14em;
  color: var(--fg);
}

.live-delta.is-up { color: var(--gold); }
.live-delta.is-down { color: var(--reject); }

/* Drawn on the panel rather than inside the scroller, which is masked and
 * would clip it. */
.role-tip {
  position: absolute;
  z-index: 6;
  transform: translate(-50%, -100%);
  padding: .5rem .7rem;
  font: 400 .7rem/1 var(--mono);
  letter-spacing: .12em;
  white-space: nowrap;
  color: var(--fg);
  background: var(--bg-deep);
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s var(--ease);
}

.role-tip.is-on { opacity: 1; }

/* -------------------------------------------------------------- boards -- */

.board {
  list-style: none;
  position: relative;   /* makes row offsetTop relative to the list itself */
  width: 100%;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
  overscroll-behavior: contain;
}

.board::-webkit-scrollbar { width: 3px; }
.board::-webkit-scrollbar-thumb { background: var(--line); border-radius: 99px; }

/* The fade only marks that the list scrolls. Kept shallow so a row that fits is
 * read, not half-dissolved. */
.board-live {
  flex: 1;
  min-height: 0;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 7px,
                      #000 calc(100% - 7px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 7px,
              #000 calc(100% - 7px), transparent 100%);
}

.row {
  display: grid;
  grid-template-columns: 2.1rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: .85rem;
  padding: 11px .7rem;
  font: 400 .95rem/1.3 var(--mono);
  color: rgba(242, 239, 226, .6);
  border-top: 1px solid var(--line);
}

.board-live .row { grid-template-columns: 22px 15px minmax(0, 1fr) auto; gap: 11px; }

.row .rk { font-size: .8rem; color: var(--dim); }
.row .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .amt { color: inherit; }

/* Proposing is the stronger position, so P reads louder than R. */
.role { font-size: .88rem; color: var(--fg); cursor: pointer; }
.role.is-receiving { opacity: .4; }

/* The two rows that matter this round are picked out by a fill and a bar down
 * the edge, not by text colour alone — at a glance you must be able to find
 * yourself and the player you are facing without reading a single name.
 *
 * Yours is gold; theirs is deliberately neutral and quieter, so the two never
 * compete and gold keeps meaning "you". */
.row.is-you,
.row.is-opponent { box-shadow: inset 3px 0 0 currentColor; }

.row.is-opponent {
  background: rgba(242, 239, 226, .07);
  color: rgba(242, 239, 226, .55);
}

.row.is-opponent .nm,
.row.is-opponent .amt { color: var(--fg); }
.row.is-opponent .rk { color: var(--muted); }

/* You are gold everywhere, and gold is never anything else. */
.row.is-you {
  background: rgba(214, 178, 92, .16);
  color: var(--gold);
}

.row.is-you .rk { color: rgba(214, 178, 92, .75); }
.row.is-you .nm,
.row.is-you .amt { color: var(--gold-bright); }

.row.is-you .role { color: var(--gold-bright); }
.row.is-you .role.is-receiving { opacity: .65; }

.board:not(.board-live) .row.is-you .rk,
.board:not(.board-live) .row.is-you .amt { color: var(--gold-bright); }

.board:not(.board-live) .row { padding: 11px .8rem; }

/* The table recedes as it goes down; you and this round's opponent never do. */
.row:nth-child(n+8):not(.is-you):not(.is-opponent)  { color: rgba(242, 239, 226, .44); }
.row:nth-child(n+14):not(.is-you):not(.is-opponent) { color: rgba(242, 239, 226, .28); }

body.is-blind .board-live .amt { display: none; }

.board-live .row.is-you.is-moved { animation: rowpulse .7s var(--ease); }

/* Ends on the row's resting fill, so a climb flares and settles rather than
 * snapping back to a different colour. */
@keyframes rowpulse {
  from { background: rgba(214, 178, 92, .46); }
  to   { background: rgba(214, 178, 92, .16); }
}

/* --------------------------------------------------------------- final -- */

.final {
  margin: auto;
  width: 100%;
  max-width: 66rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 370px;
  align-items: center;
  gap: 3.5rem;
  padding: 1.25rem 0;
}

.final-left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .55rem;
}

.final-score {
  margin-top: .9rem;
  font: 400 clamp(3.4rem, 9vw, 5.6rem)/1 var(--serif);
  color: var(--gold-bright);
}

.emblem-final { width: 370px; max-width: 100%; margin: .5rem 0 1rem; }

.final-rank { font: 400 1.95rem/1.35 var(--serif); color: var(--fg); }
.final-beat { font: 400 1.35rem/1.4 var(--serif); color: var(--muted); }

.final-record {
  margin-top: .6rem;
  font: 400 .75rem/1.6 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold);
}

.final-record[hidden] { display: none; }

.final-left .actions { margin-top: 1.75rem; gap: 1.1rem; }

.final-left .actions .btn {
  font-size: .84rem;
  font-weight: 500;
  letter-spacing: .2em;
  padding: 1.15rem 3rem;
}

/* ------------------------------------------------------------- podium -- */

.final-right { min-width: 0; display: flex; flex-direction: column; }

/* Second, first, third — in that order in the markup, so they read as a
 * podium rather than a list. Height carries the placing, which leaves gold
 * free to keep meaning "you": a medal palette would have been a third accent
 * and would have put gold on someone else's block. */
.podium {
  list-style: none;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: .45rem;
  margin-bottom: 1.1rem;
}

.pod {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: pod-rise .5s var(--ease) both;
}

.pod-2 { animation-delay: .05s; }
.pod-1 { animation-delay: .15s; }
.pod-3 { animation-delay: .25s; }

.pod-name {
  max-width: 100%;
  font: 400 clamp(.72rem, 1.75vh, .95rem)/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(242, 239, 226, .65);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pod-score {
  margin: .4rem 0 .55rem;
  font: 400 clamp(.95rem, 2.2vh, 1.3rem)/1 var(--serif);
  color: rgba(242, 239, 226, .5);
  white-space: nowrap;
}

.pod-block {
  width: 100%;
  border-radius: 5px 5px 0 0;
  background: rgba(242, 239, 226, .10);
  border-top: 3px solid rgba(242, 239, 226, .22);
  display: flex;
  justify-content: center;
  padding-top: .5rem;
  font: 400 clamp(1.3rem, 3.2vh, 2rem)/1 var(--serif);
  color: rgba(242, 239, 226, .5);
}

.pod-1 .pod-block { height: clamp(4rem, 11vh, 7rem); background: rgba(242, 239, 226, .15); }
.pod-2 .pod-block { height: clamp(2.8rem, 7.5vh, 4.8rem); }
.pod-3 .pod-block { height: clamp(2rem, 5.2vh, 3.4rem); }

/* You are gold here exactly as you are everywhere else. */
.pod.is-you .pod-name { color: var(--gold); }
.pod.is-you .pod-score { color: var(--gold-bright); }
.pod.is-you .pod-block {
  background: rgba(214, 178, 92, .20);
  border-top-color: var(--gold);
  color: var(--gold-bright);
}

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

/* Decoration only, and never over the buttons. */
.confetti {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 3;
}

/* Tall enough to read the table rather than peek at it, less what the podium
 * above it now takes. */
.final .board {
  min-height: 0;
  max-height: min(56vh, 28rem);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* -------------------------------------------------------------- motion -- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* --------------------------------------------------------------- touch -- */

/* A finger needs a target a cursor does not. These only grow the hit area —
 * nothing here changes the layout on a pointer device. */
@media (pointer: coarse), (max-width: 560px) {
  /* The figure under every mark, on both sides. `--mark-amt-line` is added to
   * the row's reservation so turning the figures on cannot shift the money and
   * the rule above them. */
  .mark-amt {
    display: block;
    margin-top: .3rem;
    font: 400 .62rem/1 var(--mono);
    letter-spacing: .06em;
    color: var(--muted);
    white-space: nowrap;
  }
  .form { min-height: calc(var(--mark-size) + 1.05rem); }
  /* Tighter, since each mark is now two lines wide-ish rather than one glyph. */
  .form { gap: 10px; }

  .choice-btn { padding: 1rem 1.15rem; }
  .mode-opts-sub .mode-btn { padding: 15px 18px; }
  .switch { padding: .7rem 0; }
  .name-input { padding: .55rem 0; }
  .hud-btn { padding: .35rem 0; }

  /* The role letter is only a glyph wide, so it gets an invisible pad. */
  .role { position: relative; }
  .role::before { content: ''; position: absolute; inset: -12px -9px; }
}

/* ---------------------------------------------------------- responsive -- */

/* Below this width the standings drop under the decision instead of beside it. */
@media (max-width: 880px) {
  .game-body { flex-direction: column; gap: .75rem; }
  .live {
    flex: 0 0 auto;
    max-height: 30vh;
    padding: 0;
    border-left: 0;
    border-top: 1px solid var(--line);
  }
  .live-head { padding-top: .6rem; }
  .stage { padding: .75rem 0; }

  /* Stacked, the standings used to sit in a 30vh box with their own scroller,
   * so most of the table was unreachable unless a thumb landed inside it. The
   * whole screen scrolls instead and the board renders at full height: one
   * ordinary swipe, no nested scrolling to find. */
  #screen-game.is-active { overflow-y: auto; }
  .game-body { flex: 0 0 auto; }
  .stage { flex: 0 0 auto; }
  .live { max-height: none; }
  .board-live {
    flex: none;
    min-height: 0;
    overflow: visible;
    -webkit-mask-image: none;
            mask-image: none;
  }
  /* Standings sit under the stage now, so there is no column to align to. */
  .hud { display: flex; justify-content: space-between; gap: 1rem; }
  #hud-round { font-size: .95rem; }
  /* No room beside the block for a stamp once the column is this narrow. */
  .eyebrow.is-result::after { display: none; }

  .opt-groups { grid-template-columns: 1fr; gap: 1.8rem; }

  .final {
    grid-template-columns: minmax(0, 1fr);
    max-width: 32rem;
    gap: 1.75rem;
  }
  .emblem-final { width: 100%; }
  .final .board { max-height: min(40vh, 20rem); }
  .final-rank { font-size: 1.55rem; }
  .final-beat { font-size: 1.15rem; }
}

/* Three squares across stop being readable well before the sidebar breakpoint. */
@media (max-width: 760px) {
  .steps {
    grid-template-columns: minmax(0, 1fr);
    max-width: 22rem;
    gap: 2.25rem;
    padding-top: 2.75rem;
  }

  /* Stacked, each panel has the full column to itself, so the type stops being
   * sized for a third of the width and reads at its proper size. Scoped here
   * rather than in the shared ramp, which the rules and rankings also use. */
  .step h2 {
    font-size: clamp(.85rem, 4vw, 1.1rem);
    letter-spacing: .18em;
    margin-bottom: clamp(.7rem, 2.6vw, 1rem);
  }
  /* The caption keeps the shared body size; only the title was too small. */
}

@media (max-width: 560px) {
  /* Three modes will not sit side by side in this width, so they stack. */
  .mode-opts { grid-auto-flow: row; grid-template-columns: minmax(0, 1fr); }

  /* A label beside its options no longer fits, so it goes above them, and the
   * preset row folds to two-by-two rather than running off the edge. */
  .choice { flex-wrap: wrap; gap: .45rem .9rem; }
  .choice-label { flex: 0 0 100%; }
  .choice-opts { flex-wrap: wrap; }

  /* The picker rows are a grid, not flex, so they stack by collapsing to one
   * column rather than by wrapping. */
  .opt-group-rows { grid-template-columns: minmax(0, 1fr); row-gap: .45rem; }
  .opt-group-rows .choice + .choice .choice-label { margin-top: .6rem; }
  .mode-opts-sub {
    width: 100%;
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .opt-line { gap: .8rem; }
  .opt-groups { gap: 1.5rem; }

  .act-row { gap: .85rem; }
  .stage .actions .btn { padding: .9rem 1.8rem; font-size: .88rem; }
  .final-left .actions .btn { padding: .9rem 1.8rem; font-size: .76rem; }
  .split-rule { height: 3.4rem; }
  .who { font-size: .78rem; }
  .holds { font-size: .7rem; }

  /* Too little width for one row: quit + round on top, the score below.
   * The round keeps its size — it is the thing being made easier to read. */
  .hud { flex-wrap: wrap; row-gap: .55rem; }
  .hud-side { flex: 1 1 100%; }
  #hud-round { font-size: .9rem; letter-spacing: .12em; }
  :root { --mark-size: 27px; }
  .form { gap: 11px; }
  .row { font-size: .84rem; }
}

/* Short windows: give the height back to the figures rather than the padding. */
@media (max-height: 700px) {
  /* The reservation stays. It was zeroed here to reclaim height, but the round
   * sentence is two lines and every result sentence is one, so without it the
   * figures and the rule jump up by half the difference the instant an answer
   * lands — on exactly the short windows an embedded player uses. The margin
   * below is what gives the height back instead. */
  .eyebrow { margin-bottom: .5rem; }
  .memo { margin-top: .9rem; }
  .split-rule { height: 4.6rem; }
  .stage .actions .btn,
  .final-left .actions .btn { padding: .95rem 2.4rem; }
  .final-score { margin-top: .4rem; }
  .emblem-final { margin: .35rem 0 .7rem; }
  .final-left .actions { margin-top: 1.1rem; }
}

@media (max-height: 620px) {
  .amount { font-size: clamp(1.9rem, 5.4vw, 2.9rem); }
  .holds { display: none; }
  :root { --mark-size: 26px; }
  .form { margin-top: .5rem; }
  .btn { padding: .8rem 1.5rem; }
  .btn-lead { padding: .9rem 3rem; }
  .stage .actions .btn,
  .final-left .actions .btn { padding: .85rem 2.1rem; }
  /* Vertical only. The shorthand used to zero the sides too, which took away
   * the .7rem the highlight fill and its bar are meant to sit in — on a short
   * window (an embedded player is often 600px or less) the gold ran flush into
   * the rank and the amount, and the row read as cramped. */
  .row { padding-top: 8px; padding-bottom: 8px; }
}
