:root {
  /* Base column sizes at "natural" (unzoomed) size. draft-board.js
     measures the board's natural width/height against the actual screen
     and applies a single zoom factor so the whole board -- header, grid,
     ticker -- always fits with zero scrolling, in either direction. */
  --team-col: 178px;
  --budget-col: 93px;
  --slot-col: 124px;
}

body { overflow: hidden; height: 100vh; }

/* Covers the board's first paint -- config fetch + the header/grid
   layout math (fitBoardToScreen) both take a beat, and without this
   the unscaled board flashes at full/wrong size for a frame before
   snapping into place. Removed once fitBoardToScreen's first real run
   completes (see draft-board.js), or immediately if a league-code
   prompt is needed instead (see shared/league-gate.js). */
.board-loading-screen {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  transition: opacity 0.35s ease;
}
.board-loading-screen[hidden] { display: none; }
.board-loading-ball {
  font-size: 64px;
  line-height: 1;
  animation: board-loading-spin 1.1s ease-in-out infinite;
}
.board-loading-text {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 1.5px;
  color: var(--gold-dim);
}
.board-loading-bar {
  width: 160px;
  height: 4px;
  border-radius: 999px;
  background: var(--panel-alt);
  overflow: hidden;
}
.board-loading-bar-fill {
  width: 40%;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #0076b6, #2f6fed);
  animation: board-loading-bar 1.3s ease-in-out infinite;
}
@keyframes board-loading-spin {
  0%, 100% { transform: rotate(-14deg) scale(1); }
  50% { transform: rotate(14deg) scale(1.08); }
}
@keyframes board-loading-bar {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}
@media (prefers-reduced-motion: reduce) {
  .board-loading-ball { animation: none; }
  .board-loading-bar-fill { animation: none; width: 100%; }
}

.board-scroll-wrapper {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  position: relative;
}

