/* The broadcast page: a 640×360pt canvas scaled to fill the screen (--pt is one point), built
   from the app's tokens (generated/tokens.css). The board follows the match screen's
   (Features/Match/MatchBoard.swift, DesignSystem/BoardFrame.swift, SplitFlap.swift). */

:root {
  --pt: min(100vw / var(--size-broadcast-canvas-width-n), 100vh / var(--size-broadcast-canvas-height-n));
  --flap: var(--size-broadcast-flap-scale-n);
  --edge: var(--size-board-edge);
}

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

html, body {
  height: 100%;
  overflow: hidden;
  background: var(--color-background);
  color: var(--color-text);
  -webkit-font-smoothing: antialiased;
  cursor: none;
}

[hidden] { display: none !important; }

.muted { color: var(--color-text-muted); }

#stage {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
}

.screen {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-screen-padding);
}

#reactions {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ── Pairing ─────────────────────────────────────────────────────────────────────────────────── */

#pair { gap: var(--space-xl); }

.code {
  flex: none;
  width: var(--size-broadcast-code);
  height: var(--size-broadcast-code);
  padding: var(--space-ms);
  /* Dark modules on light in both schemes: some scanners don't read an inverted code. */
  background: var(--color-code);
  border-radius: var(--radius-lg);
}

.code svg { display: block; width: 100%; height: 100%; }
.code path { fill: var(--color-on-code); }

.pair-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: calc(var(--pt) * 300);
}

#waiting {
  flex-direction: column;
  gap: var(--space-sm);
  text-align: center;
}

/* ── About to start (app.js PRE-START) ──────────────────────────────────────────────────────── */
#prestart {
  position: absolute;
  inset: 0;
  padding-left: calc(var(--space-screen-padding) + var(--size-icon-button) + var(--space-md));
}

#prestart.scaled { align-items: flex-start; }

.prestart-content { display: flex; align-items: center; gap: var(--space-xl); transform-origin: top center; }
.prestart-main { display: flex; flex-direction: column; gap: var(--space-lg); width: calc(var(--pt) * 360); }
.prestart-head { display: flex; flex-direction: column; gap: var(--space-xs); }
.prestart-people { display: flex; flex-direction: column; gap: var(--space-sm); }

.people { list-style: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-xs) var(--space-md); }
.person { display: flex; align-items: center; gap: var(--space-xs); min-width: 0; color: var(--color-text-muted); transition: color 300ms cubic-bezier(0.33, 1, 0.68, 1); }
.person .name { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.person .icon {
  width: var(--size-pill-icon);
  height: var(--size-pill-icon);
  fill: var(--color-success);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 300ms cubic-bezier(0.33, 1, 0.68, 1), transform 300ms cubic-bezier(0.34, 1.3, 0.64, 1);
}
.person.in { color: var(--color-text); }
.person.in .icon { opacity: 1; transform: none; }
/* Without check-in everyone listed is simply in, with no mark. */
.people.plain .person { color: var(--color-text); }
.people.plain .person .icon { display: none; }

.prestart-follow { display: flex; flex-direction: column; align-items: center; gap: var(--space-sm); text-align: center; }

/* ── Nothing live: the round, the latest results, the table ───────────────────────────────── */

/* Below the controls; app.js scales it down to fit when a long table makes it taller than the
   room left. */
#idle {
  position: absolute;
  inset: 0;
  /* Right of the rail (the icon above, the controls below). */
  padding-left: calc(var(--space-screen-padding) + var(--size-icon-button) + var(--space-md));
}

/* The two pages share one place, so one can fade over the other. */
#idle { display: grid; place-items: center; }
#idle.scaled { align-items: start; }

.idle-content {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  transform-origin: top center;
}

.idle-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  text-align: center;
}

.idle-head .meta { flex: none; }

.results, .tables, .standings, .round-cards { display: flex; flex-direction: column; gap: var(--space-md); }
.results { align-items: center; }
.results .cards { flex-direction: row; }
.results .card { width: calc(var(--pt) * 190); }
.tables { flex-direction: row; align-items: flex-start; gap: var(--space-xl); text-align: left; }
.round-cards .cards { display: grid; grid-template-columns: repeat(2, calc(var(--pt) * 200)); gap: var(--space-md); }
.cards { display: flex; flex-direction: column; gap: var(--space-md); }

