/* ==========================================================================
   HOST — styles for the map, colour, write/vote, showdown and intermission
   rounds. Loaded after host.css, which defines the palette variables.
   ========================================================================== */

/* A class that sets `display` outranks the UA stylesheet's [hidden] rule, so
   an element like .tap-stage (display:grid) stays visible when hidden is set.
   This puts the attribute back in charge everywhere. */
[hidden] { display: none !important; }

/* ---- showdown ----------------------------------------------------------- */

.showdown-vs, .tap-duel {
  display: flex;
  align-items: center;
  gap: 1.4vw;
  font-size: clamp(1.2rem, 3vw, 3rem);
  font-weight: 900;
}
.showdown-vs span, .tap-duel span {
  background: var(--surface);
  border: 3px solid var(--pink);
  border-radius: 14px;
  padding: .4em 1em;
}
.showdown-vs em, .tap-duel em {
  color: var(--gold);
  font-style: normal;
  font-size: .7em;
}
.tap-duel { margin-top: 3vh; justify-content: center; }
.tap-stage.go .tap-duel span {
  border-color: #05291a;
  color: #05291a;
  background: rgba(255,255,255,.25);
}

/* ---- world map ---------------------------------------------------------- */

.worldmap {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: 14px;
  overflow: hidden;
}
/* The map palette.

   The sea stays recognisably sea - a warm-brown ocean reads as a coffee
   stain, not a map - but it is pulled onto the cool hue the rest of the app
   already uses for "the thing being looked at", so it belongs here rather
   than looking like a screenshot from another product. Land is warm charcoal
   against it, which is a normal cartographic pairing and keeps the coastline
   crisp.

   The graticule is deliberately near-invisible. At its old weight it read as
   lines scattered over the map rather than as a grid you consult, which on a
   television is just noise. */