.board-content {
  /* Width is set explicitly by draft-board.js, computed from the header
     and grid only (never the ticker -- the news ticker's concatenated
     headline track is enormous by design, since it needs content to
     scroll through, and letting the board auto-size to "whichever child
     is widest" let that huge ticker content balloon the whole board,
     which then had to be zoomed way down to fit -- making the grid look
     tiny). The ticker instead just fills whatever width this ends up
     being and clips its own overflow.

     Positioned absolute + transform:scale(x,y) (independent horizontal/
     vertical factors, set by fitBoardToScreen()) instead of the previous
     zoom-based approach -- zoom only supports one uniform factor, which
     preserves aspect ratio but leaves blank bars on whichever axis isn't
     the limiting one. Scaling to exactly fill both dimensions removes
     the bars entirely (at the cost of a slight, generally unnoticeable
     stretch on a grid/text UI like this one). */
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.shot-flash {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 10%;
  pointer-events: none;
}
.shot-flash[hidden] { display: none; }
.shot-flash-text {
  font-size: 80px;
  font-weight: 900;
  letter-spacing: 3px;
  text-align: center;
  color: #ff3b30;
  text-shadow: 0 0 30px rgba(255, 59, 48, 0.9), 0 0 60px rgba(255, 59, 48, 0.6);
  animation: shot-pulse 0.5s ease-in-out infinite alternate;
}

/* ---------------- Header ---------------- */

.board-header {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 6px 24px;
  background: linear-gradient(180deg, rgba(6, 8, 12, 0.6) 0%, rgba(6, 8, 12, 0.8) 100%), url("shared/images/field-bg.jpg");
  background-size: cover;
  background-position: center 65%;
  border-bottom: 2px solid #fff;
  white-space: nowrap;
  flex: none;
}

.header-block { flex: none; }
.header-block[hidden] { display: none; }

.title-block { min-width: 300px; }

/* Plain white text, thin blue outline, nothing else -- no drop shadow,
   no glow, no blur. Two things had to change from the first attempt:
   the offset (1px) was too small to read as an outline at this font
   size and just blended into the anti-aliasing, and the color (a very
   dark navy) had too little contrast against the dark photo background
   to actually show. Bigger offset (2px) + a brighter, more saturated
   blue fixes both -- still a hard 0-blur edge, just actually visible. */
.board-title {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 38px;
  font-weight: 900;
  letter-spacing: 0.5px;
  color: #fff;
  text-shadow:
    -1px 0 0 #2f6fed,
    1px 0 0 #2f6fed,
    0 -1px 0 #2f6fed,
    0 1px 0 #2f6fed,
    -1px -1px 0 #2f6fed,
    1px -1px 0 #2f6fed,
    -1px 1px 0 #2f6fed,
    1px 1px 0 #2f6fed;
}

.complete-badge {
  flex: none;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.6px;
  color: #0b2e1a;
  background: linear-gradient(180deg, #4fd67a, #2fae5a);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
  text-shadow: none;
}
.complete-badge[hidden] { display: none; }

/* Condensed, moved under the clock (in the clock-block column) instead
   of under the board name -- one line of numbers + a slim bar, in the
   brand blue used for fan messages instead of gold. */
.tracker-block { margin-top: 6px; display: flex; flex-direction: column; align-items: center; }
.tracker-numbers {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.tracker-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-faint); }
.tracker-value { font-size: 14px; font-weight: 700; color: #59c2f0; }
.progress-bar {
  margin-top: 3px;
  width: 140px;
  height: 6px;
  border-radius: 999px;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #005a8a, #0076b6);
  border-radius: 999px;
  transition: width 0.5s ease;
}
@keyframes shot-pulse {
  from { opacity: 0.65; transform: scale(0.97); }
  to { opacity: 1; transform: scale(1.05); }
}

.position-totals-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-left: 1px solid var(--border);
  padding-left: 18px;
  min-width: 220px;
}
.position-totals-row { display: flex; gap: 8px; }
.pt-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  background: rgba(28, 30, 40, 0.28);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  border: 1px solid var(--border);
}
.pt-chip .pt-pos { font-size: 10px; font-weight: 800; letter-spacing: 0.5px; }
.pt-chip .pt-count { font-size: 15px; font-weight: 700; color: var(--text); }

.elapsed-block {
  border-left: 1px solid var(--border);
  padding-left: 18px;
  min-width: 90px;
}
.elapsed-value { font-size: 18px; font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; }

.recent-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  padding: 0 18px;
  /* Fixed width (not min-width) -- a flex item with no explicit width
     sizes to its content's natural/preferred size, and once real picks
     (longer names) populated the grid, that preferred size grew past
     what was measured at page load, pushing the clock/QR past the
     board's right edge since the board's own width was already fixed by
     then. A hard width means chip text just ellipsis-truncates instead
     of ever growing the box. */
  width: 360px;
}
.recent-label { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--text-faint); }
/* 2 columns instead of 3 -- 3 columns left so little width per chip that
   even the shortened "F. Lastname" format still got truncated to a
   handful of characters. Fewer, wider chips actually fit the text.
   Row height is fixed (3 explicit rows for up to 6 picks) rather than
   left to auto-size, so the header doesn't grow/shift the whole board
   down the moment a second or third row of picks actually appears. */
.recent-strip {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(3, 22px);
  gap: 4px 10px;
}
.recent-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--radius-sm);
  background: rgba(28, 30, 40, 0.28);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  border: 1px solid var(--border);
  font-size: 10px;
  overflow: hidden;
}
.recent-chip .rc-pos-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.recent-chip .rc-name { color: var(--text); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent-chip .rc-price { font-weight: 700; flex: none; margin-left: auto; }

.tools-block { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.tool-btn[hidden] { display: none; }
.tool-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--panel-alt);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}
.tool-btn:hover { border-color: #0076b6; }

#switchLeagueBtn {
  width: 40px;
  height: 40px;
  border: 2px solid #0076b6;
}