/* ── A match card (Features/TournamentHome/MatchCard.swift on DesignSystem/BoardFrame.swift's card):
   a 2pt frame on a 2pt edge, the strip (status, then the group and round) on its panel-colored rim,
   and a row per side, the name and a compact split-flap tile. ─────────────────────────────────── */
.card {
  padding: var(--edge);
  background: var(--color-board-frame);
  border-radius: calc(var(--radius-lg) + var(--edge) * 2);
  box-shadow: 0 var(--size-board-shadow-offset) var(--size-board-shadow-blur) var(--color-board-shadow);
}

.card-edge {
  padding: var(--edge);
  background: var(--color-board-edge);
  border-radius: calc(var(--radius-lg) + var(--edge));
}

.card-inner { border-radius: var(--radius-lg); overflow: hidden; }

.card-rim { padding: var(--edge) var(--edge) 0; background: var(--color-board-panel); }

.card-strip {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-ms);
  background: var(--color-board-strip);
  border-radius: calc(var(--radius-lg) - var(--edge)) calc(var(--radius-lg) - var(--edge)) var(--radius-xs) var(--radius-xs);
}

.card-strip .card-meta { flex: 1; min-width: 0; color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-status { color: var(--color-text-muted); white-space: nowrap; }
.card-status.live { color: var(--color-live); }
/* The live dot before "En vivo", as the app's match status draws it. */
.card-status.live::before {
  content: "";
  display: inline-block;
  width: var(--size-live-dot);
  height: var(--size-live-dot);
  margin-right: var(--space-xs);
  border-radius: var(--radius-full);
  background: var(--color-live);
  vertical-align: middle;
  animation: pulse 800ms ease-in-out infinite alternate;
}

.card-sides { display: flex; flex-direction: column; gap: var(--edge); background: var(--color-board-edge); }

.card-row {
  display: flex;
  align-items: center;
  padding: var(--space-sm) var(--space-ms) var(--space-sm) var(--space-md);
  background: var(--color-board-panel);
}

.card-row:first-child { border-radius: 0 0 var(--radius-xs) var(--radius-xs); }
.card-row:last-child { border-radius: var(--radius-xs) var(--radius-xs) 0 0; }
.card-row .card-name { flex: 1; min-width: 0; padding-right: var(--space-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card-row.lost .card-name, .card-row.open .card-name { color: var(--color-text-muted); }

/* The compact tile: the regular one scaled to 40pt tall, 40 wide (SplitFlap.swift's .compact). */
.flap.compact {
  --unit: calc(var(--pt) * var(--size-flap-compact-scale-n));
  --half: calc(var(--size-flap-half-n) * var(--unit));
  --seam: calc(var(--size-flap-seam-n) * var(--unit));
  --corner: calc(var(--radius-sm-n) * var(--unit));
  --flap-edge: calc(var(--size-flap-edge-n) * var(--unit));
  width: calc(var(--size-flap-compact-n) * var(--pt));
  perspective: calc(300 * var(--pt));
}

.flap.compact .flap-digits { font-size: calc(var(--type-score-compact-size-n) * var(--pt)); }

/* ── A table (Features/TournamentHome/StandingsTable.swift): the title, the columns' captions,
   then a row per place: the movement mark, the place (a league's podium on medals, a group's
   qualifiers on tiles), the name, and the six numbers. ───────────────────────────────────────── */
.standings { width: calc(var(--pt) * 330); }

.st-head, .st-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: 0 var(--space-sm);
}

.st-row { min-height: var(--size-table-row); padding: var(--space-ms) var(--space-sm); background: var(--color-background); }
.st-head { color: var(--color-text-muted); }
.st-place { display: flex; align-items: center; gap: var(--space-sm); flex: none; }
.st-head .st-pos { width: calc(var(--size-movement-mark) + var(--space-sm) + var(--size-rank-badge)); flex: none; }
.st-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.st-numbers { display: flex; gap: var(--space-sm); flex: none; }
.st-numbers > * { min-width: var(--size-table-column); text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }

.st-mark { width: var(--size-movement-mark); display: grid; place-items: center; }
.st-mark .level { width: calc(var(--size-movement-mark) - var(--pt)); height: var(--pt); background: var(--color-text-muted); }
.st-mark .up, .st-mark .down { width: var(--size-movement-mark); height: var(--size-movement-mark-height); }
.st-mark .up { background: var(--color-success); clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.st-mark .down { background: var(--color-live); clip-path: polygon(0 0, 100% 0, 50% 100%); }

.badge {
  width: var(--size-rank-badge);
  height: var(--size-rank-badge);
  display: grid;
  place-items: center;
  color: var(--color-text-muted);
}

.badge.tile { background: var(--color-tile); border-radius: var(--radius-sm); color: var(--color-on-tile); }
/* A coin with a darker rim along its bottom; the number centers on the lit face above it. */
.badge.medal { border-radius: var(--radius-full); color: var(--color-on-medal); box-shadow: inset 0 calc(var(--size-medal-lip) * -1) 0 var(--color-medal-lip); }
.badge.medal span { transform: translateY(calc(var(--size-medal-lip) / -2)); }
.badge.gold { background: var(--color-medal-gold); }
.badge.silver { background: var(--color-medal-silver); }
.badge.bronze { background: var(--color-medal-bronze); }

/* ── The board ───────────────────────────────────────────────────────────────────────────────── */

/* The board, its events and (in a league or group) the live table side by side, below the
   controls; app.js scales them down together when they don't fit. */
#match {
  position: absolute;
  inset: 0;
  /* Right of the rail (the icon above, the controls below). */
  padding-left: calc(var(--space-screen-padding) + var(--size-icon-button) + var(--space-md));
}

#match.scaled { align-items: flex-start; }

.match-content, .multi-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  transform-origin: top center;
}

.match-top { display: flex; align-items: center; justify-content: center; gap: var(--space-xl); }

/* The two playing, as in the app: the name and the points in the body's strong weight. */
.st-row.playing .st-name, .st-row.playing .st-points { font-family: "Barlow-Bold"; }

.board {
  flex: none;
  display: flex;
  flex-direction: column;
  padding: var(--edge);
  background: var(--color-board-strip) padding-box;
  border: calc(var(--edge) * 2) solid var(--color-board-frame);
  border-radius: var(--radius-xl);
}

/* The strip on its panel-colored rim, open at the bottom onto the sides. */
.strip-rim {
  padding: var(--edge) var(--edge) 0;
  background: var(--color-board-panel);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.strip {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-ms);
  background: var(--color-board-strip);
  border-radius: calc(var(--radius-lg) - var(--edge)) calc(var(--radius-lg) - var(--edge)) var(--radius-sm) var(--radius-sm);
}

.meta {
  flex: 1;
  min-width: 0;
  color: var(--color-text-muted);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.status {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  color: var(--color-text-muted);
}

.status.live { color: var(--color-live); }

.live-dot {
  width: 0;
  height: var(--size-live-dot);
  margin-right: 0;
  border-radius: var(--radius-full);
  background: var(--color-live);
  opacity: 0;
  transform: scale(0);
  transition: width var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1),
    margin-right var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1),
    opacity var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1),
    transform var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1);
}