.wm-sea { fill: #0f1a1d; }
/* One path per country, so the strokes ARE the borders. Non-scaling keeps them
   hairline-thin at every zoom instead of turning into fat bands. */
.wm-land path {
  fill: #2b241e;
  stroke: #4d4036;
  stroke-width: .7;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.wm-grid line {
  stroke: rgba(255, 240, 220, .035);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
/* Same pin as the phone, sized in its own space - the JS keeps it a constant
   size on screen however far the map is zoomed. */
.wm-pin-body {
  stroke: #fff;
  stroke-width: 1.6;
  stroke-linejoin: round;
}
.wm-pin-hole { fill: #fff; }
.wm-pin-me    .wm-pin-body { fill: var(--pink); }
.wm-pin-other .wm-pin-body { fill: #cbbdae; }
.wm-pin-best  .wm-pin-body { fill: var(--green); }
.wm-pin { filter: drop-shadow(0 1px 3px rgba(0,0,0,.7)); }
.wm-ring { fill: none; stroke: var(--gold); stroke-width: 2; }
.wm-equator { stroke: rgba(255, 240, 220, .07) !important; }
/* The answer marker pulses so the eye finds it first among the guesses.
   No non-scaling-stroke here: the whole marker is now counter-scaled in JS,
   so its stroke should scale with it or the outline would fatten as you
   zoom out. */
.wm-halo {
  fill: rgba(208, 154, 60,.2);
  stroke: var(--gold);
  stroke-width: 1.5;
  animation: haloPulse 1.2s ease-in-out infinite;
}
@keyframes haloPulse {
  0%, 100% { r: 7; opacity: 1; }
  50%      { r: 11; opacity: .35; }
}
.wm-x { stroke: var(--gold); stroke-width: 2.4; stroke-linecap: round; }
.wm-link {
  stroke: rgba(208, 154, 60,.35);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
}
.wm-pin-label {
  fill: #fff;
  font-size: 9px;
  font-weight: 800;
  paint-order: stroke;
  stroke: #0d0b0a;
  stroke-width: 3;
}

.geo-stage {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  gap: 2vw;
  width: 92%;
  align-items: center;
}
.geo-clues { display: flex; flex-direction: column; gap: 1.4vh; }
.clue {
  background: var(--surface);
  border-left: 6px solid var(--blue);
  border-radius: 8px;
  padding: .8em 1em;
  font-size: clamp(.95rem, 1.7vw, 1.6rem);
  font-weight: 700;
  opacity: 0;
  animation: clueIn .5s ease forwards;
}
@keyframes clueIn {
  from { opacity: 0; transform: translateX(-20px); }
  to   { opacity: 1; transform: none; }
}
.geo-map { aspect-ratio: var(--wm-aspect, 1.705); }

/* Sized off HEIGHT, not width - a 2:1 map at 70% of a 16:9 screen's width
   eats ~62% of its height and pushes the punishment list off the bottom. */
.geo-reveal {
  height: clamp(160px, 30vh, 340px);
  width: auto;
  aspect-ratio: var(--wm-aspect, 1.705);
  margin: 0 auto 1vh;
}
.geo-best {
  font-size: clamp(.9rem, 1.6vw, 1.5rem);
  color: var(--muted);
  margin-bottom: 1vh;
}
.geo-best b { color: var(--gold); }

/* ---- colour match ------------------------------------------------------- */

.color-stage { display: flex; flex-direction: column; align-items: center; gap: 2vh; }
.color-shape { width: clamp(240px, 38vh, 460px); aspect-ratio: 1; }
.shape { width: 100%; height: 100%; }
.shape-body {
  fill: var(--shape-fill);
  stroke: #f8f1e7;
  stroke-width: 2.5;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.shape.hollow .shape-body {
  fill: rgba(255,255,255,.04);
  stroke-width: 3;
  stroke-dasharray: 8 6;
  vector-effect: non-scaling-stroke;
}
.shape-img { width: 100%; height: 100%; object-fit: contain; }
.color-hint { color: var(--muted); font-size: clamp(.9rem, 1.5vw, 1.4rem); }

.color-reveal {
  display: flex;
  gap: 3vw;
  align-items: center;
  justify-content: center;
  margin-bottom: 2vh;
}
.cr-target {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .6vh;
  width: clamp(110px, 15vh, 190px);
}
.cr-target span {
  color: var(--muted);
  font-size: .8rem;
  letter-spacing: .15em;
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
}
.cr-target-chip {
  width: 70%;
  height: 1.6vh;
  min-height: 10px;
  border-radius: 999px;
  border: 2px solid #fff3;
}
.cr-guesses { display: flex; flex-direction: column; gap: .7vh; }
.cr-guess {
  display: flex;
  align-items: center;
  gap: .8em;
  font-size: clamp(.85rem, 1.4vw, 1.3rem);
  font-weight: 700;
}
.cr-swatch { width: 2.2em; height: 2.2em; border-radius: 8px; border: 2px solid #fff3; }
/* deltaE, not degrees. The number alone means nothing to a room full of
   people, so the colour of it does the talking. */
.cr-guess b {
  font-size: .8em;
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.cr-guess.spot  b { color: var(--green); }
.cr-guess.close b { color: var(--gold); }
.cr-guess.off   b { color: var(--muted); }
.cr-guess.miss  b { color: var(--pink); }
.cr-guess.spot  .cr-swatch { border-color: var(--green); }

/* ==========================================================================
   GEO REVEAL — the map is the point, so it gets the room
   On any landscape TV the map sits beside the drink list instead of being
   squeezed above it. That takes it from ~26vh tall to nearly the full height.
   ========================================================================== */

@media (min-width: 900px) and (min-aspect-ratio: 5/4) {
  #s-reveal.active[data-round="geo"] {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "head head"
      "map  list"
      "award award";
    column-gap: 3vw;
    align-items: center;
  }
  #s-reveal.active[data-round="geo"] .reveal-head   { grid-area: head; }
  #s-reveal.active[data-round="geo"] .reveal-extra  { grid-area: map; max-height: none; width: 100%; }
  #s-reveal.active[data-round="geo"] .reveal-body   { grid-area: list; min-height: 0; }
  #s-reveal.active[data-round="geo"] .award-banner  { grid-area: award; justify-self: center; }

  /* The projection is stretched rather than letterboxed. preserveAspectRatio
     is "none" and every pin is placed in viewBox units, so distorting it costs
     nothing and buys a much taller map - which is the whole point of this
     layout. 1.7:1 against a true 2:1 is a gentle 1.18x stretch; the TV has the
     width to afford being closer to correct than the phone can be. */
  #s-reveal.active[data-round="geo"] .reveal-extra { justify-content: center; height: 100%; }
  #s-reveal.active[data-round="geo"] .geo-reveal {
    width: 100%;
    height: auto;
    aspect-ratio: var(--wm-aspect, 1.705);
    max-height: 72vh;
    margin: 0;
  }
  /* Beside the map the list is narrow, so it stays one column and keeps the
     distance that explains why each person is drinking. */
  #s-reveal.active[data-round="geo"] .punish-list.two-col,
  #s-reveal.active[data-round="geo"] .punish-list.three-col {
    grid-template-columns: 1fr;
    width: 100%;
  }
  #s-reveal.active[data-round="geo"] .punish-list.three-col .preason { display: block; font-size: .7em; }
}

/* Pins have to be picked out from ten feet away, so they are bigger here than
   on a phone and the closest guess is marked rather than merely listed. */
/* Names beside the pins on the TV, readable from a sofa. Sized in the pin's
   own space so they scale with it rather than against it. */
#revealMap .wm-pin-label { font-size: 10px; }
#revealMap .wm-pin-best .wm-pin-label { fill: var(--green); }

/* ---- write / vote ------------------------------------------------------- */

.write-label {
  color: var(--muted);
  letter-spacing: .22em;
  font-size: clamp(.75rem, 1.2vw, 1.1rem);
  font-weight: 800;
}
.question-text.big { font-size: clamp(1.8rem, 5vw, 5rem); }

.typing-list { list-style: none; display: flex; flex-wrap: wrap; gap: .8vw; justify-content: center; }
.typing-list li {
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: 999px;
  padding: .5em 1.2em;
  font-size: clamp(.85rem, 1.4vw, 1.3rem);
  font-weight: 700;
  color: var(--muted);
}
.typing-list li.done { border-color: var(--green); color: var(--text); }

/* Column count is measured, not auto-fit: auto-fit picks columns from width
   alone and happily produces more rows than there is height for. */
.vote-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr));
  gap: 12px 16px;
  width: 88%;
  flex: 1;
  min-height: 0;
  align-content: center;
  justify-content: center;
  overflow: hidden;
}
.vote-grid .vote-card {
  /* The fitted HEIGHT. --tile is the fitted width and is only the same thing
     on a square tile. */
  height: var(--tile-h, var(--tile, auto));
  display: flex;
  align-items: center;
  justify-content: center;
}
.vote-card {
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--lift-1);
  padding: 1em 1.2em;
  font-size: clamp(1rem, 1.9vw, 1.8rem);
  font-weight: 700;
  text-align: center;
  animation: pop .25s ease backwards;
}
.vote-card.name-only { border-color: var(--purple); }

.spotlight-quote {
  background: linear-gradient(160deg, #2a1f3d, var(--surface));
  border: 3px solid var(--purple);
  border-radius: 22px;
  padding: 1em 2em;
  font-size: clamp(1.3rem, 3.2vw, 3rem);
  font-weight: 800;
  font-style: italic;
  max-width: 80%;
}
.spotlight-quote.small { font-size: clamp(1rem, 2vw, 1.8rem); margin: 0 auto 2vh; }

/* ---- reveal panels ------------------------------------------------------ */

/* The reveal panels must never crowd out the punishment list underneath.
   The panel is capped and shrinkable; the list below is guaranteed a floor. */
/* The panel takes the leftover height rather than sizing to its content.
   That matters because the grids inside are measured: content-sized, the
   panel collapsed to a couple of hundred pixels, the tiles were measured
   against that, and eight drawings ended up 81px wide with half the screen
   empty underneath. Given a real share, the measurement has something true to
   work with. */
.reveal-extra {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1 1 0;
  min-height: 0;
  max-height: 56vh;
  width: 100%;
  overflow: hidden;
}
/* The drink list takes what it needs; whatever is left is the panel's. */
#s-reveal .reveal-body { flex: 0 1 auto; min-height: 0; }
#s-reveal .punish-list { flex: 1; min-height: 0; }

/* Big-group layouts. Everyone who is drinking has to be readable at a glance
   from across the room - never scrolled out of sight. */
.punish-list.two-col,
.punish-list.three-col {
  display: grid;
  align-content: start;
  gap: .8vh 1.2vw;
  width: 94%;
}
.punish-list.two-col   { grid-template-columns: 1fr 1fr; }
.punish-list.three-col { grid-template-columns: 1fr 1fr 1fr; }

.punish-list.two-col li,
.punish-list.three-col li {
  font-size: clamp(.8rem, 1.25vw, 1.25rem);
  padding: .5em .9em;
  gap: .6em;
}
.punish-list.two-col .preason { font-size: .65em; }
.punish-list.three-col .preason { display: none; }
.punish-list.three-col li {
  font-size: clamp(.72rem, 1.05vw, 1.05rem);
  padding: .4em .7em;
  border-left-width: 5px;
}

/* Same problem on the colour reveal - eight guesses in one column overflows.
   Two columns, and the rows themselves shrink so a full room still fits inside
   the panel's height cap instead of being cut off at the fourth name. */
.cr-guesses.many {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-flow: column;
  grid-template-rows: repeat(4, auto);
  gap: .5vh 1.4vw;
}
.cr-guesses.many .cr-guess { font-size: clamp(.75rem, 1.15vw, 1.1rem); }
.cr-guesses.many .cr-swatch { width: 1.9em; height: 1.9em; }

/* When a reveal panel is present the rows get a size down so a full table of
   punished players still fits without scrolling. */
#s-reveal .reveal-extra:not(:empty) ~ .reveal-body .punish-list li {
  font-size: clamp(.9rem, 1.5vw, 1.4rem);
  padding: .55em 1.1em;
}
.reveal-opts { width: 74%; margin-bottom: 2vh; }

.never-split { display: flex; gap: 3vw; margin-bottom: 2vh; }
.ns-side {
  background: var(--surface);
  border: 3px solid var(--line);
  border-radius: 22px;
  padding: 1em 2.4em;
  text-align: center;
}
.ns-side b { display: block; font-size: clamp(2rem, 5vw, 4rem); font-weight: 900; }
.ns-side span { color: var(--muted); font-size: .85rem; letter-spacing: .15em; }
.ns-side.guilty { border-color: var(--pink); }
.ns-side.guilty b { color: var(--pink); }

.tally-list {
  list-style: none;
  width: 60%;
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 1.5vh;
  min-height: 0;
}

/* Lists that fit rather than scroll. --row-h and --row-font are measured in
   JS from the space actually available, because a list you have to scroll on
   a TV is a list whose bottom entries may as well not exist - and on a reveal
   those entries are people finding out that they are drinking. */
.fit-list {
  overflow: hidden;
}
.fit-list > li {
  height: var(--row-h, auto);
  min-height: 0;
  font-size: var(--row-font, 1rem);
  padding-block: 0;
  align-items: center;
}
.tally-list li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--surface);
  border-radius: 8px;
  padding: .55em 1.1em;
  font-size: clamp(.9rem, 1.5vw, 1.4rem);
  font-weight: 700;
}
.tally-list li b { color: var(--gold); }
.tally-list li.right { border-left: 5px solid var(--green); }
.tally-list li.wrong { border-left: 5px solid var(--pink); }