/* Now on the right side of the header, next to the QR code, with the
   Drafted Total stacked underneath it -- smaller than before since it no
   longer needs to stand alone. */
.clock-block {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.scoreboard-clock {
  display: flex;
  align-items: center;
  gap: 6px;
}
.scoreboard-value {
  font-family: "Courier New", Consolas, monospace;
  font-size: 19px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.5px;
  color: #59c2f0;
}

.qr-block { display: flex; flex-direction: column; align-items: center; margin-left: 14px; }
.qr-code { line-height: 0; border-radius: 5px; overflow: hidden; box-shadow: 0 0 0 2px #0076b6; }
.qr-code svg { display: block; width: 68px; height: 68px; }
.qr-caption { margin-top: 4px; font-size: 10px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; color: #59c2f0; }

/* ---------------- Nomination overlay ----------------
   A centered floating card over the middle of the board while a player
   is nominated but not yet assigned a team/price -- opt-in
   (show_nomination), cleared automatically the instant the real pick is
   submitted. Lives OUTSIDE #boardContent (see the HTML comment) so it
   centers on the real viewport regardless of the board's zoom/scale, and
   uses position:fixed so it floats over the grid instead of pushing it
   down like the old inline-strip version did. pointer-events: none since
   this is a pure display banner on a view-only screen -- it should never
   be able to block a tap/click on anything underneath it. */
.nomination-overlay[hidden] { display: none; }
.nomination-overlay {
  position: fixed;
  top: 50%;
  left: 50%;
  /* scale(1) after the centering translate -- translate% is resolved
     against the box's own unscaled size, so scaling here resizes the
     card in place around its own center rather than drifting it off-
     center. Was scale(2), cut back down (2026-08-21: too large on a
     real TV). */
  transform: translate(-50%, -50%) scale(1);
  z-index: 1500;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 22px 46px;
  border-radius: var(--radius-lg);
  background: var(--panel-alt);
  border: 3px solid var(--gold-dim);
  box-shadow: 0 0 0 8px rgba(8, 8, 11, 0.55), 0 20px 60px -10px rgba(0, 0, 0, 0.6), 0 0 40px -8px rgba(212, 175, 55, 0.35);
  animation: nomination-pop-in 0.28s cubic-bezier(0.2, 0.8, 0.3, 1.3);
}
@keyframes nomination-pop-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.85); }
  to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .nomination-overlay { animation: none; }
}
.nomination-label {
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 2.5px;
  color: var(--gold);
  white-space: nowrap;
}
.nomination-player {
  font-size: 44px;
  font-weight: 800;
  color: var(--text);
  line-height: 1;
  white-space: nowrap;
}
.nomination-position {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: 0.5px;
  padding: 4px 14px;
  border-radius: var(--radius-md);
  border: 2px solid var(--border-soft);
  white-space: nowrap;
}
/* Reuses the exact same position accent colors as the grid header/slot
   cells (pos-QB/pos-RB/etc.) so a nominated QB reads the same red as
   the QB column, etc. -- one color system across the whole board. */
.nomination-position.pos-QB { color: var(--qb-glow); border-color: var(--qb); }
.nomination-position.pos-RB { color: var(--rb-glow); border-color: var(--rb); }
.nomination-position.pos-WR { color: var(--wr-glow); border-color: var(--wr); }
.nomination-position.pos-TE { color: var(--te-glow); border-color: var(--te); }
.nomination-position.pos-DEF { color: var(--def-glow); border-color: var(--def); }
.nomination-position.pos-K { color: var(--k-glow); border-color: var(--k); }

/* ---------------- Empty-board hint ----------------
   Shown only while draftedCount() is 0 -- the whole point of this screen
   is display-only, and a first-time viewer staring at an untouched board
   (every slot "Open", every team at full budget) has no other signal that
   picks come from a separate app on someone else's phone. Disappears for
   good the instant the first real pick lands; not tied to show_nomination
   or any other toggle -- always on until there's a reason to turn it off. */