.status.live .live-dot {
  width: var(--size-live-dot);
  margin-right: var(--space-xs);
  opacity: 1;
  transform: scale(1);
  animation: pulse 800ms ease-in-out infinite alternate;
}

@keyframes pulse { to { opacity: 0.3; } }

.sides {
  position: relative;
  display: flex;
  gap: var(--edge);
}

.side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  width: calc(var(--size-flap-large-n) * var(--flap) * var(--pt) + var(--space-lg) * 2);
  padding: var(--space-lg) var(--space-sm);
  background: var(--color-board-panel);
}

.side.home { border-radius: 0 var(--radius-xs) var(--radius-xs) var(--radius-lg); }
.side.away { border-radius: var(--radius-xs) 0 var(--radius-lg) var(--radius-xs); }

.name {
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
}

.side.lost .name { color: var(--color-text-muted); }

.versus {
  position: absolute;
  left: 50%;
  top: calc(var(--space-lg) + (var(--size-flap-large-half-n) * 2 + var(--size-flap-large-seam-n)) * var(--flap) * var(--pt) / 2);
  width: var(--size-versus-badge);
  height: var(--size-versus-badge);
  display: grid;
  place-items: center;
  border-radius: var(--radius-full);
  background: var(--color-board-strip);
  transform: translate(-50%, -50%);
}