.quip-results {
  list-style: none;
  min-height: 0;
  width: 78%;
  display: flex;
  flex-direction: column;
  gap: .8vh;
  margin-bottom: 2vh;
}
/* A results row is a list entry, not a card. Recessing them groups eight rows
   into one object instead of scattering eight floating rectangles. */
.quip-results li {
  display: flex;
  align-items: center;
  gap: 1em;
  background: var(--sunken);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  padding: .7em 1.2em;
  font-size: clamp(.9rem, 1.6vw, 1.5rem);
}
.quip-results li.best {
  border-color: var(--prize);
  background: linear-gradient(90deg, rgba(208, 154, 60, .16), var(--sunken) 62%);
}
.quip-results .qt { flex: 1; font-style: italic; }
.quip-results .qn { color: var(--muted); font-weight: 800; font-size: .8em; }
.quip-results .qv {
  background: var(--gold);
  color: #3a2c00;
  border-radius: 999px;
  padding: .15em .8em;
  font-weight: 900;
  font-size: .8em;
}

/* ---- intermission ------------------------------------------------------- */

.ad-stack { gap: 1.2vh !important; }
.ad-label {
  color: var(--muted);
  letter-spacing: .3em;
  font-size: clamp(.7rem, 1.1vw, 1rem);
  font-weight: 800;
}
/* The fake advert. It is meant to look like it wandered in from another
   product, so it gets the cool hue and the widest setting in the family -
   the only place on the TV that looks like branding rather than a game. */
