/* Shared TV / kiosk board styles — used by BOTH the event board (Components/Pages/Events/LeaderboardTv.razor)
   and the league board (Components/Pages/Leagues/StandingsTv.razor) via <HeadContent> <link>. Kept as one
   file (not per-page scoped .razor.css) so the two boards can never drift apart.

   Full-screen, large-type, high-contrast for clubhouse projectors. Palette on the root wrapper class
   (.tv-board). A TV can't scroll, so the field is PAGED: each data row is exactly 1/var(--tv-rows) of the
   rows area, so PageSize rows always fill the screen with no clipping at any resolution; pages flip on a
   timer. Matches the public leaderboard's deliberate dark-navy surface. */

.tv-board {
    --tv-bg: #071326;
    --tv-row-alt: #0d1e39;
    --tv-border: #28446f;
    --tv-text: #f8fbff;
    --tv-text-soft: #c5d6ef;
    --tv-text-muted: #9db3d2;
    --tv-accent: #56c7ff;
    --tv-leader: #9ee7ff;
    --tv-live: #8df3c6;

    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    background: radial-gradient(circle at 14% 0%, #133159 0%, #071326 56%, #040c1b 100%);
    color: var(--tv-text);
    font-variant-numeric: tabular-nums;
    overflow: hidden;
}

/* ── header ─────────────────────────────────────────────── */
.tv-head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.2vw 2.4vw;
    /* Broadcast-grade header: a rich brand-navy field with a soft accent glow at the top-left and a
       crisp accent underline — high contrast so the title + club mark read from across the room. */
    border-bottom: 2px solid var(--tv-accent);
    background-color: #071528;
    background-image:
        radial-gradient(150% 130% at 0% 0%, rgba(86, 199, 255, 0.12) 0%, transparent 55%),
        linear-gradient(180deg, #0b213f 0%, #071528 100%);
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.38);
}
/* Club-tier event photo backdrop (gated by branding.event_image). The near-opaque gradient in the
   inline style keeps it a subtle texture — never a muddy smear over the title — and we anchor it to
   the right, away from the club mark + event name. A logo-style image all but disappears (correct:
   the club mark carries the branding); a real photo adds a faint rich texture. */
.tv-head--photo {
    background-size: cover;
    background-position: center right;
    background-color: #071528;
}

.tv-head-left { display: flex; align-items: center; gap: 1.6vw; min-width: 0; }
/* Always sit the club logo on a white chip (like the sponsor logos) so a transparent or dark-on-dark
   logo is legible on the dark board — not just clubs whose logo image happens to bake in a white bg. */
.tv-org-logo {
    height: 4vw; max-height: 68px; width: auto;
    border-radius: 8px;
    background: #fff;
    padding: 0.5vh 0.6vw;
    object-fit: contain;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);   /* lift the club mark off the header like a broadcast bug */
}
.tv-head-left > div { min-width: 0; overflow: hidden; }
.tv-event-name {
    font-size: clamp(1.5rem, 3vw, 3.2rem);
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.01em;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.55);   /* keep the title crisp over any photo texture */
    /* A long sponsor-inclusive title must NOT wrap — wrapping grows the fixed header and steals row height. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 62vw;
}
.tv-panel-title {
    display: flex;
    align-items: baseline;
    gap: 0.8vw;
    font-size: clamp(0.85rem, 1.4vw, 1.5rem);
    color: var(--tv-accent);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.tv-range { color: var(--tv-text-muted); font-weight: 500; letter-spacing: 0.04em; }

.tv-head-right { flex: 0 0 auto; }
.tv-live {
    display: inline-flex;
    align-items: center;
    gap: 0.6vw;
    font-size: clamp(1rem, 1.7vw, 2rem);
    font-weight: 800;
    letter-spacing: 0.12em;
    color: var(--tv-live);
}
.tv-live-dot {
    width: 0.9em; height: 0.9em; border-radius: 50%;
    background: var(--tv-live);
    animation: tv-pulse 1.8s infinite;
}
@keyframes tv-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(141, 243, 198, 0.55); }
    70%  { box-shadow: 0 0 0 0.7vw rgba(141, 243, 198, 0); }
    100% { box-shadow: 0 0 0 0 rgba(141, 243, 198, 0); }
}
.tv-final {
    font-size: clamp(1rem, 1.7vw, 2rem);
    font-weight: 800;
    letter-spacing: 0.12em;
    color: var(--tv-text-muted);
}

/* ── body: header row + paged data rows that fill the height ─ */
.tv-body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 0 2vw;
}
/* justify-content:center so a short page (small field / partial last page) sits centered rather than
   top-packed above a big void. A full page's rows sum to 100%, so centering is a no-op there. */