.empty-board-hint[hidden] { display: none; }
.empty-board-hint {
  padding: 8px 20px;
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
  background: var(--panel);
  border-bottom: 1px solid var(--border-soft);
}
.empty-board-hint strong { color: var(--gold); }

/* ---------------- Grid ---------------- */

.board-grid[hidden] { display: none; }
.board-grid {
  flex: none;
  display: grid;
  grid-template-columns: var(--team-col) var(--budget-col) var(--budget-col) repeat(13, var(--slot-col));
  align-content: start;
  background: var(--bg);
}

.grid-header-cell {
  background: var(--bg-alt);
  border-bottom: 2px solid var(--border);
  padding: 7px 10px;
  font-size: 15px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-align: center;
  color: var(--text-dim);
}
.grid-header-cell.corner { text-align: left; color: #59c2f0; }
.grid-header-cell.pos-QB { color: var(--qb-glow); }
.grid-header-cell.pos-RB { color: var(--rb-glow); }
.grid-header-cell.pos-WR { color: var(--wr-glow); }
.grid-header-cell.pos-TE { color: var(--te-glow); }
.grid-header-cell.pos-DEF { color: var(--def-glow); }
.grid-header-cell.pos-K { color: var(--k-glow); }

.team-cell {
  position: relative;
  padding: 8px 5px 8px 10px;
  border-bottom: 1px solid var(--border-soft);
  display: flex;
  align-items: center;
  background: var(--panel);
  min-width: 0;
}
/* Replaces the old inline color dot -- a short accent bar instead of a
   full-height border, so it doesn't visually dominate the cell the way
   a top-to-bottom border does. 70% height, centered vertically. */
.team-cell::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 70%;
  border-radius: 2px;
  background: var(--team-color, var(--border-soft));
}
.team-name-row { display: flex; align-items: center; font-size: 23px; font-weight: 800; color: var(--text); line-height: 1.2; min-width: 0; width: 100%; }
.team-name-text { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; min-width: 0; }

