@font-face {
    font-family: "Overpass Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/OverpassMono-Regular.woff2") format("woff2");
}

@font-face {
    font-family: "DSEG7Classic";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/DSEG7Classic-Regular.woff2") format("woff2");
}

@font-face {
    font-family: "Share Tech Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/ShareTechMono-Regular.woff2") format("woff2");
}

@font-face {
    font-family: "Orbitron";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/Orbitron-Regular.woff2") format("woff2");
}

@font-face {
    font-family: "Roboto Mono";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/RobotoMono-Regular.woff2") format("woff2");
}

@font-face {
    font-family: "DSEG14Classic";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/DSEG14Classic-Regular.woff2") format("woff2");
}

/* ── Theme defaults (overridden by per-page <style> block) ─────────────────── */

:root {
    --color-bg: #0d0d0d;
    --color-header-bg: #1a1a1a;
    --color-header-border: #2e2e2e;
    --color-header-label: #ffffff;
    --color-header-value: #e0e0e0;
    --color-th-text: #666666;
    --color-th-bg: #1a1a1a;
    --color-row-odd: #141414;
    --color-row-even: #202020;
    --color-row-text: #e0e0e0;
    --color-time: #ffd700;
    --color-delta-better: #4caf50;
    --color-delta-worse: #808080;
    --color-podium-gold: #545454;
    --color-podium-silver: #424242;
    --color-podium-bronze: #343434;
    /* EVENT/HEAT are one phrase at one size (see `#header_event_cell` below),
       so the word and the number read from a single variable. `fitHeaderCells()`
       overrides it per cell when a long label would not fit. */
    --header-num-size: 4.5vh;
    --font-family: "Overpass Mono";
    --font-digits: "DSEG7Classic";
    --font-timing: "Overpass Mono";
}

/* ── Reset ────────────────────────────────────────────────────────────────── */

html,
body {
    margin: 0;
    padding: 0;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    background: var(--color-bg);
    font-family: var(--font-family), monospace;
}

/* ── Main layout — flex column, full screen ───────────────────────────────── */

.timing-outer {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
    position: relative;
    z-index: 100;
}

/* ── Header bar — one flex cell per item ──────────────────────────────────── */

.timing-header-bar {
    display: flex;
    align-items: stretch;
    flex-shrink: 0;
    background-color: var(--color-header-bg);
    height: 65px;
    overflow: hidden;
    border-bottom: 1px solid var(--color-header-border);
}

/* `1vw` a side, matching the Qt board's `_HDR_PAD_X = 0.01`. It was `2vw`: that is a
   fraction of the *window*, so it costs the same on every cell however narrow, and
   five cells at 2vw a side spend a fifth of the bar on whitespace — which is what
   squeezed the header's text. The dividers already separate the cells. */
.header_cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0.8vh 1vw;
    border-left: 1px solid var(--color-header-border);
    white-space: nowrap;
    transition: opacity 0.6s;
}

.header_cell:first-child {
    border-left: none;
}

/* The event-name cell expands to fill the remaining space. (`.header_cell_grow` sat
   here too, for a meet-title cell both displays have now dropped — the title is on
   the splash.) */
.header_cell_name {
    flex: 1;
    min-width: 0;
    background-color: var(--color-header-bg);
    align-items: center;
    overflow: hidden;
}

#event_name {
    max-width: 100%;
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
    line-height: 1.2;
    font-size: 3vh;
    text-align: center;
}
/* No width-based override here on purpose. `3vw` on a short viewport was written for
   a phone in landscape, where the screen is short *and* narrow — but it keys on
   height and sizes by width, so a browser window dragged short but left wide made
   the event name jump *up*: 15px at 501px tall, 42px at 500px. It lives in
   `scoreboard_base.html` now, with the rest of the phone's short-viewport rules, so
   the kiosk shrinks monotonically. */

.header_label {
    font-size: 1.8vh;
    line-height: 1;
    color: var(--color-header-label);
    letter-spacing: 0.08em;
}

.header_value {
    font-size: 4vh;
    color: var(--color-header-value);
}

/* DSEG7 for the event/heat number digits.

   `--color-header-value`, not `--color-header-label`: the label colour is the
   board's accent blue and belongs to the EVENT/HEAT *words*, which is what tells
   them apart from their numbers. This used to be the label colour on this page and
   `header_value` on the Qt board — a divergence that existed only because both were
   near-identical greys and it made no visible difference. It does now. */
#current_event,
#current_heat {
    font-family: var(--font-digits), monospace;
    font-size: var(--header-num-size);
    line-height: 1;
    color: var(--color-header-value);
}

/* ── EVENT / HEAT: the word beside its number ─────────────────────────────────
   The Qt board's `HeaderCell`, in CSS. This cell used to be a *column* — a 12px
   word stacked over a 48px number — which reads as a caption at a desk and is
   simply not there across a pool deck, the only distance this board is read at.
   Inline and equal-sized, `EV 12` reads as one phrase.

   What the size difference used to do — separate the word from its number — the
   accent blue does instead, which is why `header_label` and `header_value` must
   stay distinguishable in any theme. Both colours are already the ones Qt uses.

   The gap is `0.45em` of the shared size, matching `_HDR_INLINE_GAP`. Centring
   stays the browser's: the Qt cell leads its bar and is left-aligned for that
   reason, while this one sits after the meet-title cell (docs/architecture/scoreboard-parity.md). */