.tv-rows { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; overflow: hidden; }

/* Paging transition — each rotation the board's @key changes, so Blazor re-mounts this node and
   replays the enter animation: a gentle fade + slight upward slide as the next page/pool/flight
   (or the sponsor wall) arrives. Purely visual; disabled under prefers-reduced-motion below. */
.tv-rows--enter,
.tv-sponsor-wall { animation: tv-page-in 520ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
@keyframes tv-page-in {
    from { opacity: 0; transform: translateY(1.6vh); }
    to   { opacity: 1; transform: translateY(0); }
}

.tv-row {
    display: flex;
    align-items: center;
    gap: 1vw;
    padding: 0 1.4vw;
    border-bottom: 1px solid rgba(40, 68, 111, 0.5);
}
/* Each data row is exactly one slot of the rows area → PageSize rows fill the screen, never clip. */
.tv-rows .tv-row { height: calc(100% / var(--tv-rows, 12)); }
.tv-rows .tv-row:nth-child(even) { background: var(--tv-row-alt); }

.tv-row-head {
    flex: 0 0 auto;
    padding-top: 1.1vh;
    padding-bottom: 1.1vh;
    border-bottom: 2px solid var(--tv-border);
}
.tv-row-head span {
    font-size: clamp(0.75rem, 1.2vw, 1.3rem);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--tv-text-muted);
}

.tv-c-rank  { flex: 0 0 8%;  text-align: center; }
/* Flex column so a team row's name + member line stack with real spacing (not squished together). */
.tv-c-name  { flex: 1 1 auto; min-width: 0; overflow: hidden; display: flex; flex-direction: column; justify-content: center; gap: 0.3em; }
.tv-c-thru  { flex: 0 0 14%; text-align: center; color: var(--tv-text-soft); }
.tv-c-score { flex: 0 0 16%; text-align: right; }

/* Detailed stroke board (LeaderboardTv only): per-round columns + Gross (reference) + Net (the ranked
   value) beside the net to-par ranking (.tv-c-score, the hero). Scoped under .tv-body--detailed so the
   org-wide TV board and league standings board are untouched. Net is full-prominence (it's what the field
   is ranked by); the per-round and gross columns are secondary/muted. */
.tv-c-rd    { flex: 0 0 8%;  text-align: center; }
.tv-c-gross { flex: 0 0 10%; text-align: right; }
.tv-c-net   { flex: 0 0 10%; text-align: right; }
.tv-body--detailed .tv-c-thru  { flex-basis: 9%; }
.tv-body--detailed .tv-c-score { flex-basis: 13%; }
.tv-body--detailed .tv-rows .tv-row .tv-c-rd,
.tv-body--detailed .tv-rows .tv-row .tv-c-gross {
    font-size: clamp(0.9rem, 1.7vw, 2rem);
    font-weight: 600;
    color: var(--tv-text-soft);
}

/* Individual Net side-competition board (LeaderboardTv only): its own per-player columns
   (Pos / Player / Team / Hcp / Gross / Net / Thru). Scoped under .tv-body--indivnet so the standard,
   team, org-wide and league boards are untouched. Net is the ranked hero; team/hcp/gross are secondary. */