/* ── Split-flap tile, the match screen's large one scaled by --flap ─────────────────────────── */

.flap {
  --unit: calc(var(--flap) * var(--pt));
  --half: calc(var(--size-flap-large-half-n) * var(--unit));
  --seam: calc(var(--size-flap-large-seam-n) * var(--unit));
  --corner: calc(var(--radius-sm-n) * var(--size-flap-large-scale-n) * var(--unit));
  --flap-edge: calc(var(--size-flap-edge-n) * var(--unit));
  position: relative;
  width: calc(var(--size-flap-large-n) * var(--unit));
  height: calc(var(--half) * 2 + var(--seam));
  perspective: calc(300 * var(--unit));
  color: var(--color-on-tile);
}

.flap.muted { color: var(--color-on-tile-muted); }

.flap-half {
  position: absolute;
  left: 0;
  width: 100%;
  height: var(--half);
  overflow: hidden;
  border-radius: var(--corner);
  background: var(--color-tile);
  backface-visibility: hidden;
}

/* The lit top edge, or the dark bottom one. */
.flap-top { top: 0; box-shadow: inset 0 var(--flap-edge) 0 var(--color-flap-highlight); transform-origin: 50% calc(100% + var(--seam) / 2); }
.flap-bottom { bottom: 0; box-shadow: inset 0 calc(var(--flap-edge) * -1) 0 var(--color-flap-edge); transform-origin: 50% calc(var(--seam) / -2); }

/* The full-height number; each half is a window onto its half. */
.flap-digits {
  position: absolute;
  left: 0;
  width: 100%;
  height: calc(var(--half) * 2 + var(--seam));
  display: grid;
  place-items: center;
  font-family: "SpaceGroteskTorneito-Bold";
  font-size: calc(var(--type-score-large-size-n) * var(--unit));
  line-height: 1;
}

.flap-top .flap-digits { top: 0; }
.flap-bottom .flap-digits { bottom: 0; }

.flap-shade {
  position: absolute;
  inset: 0;
  background: var(--color-flap-shade);
  opacity: 0;
}

/* ── The timeline (app.js TIMELINE): a lane per match, goals at their minute on a rail ──────── */

.icon { display: block; flex: none; width: var(--size-icon); height: var(--size-icon); fill: var(--color-text); }