#header_event_cell,
#header_heat_cell {
    flex-direction: row;
    align-items: center;
    /* Hard left, as `HeaderCell._relayout` packs its pair from `rect.x()`. Any slack
       a short phrase leaves goes to the right, so EVENT and HEAT start at the same
       offset in their cells however wide the words are. */
    justify-content: flex-start;
}
#header_event_cell .header_label,
#header_heat_cell .header_label {
    font-size: var(--header-num-size);
    margin-right: 0.45em;
}

/* Grow the header bar on tall viewports so the Event/Heat digits can
   match the clock's height without cropping the label above them. */
@media (min-height: 700px) {
    .timing-header-bar {
        height: 85px;
    }
    .header_cell {
        padding: 6px 1vw;
    }
}

/* ── Fixed header cell widths — `/live` only ──────────────────────────────────
   Opt-in, via a class on the bar: this stylesheet is shared with scoreboard.html,
   live-mobile.html and results.html, and only the kiosk page wants this.

   Content-sized cells mean the bar reflows whenever the event number gains a digit
   or the race clock appears, dragging the event name and both clocks sideways on
   every heat. Fixed shares hold everything still. `scoreboard/board.py` carries the
   same five numbers as layout stretch weights — they sum to 100, so they are the
   percentages directly. See docs/architecture/scoreboard-parity.md.

   An idle board shows just the two clocks: event/heat/name are `display: none` until a
   heat loads, and nothing claims their share in the meantime. */

.header_cells_fixed .header_cell {
    /* The 1vw padding has to sit *inside* the share, and a flex item defaults to
       `min-width: auto` — which would let a long event name push its cell past its
       share and shove everything to the right of it along anyway. */
    box-sizing: border-box;
    min-width: 0;
}

/* The five shares, and `scoreboard/board.py`'s `_HW_*` weights, are one set of
   numbers. EVENT and HEAT are wide because their word sits *beside* the number now
   rather than above it; the wall clock gives up what they take, being the one cell
   nobody reads a race off. Measured on the Qt board, not guessed: at these weights
   `EV 12` and `HT 7` both reach the full digit size, and the race clock ends up with
   more room than it had at 16% of the old split. */
.header_cells_fixed #header_event_cell {
    flex: 0 0 13%;
}
.header_cells_fixed #header_heat_cell {
    flex: 0 0 13%;
}
.header_cells_fixed .header_cell_name {
    flex: 0 0 48%;
}
.header_cells_fixed #header_chrono_cell {
    flex: 0 0 16%;
}
.header_cells_fixed #header_clock_cell {
    flex: 0 0 10%;
}

/* ── Scoreboard table — fills remaining height ────────────────────────────── */

.timing-content {
    flex: 1;
    overflow: hidden;
    position: relative;
    transition: opacity 0.5s;
}

#timing-bg {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
}

.timing-table {
    position: relative;
    z-index: 1;
    width: 100%;
    height: 100%;
    border-spacing: 0;
    table-layout: fixed;
}

table.timing-table td {
    overflow: hidden;
    white-space: pre;
    max-width: 0px;
    width: 0px;
    transition:
        background-color 0.5s ease,
        transform 0.5s ease;
}

table.timing-table th {
    overflow: hidden;
    white-space: nowrap;
}

.timing-header {
    font-size: 3vh;
    color: var(--color-th-text);
    background-color: var(--color-th-bg);
}

.timing-row-odd {
    font-size: 5vh;
    color: var(--color-row-text);
    background-color: var(--color-row-odd);
}

.timing-row-even {
    font-size: 5vh;
    color: var(--color-row-text);
    background-color: var(--color-row-even);
}

/* ── DSEG7Classic for lane numbers and place/position only ───────────────── */

table.timing-table tbody td:first-child,
[id^="lane_place"] {
    font-family: var(--font-digits), monospace;
}

/* ── Column widths — place and time are animated, name fills the rest ─────── */

.timing-anim {
    transition:
        width 0.5s ease,
        max-width 0.5s ease,
        transform 0.5s ease;
}

.lane-column {
    width: 5vw;
}
.place-column {
    width: 0;
    max-width: 0;
}
.time-column {
    width: 0;
    max-width: 0;
}
.delta-column {
    width: 0;
    max-width: 0;
}
.club-column {
    width: 8vw;
    padding-right: 1vw;
}
[id^="lane_club"] {
    padding-right: 1vw;
}
/* name column: no explicit width — fills remaining space; padding centers content symmetrically */
#name-column,
.lane-name-cell {
    padding: 0 2vw;
    white-space: normal;
    vertical-align: middle;
}

.name-sub {
    display: block;
    font-size: 0.7em;
    opacity: 0.7;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.2;
}
.name-sub:empty {
    display: none;
}