.tv-body--indivnet .tv-c-team  { flex: 0 0 20%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--tv-text-soft); }
.tv-body--indivnet .tv-c-hcp   { flex: 0 0 8%;  text-align: center; color: var(--tv-text-soft); }
.tv-body--indivnet .tv-c-gross { flex: 0 0 11%; text-align: center; color: var(--tv-text-soft); }
.tv-body--indivnet .tv-c-net   { flex: 0 0 12%; text-align: right; }
.tv-body--indivnet .tv-c-thru  { flex: 0 0 11%; }
.tv-body--indivnet .tv-rows .tv-row .tv-c-team,
.tv-body--indivnet .tv-rows .tv-row .tv-c-hcp,
.tv-body--indivnet .tv-rows .tv-row .tv-c-gross {
    font-size: clamp(0.9rem, 1.7vw, 2rem);
    font-weight: 600;
}

.tv-rows .tv-row span {
    font-size: clamp(1.15rem, 2.4vw, 2.9rem);
    font-weight: 700;
}
.tv-rows .tv-c-rank { color: var(--tv-text-soft); }

.tv-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1.1; }
/* Selector MUST outweigh `.tv-rows .tv-row span` (0,2,1) or the small/muted sub-line is silently
   overridden back to full team-name size+weight — the exact squished-team-row bug this is meant to fix. */
.tv-rows .tv-row .tv-name-sub {
    display: block;
    font-size: 0.46em;
    font-weight: 500;
    line-height: 1.15;
    color: var(--tv-text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Row-state modifiers MUST outweigh the base `.tv-rows .tv-row span` (0,2,1) and `.tv-rows .tv-c-rank`
   (0,2,0) — same silent-override trap already fixed above for .tv-name-sub. Prefixing with
   `.tv-rows .tv-row` reaches (0,3,1): the leader's rank cell goes gold (not soft-blue) and no-score
   rows drop to weight 500 (not the base bold 700). */
.tv-rows .tv-row.tv-row-leader span { color: var(--tv-leader); }
.tv-rows .tv-row.tv-row-noscore span { color: var(--tv-text-muted); font-weight: 500; }
/* Keep the leader's member sub-line quietly muted rather than following the row gold (0,4,0 > 0,3,1). */
.tv-rows .tv-row.tv-row-leader .tv-name-sub { color: var(--tv-text-muted); }

/* ── ticker: whole field scrolling along the bottom ──────── */
.tv-ticker {
    flex: 0 0 auto;
    height: 6.5vh;
    min-height: 44px;
    overflow: hidden;
    border-top: 2px solid var(--tv-border);
    background: rgba(4, 12, 27, 0.92);
    display: flex;
    align-items: center;
}
.tv-ticker-track {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    will-change: transform;
    animation-name: tv-marquee;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}
@keyframes tv-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }   /* content is rendered twice → seamless loop */
}
.tv-tick {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5vw;
    padding: 0 1.6vw;
    border-right: 1px solid rgba(40, 68, 111, 0.6);
    font-size: clamp(0.85rem, 1.5vw, 1.5rem);
}
.tv-tick-rank { color: var(--tv-text-muted); font-weight: 700; }
.tv-tick-name { color: var(--tv-text-soft); font-weight: 700; }
.tv-tick-score { color: var(--tv-accent); font-weight: 800; }

/* ── footer ─────────────────────────────────────────────── */
.tv-foot {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.9vw 2.4vw;
    border-top: 2px solid var(--tv-border);
    background: rgba(7, 19, 38, 0.9);
}
.tv-foot-sponsor { display: flex; align-items: center; gap: 1vw; min-width: 0; }
.tv-foot-label {
    font-size: clamp(0.7rem, 1vw, 1.1rem);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--tv-text-muted);
}
.tv-foot-logo { height: 2.6vw; max-height: 44px; width: auto; }
.tv-foot-name { font-size: clamp(0.9rem, 1.3vw, 1.5rem); font-weight: 700; color: var(--tv-text-soft); }
/* Back9Ops attribution — the approved wordmark asset (white artwork for the dark board), not plain text. */
.tv-foot-brand-logo { height: 2.4vw; max-height: 34px; width: auto; opacity: 0.92; }
/* Pool tag on ticker entries so a pooled league's scroll shows which pool each rank belongs to. */
.tv-tick-pool { color: var(--tv-text-muted); font-weight: 600; margin-right: 0.35em; }