.ad-brand {
  font-family: var(--font-display);
  font-size: clamp(3rem, 12vw, 12rem);
  font-weight: 900;
  font-stretch: 118%;
  letter-spacing: -.045em;
  line-height: .9;
  color: var(--focus);
  animation: slam .4s cubic-bezier(.2,1.4,.4,1);
}
.ad-tag { font-size: clamp(1.1rem, 2.6vw, 2.4rem); font-weight: 800; }
.ad-body { color: var(--muted); font-size: clamp(.9rem, 1.6vw, 1.5rem); max-width: 60%; }
.ad-timer {
  width: 40vw;
  height: 6px;
  background: var(--surface);
  border-radius: 999px;
  overflow: hidden;
  margin-top: 1vh;
}
.ad-timer-fill { height: 100%; width: 100%; background: var(--blue); }

.challenge-name {
  font-size: clamp(2rem, 6vw, 6rem);
  font-weight: 900;
  color: var(--gold);
  animation: slam .4s cubic-bezier(.2,1.4,.4,1);
}
.challenge-text {
  font-size: clamp(1.1rem, 2.8vw, 2.6rem);
  font-weight: 800;
  max-width: 70%;
  line-height: 1.3;
}

@media (max-width: 900px) {
  .geo-stage { grid-template-columns: 1fr; }
  .geo-reveal, .tally-list, .quip-results, .vote-grid { width: 96%; }
  /* The colour reveal deliberately stays a row here. Stacking it pushed the
     guess list past the panel's height cap, which silently clipped everyone
     below the fourth name - the one thing this screen must never do. */
  .cr-target { width: clamp(90px, 12vh, 140px); }
}

