/* ── TV / PROJECTOR MODE (?view=tv) — big-screen auto-rotating public display ── */
#tvView { display: none; }
body.tv-mode { overflow: hidden; }
body.tv-mode .nav,
body.tv-mode .container,
body.tv-mode #fsNav,
body.tv-mode .fs-trigger-zone { display: none !important; }

body.tv-mode #tvView {
  position: fixed; inset: 0; z-index: 4000;
  display: flex; flex-direction: column;
  background:
    radial-gradient(ellipse at 25% 15%, rgba(255,59,92,0.10) 0%, transparent 55%),
    radial-gradient(ellipse at 75% 85%, rgba(59,142,255,0.10) 0%, transparent 55%),
    var(--bg);
  color: var(--text);
  padding: clamp(20px, 4vh, 56px) clamp(20px, 4vw, 72px);
}

/* TV-only palette tweak (A-04 · S-13): red and blue had almost the same brightness (1.08:1), so in
   glare, from far away or on a black-and-white screen they merged. A lighter blue gives 1.67:1;
   red is unchanged. One place — delete this rule to go back to the app blue. */
body.tv-mode { --blue: #7cb7ff; --blue-glow: rgba(124,183,255,0.45); --blue-dim: rgba(124,183,255,0.1); }

.tv-panel { flex: 1; display: flex; flex-direction: column; animation: tvFade .6s ease; min-height: 0; }
@keyframes tvFade { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

.tv-heading {
  font-family: 'Bebas Neue', sans-serif;
  font-size: clamp(28px, 4.5vw, 68px);
  letter-spacing: 6px; color: var(--accent);
  text-align: center; margin-bottom: clamp(12px, 2.5vh, 40px);
  text-shadow: 0 0 30px var(--accent-glow);
}

/* ── Battle ── */
.tv-battle { justify-content: center; }
.tv-battle-row { display: flex; align-items: center; justify-content: center; gap: clamp(20px, 4vw, 80px); }
.tv-team { text-align: center; flex: 1; max-width: 40%; transition: transform .4s; }
.tv-team.lead { transform: scale(1.06); }
.tv-team-name {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(26px, 4vw, 64px);
  letter-spacing: 3px; margin-bottom: clamp(6px, 1.5vh, 20px); line-height: 1.05;
}
.tv-team-score {
  font-family: 'Bebas Neue', sans-serif; font-weight: 400;
  font-size: clamp(90px, 22vw, 340px); line-height: 0.9;
}
.tv-team.red  .tv-team-name, .tv-team.red  .tv-team-score { color: var(--red);  }
.tv-team.blue .tv-team-name, .tv-team.blue .tv-team-score { color: var(--blue); }
.tv-team.red.lead  .tv-team-score { text-shadow: 0 0 60px var(--red-glow); }
.tv-team.blue.lead .tv-team-score { text-shadow: 0 0 60px var(--blue-glow); }
.tv-vs {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(24px, 3vw, 56px);
  color: var(--muted); letter-spacing: 4px;
}

/* ── Live ── */
.tv-live-grid {
  --tv-gap: clamp(12px, 2vw, 28px);
  /* least width a card needs to hold two faces, a score and two names without touching its
     neighbour — measured with the longest player names: 317 px at 1024 wide … 531 px from 2560 */
  --tv-card-min: clamp(340px, 22vw + 120px, 540px);
  flex: 1; display: grid; gap: var(--tv-gap); min-height: 0;
  /* --tv-cols (set by _tvGridHtml) is how many cards fit across; a card never gets narrower than
     --tv-card-min, so on a small screen the grid uses fewer columns instead of overflowing */
  grid-template-columns: repeat(auto-fit, minmax(max(var(--tv-card-min), calc((100% - (var(--tv-cols, 3) - 1) * var(--tv-gap)) / var(--tv-cols, 3) - 1px)), 1fr));
  align-content: center;
}
.tv-live-card {
  background: rgba(255,255,255,0.04); border: 2px solid var(--border2);
  border-radius: 20px; padding: clamp(14px, 2vh, 30px) clamp(16px, 2vw, 34px);
}
.tv-live-id { font-family: 'Bebas Neue', sans-serif; font-size: clamp(18px, 2vw, 34px); color: var(--accent); letter-spacing: 2px; }
.tv-live-teams { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 8px 0; }
.tv-lt { flex: 1; min-width: 0; overflow-wrap: anywhere; font-size: clamp(16px, 1.6vw, 30px); font-weight: 700; line-height: 1.15; }
.tv-lt.red  { color: var(--red);  text-align: left; }
.tv-lt.blue { color: var(--blue); text-align: right; }
.tv-live-score { font-family: 'Bebas Neue', sans-serif; font-size: clamp(40px, 6vw, 96px); white-space: nowrap; flex-shrink: 0; }
.tv-live-score .red { color: var(--red); } .tv-live-score .blue { color: var(--blue); } .tv-live-score .sep { color: var(--muted); margin: 0 .12em; }
.tv-live-games { text-align: center; color: var(--muted); font-size: clamp(13px, 1.3vw, 22px); font-weight: 600; }

/* court number — the first thing a viewer looks for — and the status label (พักเกม / ไม่มีความเคลื่อนไหว) */
.tv-court {
  display: inline-block; margin-right: .45em; padding: 0 .5em; border-radius: .45em;
  font-family: 'Space Grotesk', 'Rajdhani', sans-serif; font-weight: 800; letter-spacing: 0; line-height: 1.25;
  color: #14120a; background: var(--gold);
}
.tv-live-card { position: relative; }
/* hangs on the card's top edge, so it never changes the card's height — a grid that fits still fits */
.tv-status {
  position: absolute; top: 0; right: clamp(12px, 1.6vw, 28px); transform: translateY(-55%); z-index: 1;
  padding: 0 .7em; border-radius: 999px; white-space: nowrap;
  font-size: clamp(12px, 1.15vw, 20px); font-weight: 800; letter-spacing: 0; line-height: 1.5;
  color: #14120a; background: var(--gold);
}
.tv-status.stuck { background: #FF8A8A; }
.tv-status:empty { display: none; }
/* single court: no card to hang on — a line under the score, its space kept so nothing jumps */
.tv-vs-mid .tv-status { position: static; transform: none; align-self: center; min-height: 1.5em; font-size: clamp(14px, 1.6vw, 28px); }
.tv-vs-mid .tv-status:empty { display: block; visibility: hidden; }

/* ── Leaderboard ── */
.tv-board { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: clamp(8px, 1.4vh, 20px); max-width: 1100px; margin: 0 auto; width: 100%; }
.tv-board-row {
  display: grid; grid-template-columns: clamp(48px,6vw,96px) auto 1fr auto auto; align-items: center; gap: clamp(10px, 1.8vw, 28px);
  background: rgba(255,255,255,0.03); border: 1px solid var(--border); border-radius: 16px;
  padding: clamp(6px, 1.1vh, 14px) clamp(16px, 2.5vw, 36px);
}
.tv-rank { font-family: 'Bebas Neue', sans-serif; font-size: clamp(28px, 3.6vw, 60px); text-align: center; }
/* player photo on the leaderboard — the one standings list that lacked it */
.tv-board-face { display: flex; align-items: center; }
.tv-board-face .pav { --pav-size: clamp(40px, 4.4vw, 76px) !important; border-width: 2px; }
/* page indicator — the board scrolls through every rank, this says where we are */
.tv-board-page {
  text-align: center; color: var(--muted); font-weight: 700; letter-spacing: 2px;
  font-size: clamp(12px, 1.4vw, 24px); margin-top: clamp(-6px, -0.6vh, -2px); margin-bottom: clamp(10px, 1.8vh, 26px);
}
.tv-pname { font-size: clamp(20px, 2.6vw, 46px); font-weight: 700; }
.tv-pname.red { color: var(--red); } .tv-pname.blue { color: var(--blue); }
.tv-pmeta { color: var(--muted); font-size: clamp(12px, 1.3vw, 22px); font-weight: 600; white-space: nowrap; }
.tv-ppts { font-family: 'Bebas Neue', sans-serif; font-size: clamp(28px, 3.6vw, 58px); color: var(--accent); }
.tv-ppts span { font-size: .4em; color: var(--muted); margin-left: 4px; }

.tv-empty { color: var(--muted); font-size: clamp(20px, 3vw, 40px); text-align: center; margin: auto; }

/* ── Footer (dots + brand) ── */
.tv-foot { display: flex; align-items: center; justify-content: space-between; padding-top: clamp(10px, 2vh, 28px); }
.tv-dots { display: flex; gap: 12px; }
.tv-dot { width: clamp(10px, 1vw, 16px); height: clamp(10px, 1vw, 16px); border-radius: 50%; background: var(--border2); transition: all .3s; }
.tv-dot.on { background: var(--accent); box-shadow: 0 0 14px var(--accent-glow); transform: scale(1.2); }
.tv-brand { color: var(--muted); font-size: clamp(12px, 1.3vw, 22px); letter-spacing: 2px; font-weight: 600; }

/* sync chip — the last moment this screen was confirmed live (a frozen page = a frozen clock) */
.tv-sync { display: flex; align-items: center; gap: 8px; color: var(--muted); font-size: clamp(11px, 1vw, 16px); font-weight: 600; letter-spacing: 1px; font-variant-numeric: tabular-nums; }
.tv-sync-dot { width: clamp(7px, .6vw, 10px); height: clamp(7px, .6vw, 10px); border-radius: 50%; background: var(--green); }
.tv-sync-warn { color: var(--gold); font-weight: 700; }
.tv-sync.off { color: #FF8A8A; }
.tv-sync.off .tv-sync-dot { background: var(--danger); }
/* red bar across the top while the data may be old (toggled by _tvHealth; above every panel) */
.tv-stale { display: none; }
body.tv-mode .tv-stale:not([hidden]) {
  display: block; position: fixed; top: 0; left: 0; right: 0; z-index: 4020; text-align: center;
  padding: clamp(8px, 1.4vh, 18px) 16px; background: #B3262F; color: #fff;
  font-size: clamp(18px, 2.4vw, 44px); font-weight: 800; letter-spacing: 1px; box-shadow: 0 6px 30px rgba(0,0,0,.5);
}

/* faces on the TV live card — the audience screen is where a face
   earns the most, so these scale with the viewport and overlap slightly */
.tv-faces { display: inline-flex; flex-wrap: wrap; justify-content: center; max-width: 100%; margin-bottom: clamp(4px, 0.8vh, 10px); }
.tv-live-card .tv-faces .pav { --pav-size: clamp(32px, 3.4vw, 64px) !important; border-width: 2px; }
.tv-faces .pav + .pav { margin-left: -8px; }
.tv-lt { display: flex; flex-direction: column; align-items: center; }

/* team tag — the team's name plus a shape beside the colour (triangle = red, circle = blue), so a
   team is never told apart by colour alone (A-04) */
.tv-shape { display: inline-block; flex: none; width: .8em; height: .8em; background: currentColor; vertical-align: -.05em; }
.tv-shape.red  { color: var(--red);  clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.tv-shape.blue { color: var(--blue); border-radius: 50%; }
.tv-tag {
  display: inline-flex; align-items: center; justify-content: center; gap: .45em; max-width: 100%; margin-bottom: clamp(2px, .5vh, 6px);
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(12px, 1.1vw, 20px); letter-spacing: 2px; line-height: 1; white-space: nowrap;
}
.tv-tag.red  { color: var(--red); }
.tv-tag.blue { color: var(--blue); }
.tv-tag-name { overflow: hidden; text-overflow: ellipsis; }
.tv-vs-side .tv-tag { font-size: clamp(16px, 1.8vw, 34px); margin-bottom: clamp(6px, 1vh, 14px); }

/* 7+ courts: compact cards — faces dropped, type scaled down — so every court still fits on
   the screen. Interim: the big-court layout (7–10 courts, number-led cards) is WP8. */
.tv-live-grid.is-compact { --tv-card-min: clamp(250px, 14vw + 90px, 330px); }
.tv-live-grid.is-compact .tv-faces, .tv-live-grid.is-compact .tv-tag-name { display: none; }   /* the shape alone keeps the team */
.tv-live-grid.is-compact .tv-live-card { padding: clamp(8px, 1.2vh, 14px) clamp(10px, 1.2vw, 20px); border-radius: 14px; }
.tv-live-grid.is-compact .tv-live-id { font-size: clamp(14px, 1.4vw, 24px); }
.tv-live-grid.is-compact .tv-live-teams { gap: 8px; margin: 4px 0; }
.tv-live-grid.is-compact .tv-lt { font-size: clamp(13px, 1.25vw, 24px); }
.tv-live-grid.is-compact .tv-live-score { font-size: clamp(30px, 4.2vw, 72px); }
.tv-live-grid.is-compact .tv-live-games { font-size: clamp(11px, 1vw, 18px); }

/* a hot court stands out even inside the grid, so the eye finds the drama */
.tv-live-card.is-climax { border-color: rgba(255,107,53,0.55); box-shadow: inset 0 0 90px -50px rgba(255,107,53,0.5); }
.tv-live-card.is-deuce  { border-color: rgba(245,200,66,0.6);  box-shadow: inset 0 0 90px -50px rgba(245,200,66,0.55); }
.tv-live-card.is-climax .tv-live-id { color: #FF8A4C; }
.tv-live-card.is-deuce  .tv-live-id { color: var(--gold); }

/* ── Fullscreen button (TV mode only) ── */
.tv-fs-btn { display: none; }
body.tv-mode .tv-fs-btn {
  display: flex;
  position: fixed;
  top: clamp(14px, 2.5vh, 28px);
  right: clamp(14px, 2.5vw, 32px);
  z-index: 4010;
  width: 52px; height: 52px;
  align-items: center; justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--border2);
  background: rgba(20,20,32,0.72);
  backdrop-filter: blur(10px);
  color: var(--text2);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: opacity 0.5s ease, background 0.2s, color 0.2s, transform 0.15s;
}
body.tv-mode .tv-fs-btn:hover {
  background: rgba(32,32,48,0.9);
  color: var(--text);
  transform: scale(1.06);
}
body.tv-mode .tv-fs-btn.is-on {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}
/* a projector should show the scoreboard, not a button — fade out when
   nobody is touching the machine, any input brings it straight back */
body.tv-mode .tv-fs-btn.idle { opacity: 0; }
body.tv-mode .tv-fs-btn.idle:hover { opacity: 1; }
body.tv-mode .tv-fs-btn:focus-visible { opacity: 1; }

/* ── VS panel — one live match, big: pair vs pair with photos + live score ── */
.tv-vs-panel { justify-content: center; }
.tv-vs-top {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(10px, 1.6vw, 28px); margin-bottom: clamp(14px, 3vh, 44px);
}
.tv-vs-court {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(24px, 3.4vw, 60px);
  letter-spacing: 2px; color: var(--accent); text-shadow: 0 0 24px var(--accent-glow);
}
.tv-vs-round { color: var(--muted); font-weight: 700; letter-spacing: 1px; font-size: clamp(13px, 1.5vw, 26px); }
.tv-vs-game {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(18px, 2.2vw, 40px); letter-spacing: 2px;
  background: rgba(255,255,255,0.06); border: 1px solid var(--border2); border-radius: 12px;
  padding: 2px 14px;
}
.tv-vs-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: clamp(16px, 3vw, 64px); }
.tv-vs-side { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.tv-vs-faces { display: flex; justify-content: center; gap: clamp(8px, 1.4vw, 24px); margin-bottom: clamp(8px, 1.5vh, 22px); }
.tv-vs-faces .pav { --pav-size: clamp(84px, 12vw, 200px) !important; border-width: 3px; }
.tv-vs-names { font-size: clamp(22px, 3vw, 54px); font-weight: 800; text-align: center; line-height: 1.15; }
.tv-vs-names.red  { color: var(--red);  }
.tv-vs-names.blue { color: var(--blue); }
.tv-vs-mid { display: flex; flex-direction: column; align-items: center; gap: clamp(4px, 1vh, 10px); }
.tv-vs-vs { font-family: 'Bebas Neue', sans-serif; font-size: clamp(28px, 3.4vw, 64px); letter-spacing: 3px; color: var(--muted); }
.tv-vs-score { font-family: 'Bebas Neue', sans-serif; font-size: clamp(70px, 13vw, 240px); line-height: 0.85; white-space: nowrap; }
.tv-vs-score .red  { color: var(--red); text-shadow: 0 0 40px var(--red-glow); }
.tv-vs-score .blue { color: var(--blue); }
.tv-vs-score .sep  { color: var(--muted); margin: 0 0.1em; }
.tv-vs-g1 { font-size: clamp(13px, 1.5vw, 26px); color: var(--muted); font-weight: 700; letter-spacing: 1px; }
.tv-vs-nowplaying {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(38px, 6.5vw, 120px); line-height: 0.9;
  letter-spacing: 3px; text-align: center; color: var(--accent);
  text-shadow: 0 0 40px var(--accent-glow); animation: tvNowPulse 1.6s ease infinite;
}
@keyframes tvNowPulse { 50% { opacity: 0.55; } }
@media (prefers-reduced-motion: reduce) { .tv-vs-nowplaying { animation: none; } }
.tv-vs-count { text-align: center; color: var(--muted); font-size: clamp(12px, 1.3vw, 22px); font-weight: 600; letter-spacing: 1px; margin-top: clamp(10px, 2vh, 26px); }

/* ── Climax highlight on the VS panel ── */
.tv-vs-climax {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(14px, 1.6vw, 26px); letter-spacing: 2px;
  padding: 2px 14px; border-radius: 20px; color: #FF8A4C;
  background: rgba(255,107,53,0.15); border: 1px solid rgba(255,107,53,0.5);
  animation: tvCxPulse 1.1s ease infinite;
}
.tv-vs-climax.deuce { color: #FBBF24; background: rgba(245,200,66,0.15); border-color: rgba(245,200,66,0.55); }
@keyframes tvCxPulse { 50% { opacity: 0.5; } }
.tv-vs-panel.is-climax {
  box-shadow: inset 0 0 200px -60px rgba(255,107,53,0.35);
  animation: tvCxGlow 1.6s ease infinite;
}
@keyframes tvCxGlow { 50% { box-shadow: inset 0 0 240px -50px rgba(255,107,53,0.5); } }
@media (prefers-reduced-motion: reduce) { .tv-vs-climax, .tv-vs-panel.is-climax { animation: none; } }

/* ── Transient announcement panels (match finished / end of game 1) ── */
.tv-event {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(20px, 4vh, 48px); text-align: center; height: 100%;
  animation: tvEvIn 0.4s cubic-bezier(0.34,1.56,0.64,1);
}
@keyframes tvEvIn { from { transform: scale(0.9); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.tv-ev-tag {
  font-family: 'Space Grotesk', sans-serif; font-weight: 700; letter-spacing: 3px;
  font-size: clamp(14px, 2vw, 30px); color: var(--muted); text-transform: uppercase;
}
.tv-ev-names { display: flex; align-items: center; gap: clamp(16px, 3vw, 48px); flex-wrap: wrap; justify-content: center; }
.tv-ev-side { font-family: 'Bebas Neue', sans-serif; font-size: clamp(34px, 6vw, 88px); letter-spacing: 2px; line-height: 1; opacity: 0.55; }
.tv-ev-side.red  { color: var(--red); }  .tv-ev-side.blue { color: var(--blue); }
.tv-ev-side.win  { opacity: 1; text-shadow: 0 0 40px currentColor; }
.tv-ev-score { font-family: 'Bebas Neue', sans-serif; font-size: clamp(26px, 4vw, 60px); color: var(--text2); letter-spacing: 2px; }
.tv-ev-result {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(44px, 8vw, 120px); letter-spacing: 4px; line-height: 1;
  padding: 6px 40px; border-radius: 22px;
}
.tv-ev-result.red  { color: var(--red);  background: rgba(255,59,92,0.12);  border: 2px solid rgba(255,59,92,0.4); text-shadow: 0 0 50px rgba(255,59,92,0.5); }
.tv-ev-result.blue { color: var(--blue); background: rgba(59,142,255,0.12); border: 2px solid rgba(59,142,255,0.4); text-shadow: 0 0 50px rgba(59,142,255,0.5); }
.tv-ev-result.draw { color: var(--gold); background: rgba(245,200,66,0.12); border: 2px solid rgba(245,200,66,0.4); }
.tv-ev-big { font-family: 'Bebas Neue', sans-serif; font-size: clamp(50px, 9vw, 150px); letter-spacing: 6px; color: var(--gold); line-height: 1; text-shadow: 0 0 50px rgba(245,200,66,0.4); }
.tv-ev-g1 { font-family: 'Bebas Neue', sans-serif; font-size: clamp(60px, 11vw, 180px); letter-spacing: 3px; line-height: 1; }
.tv-ev-g1 .red { color: var(--red); } .tv-ev-g1 .blue { color: var(--blue); } .tv-ev-g1 .sep { color: rgba(255,255,255,0.25); padding: 0 clamp(8px,1.5vw,20px); }
.tv-ev-note { font-size: clamp(16px, 2.4vw, 34px); color: var(--text2); font-weight: 600; letter-spacing: 1px; }
.tv-ev-note b.red { color: var(--red); } .tv-ev-note b.blue { color: var(--blue); }
@media (prefers-reduced-motion: reduce) { .tv-event { animation: none; } }