/* ── sponsor wall interstitial + rotating footer slot ────── */
/* Full-screen "Thank you to our sponsors" view shown once per rotation cycle. Logos sit on light
   chips so dark logos stay visible on the dark board. */
.tv-sponsor-wall {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3.5vh;
    padding: 4vh 4vw;
    overflow: hidden;
}
.tv-sponsor-wall-label {
    font-size: clamp(1.2rem, 2.4vw, 2.6rem);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--tv-accent);
}
.tv-sponsor-presenting {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1vh;
}
.tv-sponsor-presenting-logo {
    max-height: 18vh;
    max-width: 40vw;
    width: auto;
    background: #fff;
    border-radius: 14px;
    padding: 1.2vh 1.6vw;
}
.tv-sponsor-presenting-name { font-size: clamp(1.3rem, 2.6vw, 2.8rem); font-weight: 800; }
.tv-sponsor-presenting-tag {
    font-size: clamp(0.75rem, 1.1vw, 1.2rem);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--tv-text-muted);
}
/* A GRID that fills the screen, not a centred row that floats in it.
   Six columns x four rows = 24 sponsors per card, which is what keeps a 124-sponsor roll to six
   cards (about two minutes) instead of twenty-one (about seven). */
/* Flex rather than grid, for one reason: cards are balanced (21/21/21/21/20/20 for 124), so the
   final row of a card is often partly filled. A grid leaves those stragglers hard against the left
   edge, which reads as a rendering fault. flex-wrap + justify-content centres them, so a short row
   looks deliberate. Six per row is enforced by the item width, not by a column count. */
.tv-sponsor-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-content: center;
    gap: 1.1vh 0.9vw;
    width: 94vw;
}
.tv-sponsor-chip {
    flex: 0 0 calc((100% - 5 * 0.9vw) / 6);
    max-width: calc((100% - 5 * 0.9vw) / 6);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5vh;
    min-width: 0;
}
/* The mark itself is the coloured plate — see .tv-plate-c0..c7 below. */
.tv-sponsor-logo {
    width: 100%;
    height: 9vh;
    max-height: 9vh;
    object-fit: contain;
}

.tv-foot-rotating { display: flex; align-items: center; gap: 0.8vw; min-width: 0; }
.tv-foot-rotating .tv-foot-logo { background: #fff; border-radius: 8px; padding: 0.3vh 0.4vw; }

/* ── empty / loading ────────────────────────────────────── */
.tv-empty {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.8vh;
    text-align: center;
    padding: 4vh 2vw;
}
.tv-empty-title { font-size: clamp(1.4rem, 3vw, 3rem); font-weight: 800; }
.tv-empty-sub { font-size: clamp(1rem, 1.6vw, 1.6rem); color: var(--tv-text-muted); }

/* Respect reduced-motion: stop the ticker scroll + live pulse for sensitive viewers. */
@media (prefers-reduced-motion: reduce) {
    .tv-ticker-track { animation: none; }
    .tv-live-dot { animation: none; }
    .tv-rows--enter,
    .tv-sponsor-wall { animation: none; }
    .tv-org-progress { animation: none; width: 100%; opacity: 0.4; }
}

/* ── ORG-WIDE board: bottom "Live events" rotation strip (OrgLeaderboardTv.razor) ──────────────
   Rendered into the <TvBoard> Footer slot on the org-wide board. Uses the same .tv-board design
   tokens so it can never drift from the board it sits under.
   NOTE: the progress-fill duration (15s) mirrors OrgLeaderboardTv.RotateSeconds — keep the two in sync. */
.tv-org-strip {
    flex: 0 0 auto;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 2vw;
    padding: 1vw 2.4vw;
    border-top: 1px solid var(--tv-border);
    background: rgba(0, 0, 0, 0.22);
}
.tv-org-segs {
    display: flex;
    align-items: center;
    gap: 0.8vw;
    min-width: 0;
    overflow: hidden;
    flex-wrap: nowrap;
}
.tv-org-strip-label {
    font-size: 1vw;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--tv-text-muted);
    white-space: nowrap;
    margin-right: 0.4vw;
}
.tv-org-seg {
    font-size: 1.2vw;
    color: var(--tv-text-soft);
    padding: 0.5vw 1.1vw;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--tv-border);
    white-space: nowrap;
    max-width: 20vw;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tv-org-seg.is-active {
    color: #04101f;
    font-weight: 800;
    border-color: transparent;
    background: linear-gradient(90deg, var(--tv-accent), var(--tv-leader));
    box-shadow: 0 0.3vw 1.2vw rgba(86, 199, 255, 0.35);
}
.tv-org-strip-right {
    display: flex;
    align-items: center;
    gap: 1.4vw;
    white-space: nowrap;
    flex: 0 0 auto;
}
.tv-org-url {
    font-size: 1.3vw;
    font-weight: 700;
    color: var(--tv-accent);
    letter-spacing: 0.01em;
}
.tv-org-brand {
    font-size: 1vw;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--tv-text-muted);
}
.tv-org-progress {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 0.32vw;
    width: 0;
    background: linear-gradient(90deg, var(--tv-accent), var(--tv-live));
    animation: tv-org-fill 15s linear forwards;
}
.tv-org-progress--paused {
    /* Free org / static board — no live countdown; a subtle full bar instead of an animating one. */
    width: 100%;
    animation: none;
    opacity: 0.4;
}
@keyframes tv-org-fill {
    from { width: 0; }
    to   { width: 100%; }
}
.tv-org-url--idle {
    margin-top: 2vh;
    font-size: 1.6vw;
    font-weight: 700;
    color: var(--tv-accent);
}