.timeline { display: flex; flex-direction: column; }
.tl-lane { display: flex; align-items: center; gap: var(--space-md); height: calc(var(--pt) * 52); }
.tl-label { flex: none; width: calc(var(--pt) * 120); color: var(--color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tl-track { position: relative; flex: 1; min-width: 0; height: 100%; display: flex; overflow: hidden; }
.timeline:not(.labelled) .tl-track { justify-content: center; }
/* More than fits: the newest stay in view, the first slide out under a fade on the left. */
.tl-track.full { justify-content: flex-end; mask-image: linear-gradient(to right, transparent, #000 var(--space-lg)); }

.tl-events { position: relative; flex: none; display: flex; gap: var(--space-lg); height: 100%; }
/* The rail, from the first event's middle to the last's. */
.tl-rail {
  position: absolute;
  left: calc(var(--size-pill-icon) / 2);
  right: calc(var(--size-pill-icon) / 2);
  top: 50%;
  height: var(--size-flap-seam);
  background: var(--color-border);
}

/* An event: what's above the rail, its mark on the rail, what's below. */
.tl-event {
  position: relative;
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  justify-items: center;
  min-width: var(--size-pill-icon);
}
.tl-event .icon { grid-row: 2; }
.tl-event .icon { width: var(--size-pill-icon); height: var(--size-pill-icon); background: var(--color-background); border-radius: var(--radius-full); }
.tl-event[data-key="kickoff"] .icon, .tl-event[data-key="final"] .icon { fill: var(--color-text-muted); }
.tl-above { align-self: end; white-space: nowrap; color: var(--color-text-muted); }
.tl-above b { font-family: "Barlow-Bold"; font-weight: normal; color: var(--color-text); }
.tl-below { align-self: start; white-space: nowrap; }
/* ── A goal lights up its scorer (app.js HIGHLIGHT) ──────────────────────────────────────────── */
.side, .card-row { transition: background-color 600ms cubic-bezier(0.33, 1, 0.68, 1); }
.side.scored, .card-row.scored { background-color: var(--color-accent-soft); transition-duration: 250ms; }

/* Rolling text: each character in its own slot. */
.roll-char { display: inline-block; }
.roll-slot { display: inline-grid; }
.roll-slot > * { grid-area: 1 / 1; }

/* ── Errors ──────────────────────────────────────────────────────────────────────────────────── */

/* The app's EmptyState (DesignSystem/Surfaces.swift): the title, the line under it, centered. */
#error { flex-direction: column; gap: var(--space-sm); padding: var(--space-lg); text-align: center; }

/* Stale content: the app's sync banner (Features/Match/SyncBanner.swift, offline) at the bottom
   center while the connection comes back. */
#offline {
  position: fixed;
  left: 50%;
  bottom: var(--space-screen-padding);
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-text);
  transform: translateX(-50%);
  white-space: nowrap;
}

#offline .dot {
  width: var(--size-live-dot);
  height: var(--size-live-dot);
  border-radius: var(--radius-full);
  background: var(--color-live);
}

/* ── Controls: Desconectar and full screen ──────────────────────────────────────────────────── */

/* The rail's foot: bottom left, 16pt from the edges, Desconectar over full screen, 8pt apart. Up
   while the page isn't full screen; in full screen they show while the pointer moves (app.js),
   with the cursor, and go again when it rests. */
#controls {
  position: fixed;
  left: var(--space-screen-padding);
  bottom: var(--space-screen-padding);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-sm);
  transition: opacity var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1);
}

#controls button {
  height: var(--size-icon-button);
  min-width: var(--size-icon-button);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-text);
  cursor: pointer;
}

#controls button:active { background: var(--color-surface-pressed); }
#controls .icon { width: var(--size-menu-icon); height: var(--size-menu-icon); fill: currentColor; }

/* Desconectar's confirm: the circle opens to the right into a capsule with "¿Desconectar?" in the
   danger color (250ms ease-out), and closes back the same way. */
#disconnect { padding: 0 calc((var(--size-icon-button) - var(--size-menu-icon)) / 2); }
#disconnect .label {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  transition: max-width var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1), opacity var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1),
    margin-left var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1);
}
#disconnect.confirming { color: var(--color-danger); }
#disconnect.confirming .label { max-width: calc(var(--pt) * 120); margin-left: var(--space-sm); opacity: 1; }

body.full { cursor: none; }
body.full #controls { opacity: 0; pointer-events: none; }
body.full.awake { cursor: default; }
body.full.awake #controls { opacity: 1; pointer-events: auto; }

/* ── Torneito's icon, top left, lined up with the controls ──────────────────────────────────── */
#brand {
  position: fixed;
  top: var(--space-screen-padding);
  left: var(--space-screen-padding);
  height: var(--size-icon-button);
  display: flex;
  align-items: center;
  pointer-events: none;
}

/* The wordmark (784×309 art): the letters are a mask over the text color, so they read in light
   and dark; the crown sits over the N at (351, 75), 109 wide. */