/* The swimmer's own name, sized to fit by fitNameFontSize(). A measurable block so
   that pass can compare scroll width against client width; the ellipsis is the
   floor, for a name too long to shrink into the cell at all. Every display that
   renders a name uses this — the phone board, Results, and the kiosk — matching
   the Qt board's FitLabel. */
.name-primary {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── Display toggles ─────────────────────────────────────────────────────── */

/* A hidden column title keeps its cell and loses only its word. The grey behind
   the titles is the row's (`.timing-header`), and a browser paints a row's
   background inside each cell — so `visibility: hidden` took the grey with it and
   left a black hole in the band, which is what `show_laps` always does to Δ. */
.timing-table.hide-lane-header .lane-column,
.timing-table.hide-name-header #name-column,
.timing-table.hide-club-header .club-column,
.timing-table.hide-time-header #time-column,
.timing-table.hide-delta-header #delta-column,
.timing-table.hide-position-header #place-column {
    color: transparent;
}

.timing-table.hide-name #name-column,
.timing-table.hide-name .lane-name-cell {
    display: none;
}

.timing-table.hide-club .club-column,
.timing-table.hide-club [id^="lane_club"] {
    display: none;
}

.timing-table.hide-delta #delta-column,
.timing-table.hide-delta .td_delta {
    display: none;
}

.timing-table.hide-position #place-column,
.timing-table.hide-position [id^="lane_place"] {
    display: none;
}

/* ── Test session overlay ─────────────────────────────────────────────────── */

.test-overlay {
    position: fixed;
    bottom: 2.5vh;
    left: 50%;
    transform: translateX(-50%);
    color: var(--color-bg);
    padding: 0.6vh 2.5vw;
    border-radius: 6px;
    font-size: 2.2vh;
    font-weight: bold;
    letter-spacing: 0.15em;
    z-index: 200;
    pointer-events: none;
    white-space: nowrap;
    isolation: isolate;
}
.test-overlay::before {
    content: "";
    position: absolute;
    inset: 0;
    background-color: var(--color-row-text);
    opacity: 0.75;
    border-radius: 6px;
    z-index: -1;
}

/* ── Background (splash image) ────────────────────────────────────────────── */

.background {
    background-color: var(--color-bg);
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -100;
}

#splash_img {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 150;
    object-fit: contain;
    transition: opacity 3s ease;
}

/* ── Test controls ────────────────────────────────────────────────────────── */

.controls {
    position: fixed;
    top: 10px;
    left: 10px;
}

/* ── Time column — yellow; on podium rows the !important below overrides it ── */

#time-column,
.td_time {
    color: var(--color-time);
    font-family: var(--font-timing), monospace;
}

/* ── Time lock animation ──────────────────────────────────────────────────── */

[id^="lane_time"].time-running {
    color: #a0a0a0;
}

@keyframes time-lock-flash {
    0% {
        color: #ffffff;
    }
    100% {
        color: var(--color-time);
    }
}
[id^="lane_time"].time-locked {
    animation: time-lock-flash 0.8s ease-out forwards;
}

/* ── Seed-time delta ─────────────────────────────────────────────────────── */

/* Centred, like every other timing column. It was right-aligned while the delta
   was its only tenant; a lap count is one or two digits, and right-aligning that
   pushed it against the place column, where a bare `3` sat a glyph away from a
   `#3` and read as a rank. */
.td_delta {
    font-size: 5vh;
    text-align: center;
    font-family: var(--font-timing), monospace;
}
.delta-better {
    color: var(--color-delta-better);
}
.delta-worse {
    color: var(--color-delta-worse);
}

/* ── Lap count (shares the delta cell) ────────────────────────────────────────
   While a lane is swimming the delta cell carries the lengths it has completed;
   at the finish the delta takes the cell back. A lap is not a time and not a
   result, so it takes the header's accent blue — the colour this board already
   uses for "this is a label, not a number you race against" — while the delta
   keeps its better/worse green and grey. That contrast is what makes the swap
   legible without the column header ever moving. Both boards render this
   (`renderDelta` in scoreboard_base.html and live.html), so the rule lives here
   rather than twice. */
.td_delta.lap-count {
    color: var(--color-header-label);
}
/* The final stretch: the same number, in the timing colour the stopped chrono
   takes. Not an animation — the number is already the information, and this only
   has to say "this one is the last". It necessarily holds until the finish: once
   `splits + split_step >= expected_splits` the next thing the console reports *is*
   the finish, so no further split can change the cell. With touchpads at one end
   only that covers the last two lengths, because the swimmer is not seen in
   between. */
.td_delta.lap-count.lap-final {
    color: var(--color-time);
}

/* ── Podium highlight ─────────────────────────────────────────────────────── */

tr.podium-gold td {
    background-color: var(--color-podium-gold) !important;
}
tr.podium-silver td {
    background-color: var(--color-podium-silver) !important;
}
tr.podium-bronze td {
    background-color: var(--color-podium-bronze) !important;
}