/* Shorter screens (720p TVs, a non-fullscreen browser window). The reveal
   screen is the tightest layout in the game - with 8 players the drink list
   is long AND there is a panel above it. Everything else gives up room so the
   list stays complete: nobody may be scrolled out of sight. */
@media (max-height: 820px) {
  #s-reveal .reveal-head { margin-bottom: .5vh; }
  #s-reveal .reveal-answer { font-size: clamp(1.05rem, 2.3vw, 2rem); }
  #s-reveal .winner-line { font-size: clamp(.85rem, 1.5vw, 1.3rem); }
  #s-reveal .punish-title { font-size: clamp(1rem, 2vw, 1.8rem); margin-bottom: .8vh; }

  /* No height cap here any more. The panel's contents are measured against
     the space it actually gets, so capping it just wastes screen - this rule
     was pinning eight drawings to 81px while a third of the TV sat empty. */
  .reveal-opts { margin-bottom: .8vh; }
  .reveal-opts .option {
    padding: .5em .8em;
    font-size: clamp(.78rem, 1.35vw, 1.15rem);
  }
  .reveal-opts .option .letter { width: 1.5em; height: 1.5em; }
  .geo-reveal { height: clamp(120px, 22vh, 240px); }

  /* Likewise: the drink list takes what it needs and no more. */

  .award-banner {
    padding: .5em 1.1em;
    font-size: clamp(.78rem, 1.3vw, 1.1rem);
    margin-top: .8vh;
  }
  #s-reveal .btn-big { padding: .55em 1.8em; font-size: clamp(.95rem, 1.6vw, 1.4rem); }
  #s-reveal .next-btn { margin-top: .5vh; }
}
/* A quiet aside under the water round. Deliberately small and low-contrast:
   it is a suggestion, not an instruction, and the point of this screen is the
   glass of water. */