#brand .wordmark { position: relative; display: block; height: var(--size-broadcast-logo); aspect-ratio: 784 / 309; }
#brand .letters {
  position: absolute; inset: 0; background: var(--color-text);
  -webkit-mask: url(logo-letters.png) center / 100% 100% no-repeat;
  mask: url(logo-letters.png) center / 100% 100% no-repeat;
}
#brand .crown { position: absolute; left: calc(351 / 784 * 100%); top: calc(75 / 309 * 100%); width: calc(109 / 784 * 100%); height: auto; }

/* ── Several matches live: the cards, and their tables or the bracket beside them ───────────── */
#multi {
  position: absolute;
  inset: 0;
  /* Right of the rail (the icon above, the controls below). */
  padding-left: calc(var(--space-screen-padding) + var(--size-icon-button) + var(--space-md));
}

#multi.scaled { align-items: flex-start; }

.multi-top { display: flex; align-items: center; justify-content: center; gap: var(--space-xl); }

/* Up to three stacked; four or more in two columns. */
.multi-cards { display: grid; grid-auto-flow: column; grid-template-rows: repeat(var(--rows, 3), auto); gap: var(--space-md); }
.multi-cards .card { width: calc(var(--pt) * 190); }
.multi-side, .multi-tables { display: flex; align-items: flex-start; gap: var(--space-xl); }

/* ── The bracket (Features/TournamentHome/BracketView.swift), from the round being played: a
   column per round under its short name, each match two rows (the winner in bold, the loser
   muted, a live score in the live color), lines from each pair to the match it feeds. ───────── */
.bracket { display: flex; flex-direction: column; gap: var(--space-sm); }
.bracket-heads { display: flex; gap: var(--space-lg); }
.bracket-heads > * { width: var(--size-broadcast-bracket-column); }
.bracket-body { position: relative; }

.b-cell, .b-line { position: absolute; transition: top var(--duration-base) cubic-bezier(0.33, 1, 0.68, 1); }
.b-line { background: var(--color-border); }

.b-cell {
  width: var(--size-broadcast-bracket-column);
  display: flex;
  flex-direction: column;
  gap: var(--size-flap-seam);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-background);
}

.b-row {
  height: var(--size-broadcast-bracket-row);
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0 calc(var(--space-sm) + var(--space-xs));
  background: var(--color-surface);
}

.b-row .b-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.b-row .b-score { font-family: "Barlow-Bold"; font-variant-numeric: tabular-nums; }
.b-row.won .b-name { font-family: "Barlow-Bold"; }
.b-row.lost, .b-row.open { color: var(--color-text-muted); }
.b-cell.live .b-score { color: var(--color-live); }
.b-cell.focused .b-row { background: var(--color-accent-soft); }

/* A top seed's bye: outlined, since nobody plays it. */
.b-cell.bye { background: none; box-shadow: inset 0 0 0 var(--size-flap-seam) var(--color-border); }
.b-cell.bye .b-row { background: none; }
.b-cell.bye .b-row + .b-row { color: var(--color-text-muted); border-top: var(--size-flap-seam) solid var(--color-border); }

/* A place in the next round as it stands: who leads the live match that feeds it, after the live
   dot. */
.b-row.projected .b-name::before {
  content: "";
  display: inline-block;
  width: var(--size-live-dot);
  height: var(--size-live-dot);
  margin-right: var(--space-xs);
  border-radius: var(--radius-full);
  background: var(--color-live);
  vertical-align: middle;
  animation: pulse 800ms ease-in-out infinite alternate;
}

/* ── Follow the tournament: the invite link's code, bottom right, while the screen waits ───── */
#follow {
  position: fixed;
  right: var(--space-screen-padding);
  bottom: var(--space-screen-padding);
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  gap: var(--space-sm);
}

.follow-code {
  width: var(--size-broadcast-follow);
  height: var(--size-broadcast-follow);
  padding: var(--space-xs);
  background: var(--color-code);
  border-radius: var(--radius-sm);
}

.follow-code svg { display: block; width: 100%; height: 100%; }
.follow-code path { fill: var(--color-on-code); }

/* The waiting and idle screens keep clear of it. */
body.following #idle, body.following #waiting { padding-bottom: calc(var(--space-screen-padding) + var(--size-broadcast-follow) + var(--space-sm)); }