.budget-cell {
  padding: 10px 5px;
  border-bottom: 1px solid var(--border-soft);
  border-left: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--panel);
}
.budget-cell .bc-value { font-size: 26px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.budget-cell.max-bid .bc-value { color: #59c2f0; }
.budget-cell.remaining .bc-value { color: var(--text); }
.budget-cell.remaining.tight .bc-value { color: var(--qb-glow); }

.slot-cell {
  margin: 2px;
  border-radius: var(--radius-md);
  border: 2px solid var(--border-soft);
  background: var(--panel-alt);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 6px 4px;
  min-height: 72px;
}

.slot-cell.filled { background: var(--panel); }
.slot-cell.empty { border-style: dashed; }
.slot-cell .slot-player-first,
.slot-cell .slot-player-last {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.15;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.slot-cell .slot-price { font-size: 14px; font-weight: 800; margin-top: 3px; }
.slot-cell .slot-open { font-size: 11px; color: var(--text-faint); letter-spacing: 0.5px; text-transform: uppercase; }

.slot-cell.pos-QB { border-color: var(--qb); box-shadow: 0 0 10px -2px var(--qb-glow); }
.slot-cell.pos-RB { border-color: var(--rb); box-shadow: 0 0 10px -2px var(--rb-glow); }
.slot-cell.pos-WR { border-color: var(--wr); box-shadow: 0 0 10px -2px var(--wr-glow); }
.slot-cell.pos-TE { border-color: var(--te); box-shadow: 0 0 10px -2px var(--te-glow); }
.slot-cell.pos-DEF { border-color: var(--def); box-shadow: 0 0 10px -2px var(--def-glow); }
.slot-cell.pos-K { border-color: var(--k); box-shadow: 0 0 10px -2px var(--k-glow); }
.slot-cell.pos-QB .slot-price { color: var(--qb-glow); }
.slot-cell.pos-RB .slot-price { color: var(--rb-glow); }
.slot-cell.pos-WR .slot-price { color: var(--wr-glow); }
.slot-cell.pos-TE .slot-price { color: var(--te-glow); }
.slot-cell.pos-DEF .slot-price { color: var(--def-glow); }
.slot-cell.pos-K .slot-price { color: var(--k-glow); }

/* A newly-posted pick briefly glows so it's obvious at a glance where a
   pick just landed on the board, not just that something changed
   somewhere in the grid. (An earlier version also traced a rotating
   ring around the border, but it only completed a partial sweep before
   fading -- looked broken rather than intentional -- so that part was
   dropped in favor of just the glow.) */
.slot-cell.pick-flash {
  animation: pick-flash-glow 1.6s ease-out 1;
}
@keyframes pick-flash-glow {
  0% { box-shadow: 0 0 0 0 rgba(242, 193, 78, 0.95); }
  55% { box-shadow: 0 0 24px 7px rgba(242, 193, 78, 0.55); }
  100% { box-shadow: 0 0 0 0 rgba(242, 193, 78, 0); }
}

/* ---------------- Break screen ----------------
   A fixed base width/height (like the grid's own gridBaseWidth) gives
   fitBoardToScreen() a consistent, predictable natural size to scale
   from. Pulled a lot smaller/denser than the first pass -- timer bar,
   then facts + odds side by side, then a condensed team board below,
   all with tight padding/small type instead of the roomy layout that
   made the whole screen feel oversized once scaled to fill a display. */
.break-screen[hidden] { display: none; }
.break-screen {
  width: 100%;
  /* Fallback only -- draft-board.js sets this inline to the grid's own
     natural height on entering break mode, so the break screen keeps
     the same aspect ratio the board's scale-to-fit math already uses.
     620px was a disconnected magic number that made the break screen
     scale down by width alone on a big TV, leaving large empty margins
     top/bottom. */
  height: 620px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: var(--bg);
  box-sizing: border-box;
}
.break-banner {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 16px;
  border-radius: var(--radius-md);
  background: linear-gradient(155deg, rgba(212, 175, 55, 0.22) 0%, var(--panel-alt-grad) 70%);
  border: 1px solid var(--gold-dim);
  box-shadow: 0 0 24px -8px rgba(212, 175, 55, 0.4);
}
.break-banner-text {
  font-size: 15px;
  font-weight: 900;
  letter-spacing: 1px;
  color: var(--gold-bright);
  text-shadow: 0 0 14px rgba(242, 193, 78, 0.4);
}
.break-timer {
  font-size: 17px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
/* Fixed three-column layout (not conditionally hidden/shown like the old
   poll card was) -- all three cards are always present once on break, so
   the board's measured height never jumps around between renders, which
   is what made fitBoardToScreen's scale flicker/resize unpredictably with
   the old poll-or-nothing card. Fills all remaining height below the
   timer banner instead of a fixed row. */
.break-screen-body { flex: 1; min-height: 0; display: flex; gap: 10px; }
.break-section-heading {
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.5px;
  color: var(--gold-bright);
  text-shadow: 0 0 14px rgba(242, 193, 78, 0.35);
  margin-bottom: 6px;
}
/* Fun facts and season odds started as equal 25%-narrower-than-a-third
   columns (0.75 : 0.75 : 1.5); season odds has since been trimmed 10%
   of its own share three times more (0.75 -> 0.675 -> 0.6075 ->
   0.54675), each time handing the freed width to the draft board
   (1.5 -> 1.575 -> 1.6425 -> 1.70325). */
.break-odds-card,
.break-fact-card {
  background: var(--panel-grad);
  box-shadow: var(--panel-sheen);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  flex: 0.75;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
}
/* Season odds is capped per slide (see draft-board.js) so it never
   needs to scroll -- hidden instead of auto so no scrollbar can ever
   flash even for a brief oversized render. */
.break-odds-card { flex: 0.54675; overflow-y: hidden; }
.break-odds-note { font-size: 11px; color: var(--text-faint); margin: -2px 0 6px; line-height: 1.3; }
.break-odds-list { display: flex; flex-direction: column; gap: 9px; }
/* Season odds now lists every entry in every market (not just the
   favorite), so results are grouped under a heading per market instead
   of one flat list of favorites. Font sizes here (and in the fact/
   roster cards below) are deliberately larger than a first pass -- the
   whole board is scaled up via a CSS transform to fill the screen
   (fitBoardToScreen), and very small source font sizes turn visibly
   blurry once magnified; bigger source text holds up much better. */
.bo-category { display: flex; flex-direction: column; gap: 2px; }
.bo-cat-heading {
  font-size: 11.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-faint);
  padding-bottom: 3px;
  margin-bottom: 2px;
  border-bottom: 1px solid var(--border-soft);
}
.break-odds-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 1.5px 0; }
.break-odds-row .bor-pick { font-size: 11px; font-weight: 700; color: var(--text); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.break-odds-row .bor-value { font-size: 11px; font-weight: 800; color: var(--gold-bright); flex: none; }
.break-fact-list { display: flex; flex-direction: column; gap: 5px; }
.break-fact-item { font-size: 12.5px; line-height: 1.3; color: var(--text-dim); font-style: italic; padding-bottom: 5px; border-bottom: 1px solid var(--border-soft); }
.break-fact-item:last-child { border-bottom: none; padding-bottom: 0; }
/* Below the 4 facts, a rotating top-10 all-time leaderboard -- the 2
   categories in a slide sit side by side (not stacked) so both fit
   without pushing the card's height out, with a smaller font than the
   odds card to compensate for the narrower per-category column. */
.break-leaders-heading {
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.5px;
  color: var(--gold-bright);
  margin: 64px 0 4px;
}
.break-leaders-list { display: flex; flex-direction: row; gap: 10px; }
.break-leaders-list .bo-category { flex: 1; min-width: 0; }
.break-leaders-list .break-odds-row { padding: 1px 0; }
.break-leaders-list .bor-pick { font-size: 9.5px; overflow: hidden; text-overflow: ellipsis; }
.break-leaders-list .bor-value { font-size: 9.5px; }
.break-leaders-list .bo-cat-heading { font-size: 10px; }

/* A genuinely different presentation of the same draft data as the
   normal grid, not a shrunk copy of it: one row per team (colored dot +
   name + a merged max/remaining budget chip), followed by every player
   they've drafted so far as small position-colored chips wrapped inline
   -- instead of the normal grid's fixed columns-per-roster-slot layout,
   which doesn't compress well at this scale. */
.break-roster-board {
  flex: 1.70325;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--panel-grad);
  box-shadow: var(--panel-sheen);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
}
.break-roster-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.break-roster-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 5px 8px;
  border-radius: var(--radius-sm);
  background: var(--panel-alt);
  border: 1px solid var(--border-soft);
}
.break-roster-row .brr-team {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.break-roster-row .brr-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; align-self: center; }
.break-roster-row .brr-name { font-size: 13px; font-weight: 800; color: var(--text); flex: none; max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.break-roster-row .brr-budget { font-size: 11px; color: var(--text-faint); white-space: nowrap; }
.break-roster-row .brr-picks { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 4px; align-content: flex-start; }
.brr-pick-chip {
  font-size: 11px;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--border-soft);
  white-space: nowrap;
}
.brr-pick-chip .brc-price { font-weight: 800; margin-left: 3px; }
.brr-empty-note { font-size: 11px; color: var(--text-faint); font-style: italic; padding-top: 2px; }

/* ---------------- Ticker ---------------- */

.board-ticker {
  flex: none;
  width: 100%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-top: 2px solid #fff;
}

.ticker-row {
  position: relative;
  width: 100%;
  min-width: 0;
  height: 44px;
  overflow: hidden;
}
.ticker-row[hidden] { display: none; }
/* A subtly bluer tint than the news row below it (which is just
   --panel) so a fan message lane always reads as its own separate
   strip, not more news -- kept whether or not a message is currently
   showing, not just while one's animating through. */
.message-row {
  background: #141b28;
}

/* A visible divider between the message lane and the news ticker below
   it -- previously the only separation was the message row's own
   background tint, with nothing marking the actual seam. */
.news-row { border-top: 1px solid #59c2f0; }

/* position:absolute (not just overflow:hidden on the row) so the track's
   content -- deliberately huge, since it needs a long scroll of headlines
   or several messages to loop through -- can never influence the row's
   (or any ancestor's, including board-content) own size calculations.
   overflow:hidden alone clips the *paint* but a flex child's intrinsic
   min-width can still be picked up by layout; an absolutely positioned
   element is fully out of flow and can't affect ancestor sizing at all. */
.ticker-track {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  animation: ticker-scroll 60s linear infinite;
  font-size: 17px;
  font-weight: 600;
  color: var(--text-dim);
  will-change: transform;
  /* This element is a transform-animated child of boardContent, which
     itself gets a transform: scale(...) from fitBoardToScreen() -- a
     transform inside an already-transformed ancestor is a known cause
     of stutter, especially on lower-powered hardware (a Fire TV
     Stick's GPU is nowhere near a phone/desktop's). backface-visibility
     plus a translateZ(0) baked into the keyframes below (a plain static
     transform here would just get overridden by the animation) forces
     this onto its own composited layer instead of being re-rasterized
     as part of the parent's transformed layer every frame. */
  backface-visibility: hidden;
}
.ticker-track span.ticker-item {
  padding: 0 32px;
  border-right: 1px solid var(--border);
}
/* No border/box-shadow -- just the color -- per feedback that the
   top/bottom border reads as a stray line across the ticker. */
.ticker-track span.ticker-item.fan-message {
  padding: 0 32px;
  color: #59c2f0;
  font-weight: 800;
}

@keyframes ticker-scroll {
  0% { transform: translateX(0) translateZ(0); }
  100% { transform: translateX(-50%) translateZ(0); }
}

/* Messages use a true marquee (enters fully off-screen right, exits
   fully off-screen left, repeats) instead of the news ticker's doubled-
   content loop -- the doubled technique only reads as "entering from the
   right" when total content is much wider than the viewport (so there's
   always more waiting off-screen); message content is short enough that
   it just sat fully visible at the left edge and repeated in place. */
@keyframes message-scroll {
  0% { transform: translateX(var(--message-start, 100%)); }
  100% { transform: translateX(var(--message-end, -100%)); }
}

/* The shared .faq-card (shared/league-gate.css) is sized for a phone
   overlay (max-width: 420px) -- on a TV that reads as a tiny box in
   the middle of a huge screen. Take advantage of the real estate
   instead: much wider, bigger type, and the FAQ items run two columns
   side by side rather than one long scroll. */
.tv-faq-card {
  max-width: 1100px;
  width: 90vw;
  max-height: 85vh;
  padding: 48px 56px;
}
.tv-faq-card .league-gate-title { font-size: 34px; margin-bottom: 24px; }
.tv-faq-card .faq-scroll {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 40px;
  align-content: start;
}
.tv-faq-card .faq-item + .faq-item { margin-top: 0; }
.tv-faq-card .faq-q { font-size: 20px; margin-bottom: 8px; }
.tv-faq-card .faq-a { font-size: 17px; line-height: 1.6; }
.tv-faq-card .league-gate-secondary { font-size: 18px; padding: 14px 28px; margin-top: 24px; }