.water-note {
  margin-top: 1.6vh;
  color: var(--muted);
  font-size: clamp(.8rem, 1.4vw, 1.25rem);
  font-weight: 600;
  opacity: .8;
}

/* --------------------------------------------------------------------------
   ODD ONE OUT (TV)

   The two questions are the joke. They have to sit next to each other, close
   enough to compare word for word, with the odd one marked - reading them one
   after another loses the "wait, that's almost the same" beat entirely.
   -------------------------------------------------------------------------- */
.odd-reveal {
  display: flex;
  flex-direction: column;
  gap: 1.4vh;
  width: 82%;
  min-height: 0;
  flex: 1;
}
.odd-prompts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.2vw;
}
.odd-prompts .op {
  background: var(--surface);
  border: 3px solid var(--line);
  border-radius: 16px;
  padding: .9em 1.2em;
  text-align: left;
}
.odd-prompts .op.odd { border-color: var(--gold); background: linear-gradient(160deg, #2e2513, var(--surface)); }
.odd-prompts .op-tag {
  display: block;
  font-size: clamp(.6rem, .95vw, .95rem);
  font-weight: 900;
  letter-spacing: .14em;
  color: var(--muted);
  margin-bottom: .35em;
}
.odd-prompts .op.odd .op-tag { color: var(--gold); }
.odd-prompts .op p {
  margin: 0;
  font-size: clamp(1rem, 1.8vw, 1.7rem);
  font-weight: 800;
  line-height: 1.2;
  text-wrap: balance;
}
.odd-prompts { flex: 0 0 auto; }
/* fitRows fits the rows to the box it is given, so the list has to be the
   child that takes whatever the two prompts above it left behind. */
.odd-reveal .quip-results { width: 100%; margin-bottom: 0; flex: 1 1 0; min-height: 0; }
/* The giveaway answer, marked after the fact. */
.quip-results li.odd {
  border: 2px solid var(--gold);
  background: linear-gradient(100deg, #2e2513, var(--surface));
}

.vote-card.accuse { flex-direction: column; gap: .3em; border-color: var(--purple); }
.vote-card.accuse .vs-name {
  font-size: 1.05em;
  font-weight: 900;
  color: var(--gold);
  letter-spacing: .02em;
}
.vote-card.accuse .vs-track {
  font-size: .9em;
  font-style: italic;
  line-height: 1.2;
  text-wrap: balance;
}

/* --------------------------------------------------------------------------
   THE CHAIN (TV)

   During the vote every story is on screen at once, which is the only time
   anybody sees a whole one - phones only ever showed a single line. So the
   cards are read top-down rather than centred, and the seed is set apart from
   the lines that answer it.
   -------------------------------------------------------------------------- */
.vote-grid.stories .vote-card.story {
  height: var(--tile-h, var(--tile, auto));
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: .35em;
  padding: .8em 1em;
  text-align: left;
  overflow: hidden;
}
/* Sized from the measured fit rather than from the viewport: six stories and
   three stories need very different type, and a vw-based clamp cannot know
   which it is looking at. */
.vote-grid.stories .vote-card.story { font-size: var(--story-font, 1rem); }
.vote-card.story .st-num {
  font-size: .62em;
  font-weight: 900;
  letter-spacing: .16em;
  color: var(--purple);
}
.vote-card.story .st-seed {
  margin: 0;
  font-size: .8em;
  font-style: italic;
  color: var(--muted);
  line-height: 1.25;
}
.vote-card.story .st-line {
  margin: 0;
  font-size: .82em;
  font-weight: 700;
  line-height: 1.25;
}

.chain-reveal {
  display: flex;
  flex-direction: column;
  gap: 1.2vh;
  width: 80%;
  min-height: 0;
  flex: 1;
}
.chain-win {
  background: linear-gradient(160deg, #2e2513, var(--surface));
  border: 3px solid var(--gold);
  border-radius: 18px;
  padding: 1em 1.4em;
  text-align: left;
}
.cw-seed {
  margin: 0 0 .5em;
  font-size: clamp(.9rem, 1.5vw, 1.4rem);
  font-style: italic;
  color: var(--muted);
  line-height: 1.25;
}
/* The name belongs to the line, not to the story, so it sits on the same row
   as the line it explains rather than in a caption underneath. */
.cw-line {
  margin: 0 0 .35em;
  display: flex;
  align-items: baseline;
  gap: .8em;
  font-size: clamp(1rem, 1.8vw, 1.7rem);
  font-weight: 800;
  line-height: 1.25;
}
.cw-line .cw-text { flex: 1; }
.cw-line .cw-who {
  flex: none;
  font-size: .62em;
  font-weight: 900;
  letter-spacing: .06em;
  color: var(--gold);
  white-space: nowrap;
}
.cw-votes {
  margin-top: .5em;
  font-size: clamp(.7rem, 1.1vw, 1.1rem);
  font-weight: 900;
  letter-spacing: .1em;
  color: var(--gold);
}
.chain-win { flex: 0 0 auto; }
.chain-rest {
  list-style: none;
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: .6vh;
  margin: 0;
  padding: 0;
}
.chain-rest li {
  display: flex;
  align-items: center;
  gap: 1em;
  background: var(--surface);
  border-radius: 12px;
  padding: .5em 1.1em;
  font-size: clamp(.8rem, 1.35vw, 1.3rem);
}
.chain-rest .qt { flex: 1; font-style: italic; color: var(--muted); text-align: left; }
.chain-rest .qv {
  background: var(--line);
  color: var(--text);
  border-radius: 999px;
  padding: .15em .8em;
  font-weight: 900;
  font-size: .85em;
}

/* Nobody voted. Still worth reading one out, but a gold winner's frame around
   a story that won nothing is a lie the screen tells. */
.chain-win.nowin { border-color: var(--line); background: var(--surface); }
.chain-win.nowin .cw-line .cw-who { color: var(--muted); }
.chain-win.nowin .cw-votes { color: var(--muted); }


/* --------------------------------------------------------------------------
   THE CHAIN, READ OUT

   One story at a time, filling the screen. This is the moment the round
   exists for, so nothing else is on screen competing with it - no ballot, no
   scores, no other stories.
   -------------------------------------------------------------------------- */
.read-stage {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.6vh;
  width: 82%;
  margin: 0 auto;
  text-align: center;
}
.read-num {
  font-family: var(--font-display);
  font-size: clamp(.7rem, 1.1vw, 1.05rem);
  font-weight: 700;
  letter-spacing: .3em;
  color: var(--focus);
}
/* The seed is set apart because nobody in the room wrote it - it is the
   prompt the story is answering, not part of the joke. */
.read-seed {
  font-size: clamp(.9rem, 1.7vw, 1.7rem);
  font-style: italic;
  line-height: 1.3;
  color: var(--muted);
  max-width: 34ch;
  text-wrap: balance;
}
.read-lines {
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2.4vh;
  width: 100%;
  font-size: var(--read-font, 2rem);
}
/* Each line was written blind by a different person, and that is the joke -
   so the seams have to be visible. Run together as one paragraph they read as
   a single voice, which is the one thing this round is not. */
.read-line {
  font-weight: 800;
  line-height: 1.22;
  text-wrap: balance;
  animation: readIn .32s var(--ease) backwards;
  position: relative;
}
.read-line + .read-line::before {
  content: "";
  position: absolute;
  top: -1.2vh;
  left: 50%;
  transform: translateX(-50%);
  width: 2.5em;
  height: 1px;
  background: var(--line);
}
.read-line:nth-child(2) { animation-delay: .07s; }
.read-line:nth-child(3) { animation-delay: .14s; }
.read-line:nth-child(4) { animation-delay: .21s; }
@keyframes readIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.read-hint {
  font-size: clamp(.7rem, 1.05vw, 1rem);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  opacity: .75;
}

.chain-rest li.more { justify-content: center; opacity: .55; }
.chain-rest li.more .qt { flex: none; font-style: normal; }