/* ════════════════════════════════════════════════════════════════════
   SPONSOR PLATE COLOURS

   A wall of identical cream nameplates on navy reads as a spreadsheet.
   Most sponsors at a community outing have no artwork, so the plate IS
   the wall — and it should look like a row of painted tee signs, not a
   list. Each business gets one of eight colours, picked from its row id
   so the SAME business is the SAME colour every time it comes round,
   which also helps someone spot their own sign.

   Pastels, not saturated hues: the text on top is near-black, and these
   all clear 4.5:1 against it. Logos keep a white plate — sponsor artwork
   is drawn for white and must not be tinted.
   ════════════════════════════════════════════════════════════════════ */
.tv-sponsor-logo.sponsor-mark-plate {
    border-width: 3px;
    border-radius: 10px;
    padding: 0.6vh 0.5vw;
}

.tv-sponsor-logo.sponsor-mark-plate .sponsor-plate-text {
    font-size: clamp(0.62rem, 0.95vw, 1.15rem);
    -webkit-line-clamp: 4;
}

.tv-plate-c0.sponsor-mark-plate { background: #FFE0B2; }  /* amber   */
.tv-plate-c1.sponsor-mark-plate { background: #C8E6C9; }  /* green   */
.tv-plate-c2.sponsor-mark-plate { background: #BBDEFB; }  /* blue    */
.tv-plate-c3.sponsor-mark-plate { background: #F8BBD0; }  /* pink    */
.tv-plate-c4.sponsor-mark-plate { background: #FFF59D; }  /* yellow  */
.tv-plate-c5.sponsor-mark-plate { background: #D1C4E9; }  /* violet  */
.tv-plate-c6.sponsor-mark-plate { background: #B2EBF2; }  /* cyan    */
.tv-plate-c7.sponsor-mark-plate { background: #FFCCBC; }  /* coral   */

/* Name under each plate, on the dark board rather than inside the card. */
.tv-sponsor-chip-name {
    font-size: clamp(0.6rem, 0.85vw, 1rem);
    font-weight: 700;
    color: var(--tv-text-soft);
    text-align: center;
    line-height: 1.15;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.tv-sponsor-progress {
    font-size: clamp(0.7rem, 1.1vw, 1.15rem);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--tv-text-muted);
    font-variant-numeric: tabular-nums;
}
