/*
    Layout: fullscreen -- the board on its own on a screen, with no race feed
    behind it (/LapCharts/LiveRaceFullscreen).

    Where the parts sit and how big they are; everything else is
    liveraceboard.css. The tower is the overlay's, scaled up, and takes the
    left of the screen under the header. Down the right, in frames (the
    component's, switched on by --framed): the race notifications, newest at
    the top, then the two closest battles above the club and the time, which
    keep the bottom-right corner.

    The layout stretches to the window rather than holding a 16:9 frame, so
    on a screen of another shape the parts go to its corners.
*/

/*
    The same scale as the overlay: 1rem is 1% of the width at 16:9. Behind
    everything, dark carbon fibre: a 2x2 twill whose own stepped weave runs
    at 45 degrees -- leaning /, the same way as the sheen -- drawn as one SVG
    tile, four strands square, 3.4rem, so it scales with the board. The
    page's background, so it is painted once.

    The size is 3.4 of --board-rem, the scale 1rem is set from, not 3.4rem:
    on iOS, rem in the root element's own background-size came out at the
    default 16px, not this font-size, and the weave four or five times too
    big.
*/
html {
    --board-rem: min(.5vw, .8889vh);
    font-size: var(--board-rem);
    background: #0a0b0d url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4' preserveAspectRatio='none'%3E%3Cdefs%3E%3ClinearGradient id='h' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23101114'/%3E%3Cstop offset='.5' stop-color='%231c1d21'/%3E%3Cstop offset='1' stop-color='%230d0e10'/%3E%3C/linearGradient%3E%3ClinearGradient id='v' x1='0' y1='0' x2='1' y2='0'%3E%3Cstop offset='0' stop-color='%230a0b0d'/%3E%3Cstop offset='.5' stop-color='%23131417'/%3E%3Cstop offset='1' stop-color='%2308090a'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect y='0' width='4' height='1' fill='url(%23h)'/%3E%3Crect y='1' width='4' height='1' fill='url(%23h)'/%3E%3Crect y='2' width='4' height='1' fill='url(%23h)'/%3E%3Crect y='3' width='4' height='1' fill='url(%23h)'/%3E%3Crect x='2' y='0' width='1' height='1' fill='url(%23v)'/%3E%3Crect x='3' y='0' width='1' height='1' fill='url(%23v)'/%3E%3Crect x='1' y='1' width='1' height='1' fill='url(%23v)'/%3E%3Crect x='2' y='1' width='1' height='1' fill='url(%23v)'/%3E%3Crect x='0' y='2' width='1' height='1' fill='url(%23v)'/%3E%3Crect x='1' y='2' width='1' height='1' fill='url(%23v)'/%3E%3Crect x='0' y='3' width='1' height='1' fill='url(%23v)'/%3E%3Crect x='3' y='3' width='1' height='1' fill='url(%23v)'/%3E%3Cpath d='M0 0h4M0 1h4M0 2h4M0 3h4M0 4h4' stroke='%23040405' stroke-width='.06'/%3E%3C/svg%3E");
    background-size: calc(3.4 * var(--board-rem)) calc(3.4 * var(--board-rem));
}

/*
    Now and then a narrow sheen along the weave: a pass of about 2.8 seconds
    every 48, leaning /, slid right across the screen by transform, so it is
    painted once and the compositor moves it. Its own negative z-index keeps
    it under the board: a fixed pseudo-element with none paints in document
    order, after the board.

    Two bands: the sheen, and a thin glint trailing it -- behind it, since
    it moves right. In one gradient so they move as one, at the same speed
    and a fixed distance apart. (The glint was a second strip on the same
    animation a moment later; on an eased pass that let the gap between
    them stretch and shrink as they crossed.)

    Drawn on a strip exactly as wide as the two bands (22.09vh) and long
    enough, turned 45 degrees, to cross the screen's height with its ends
    off it (180vh), centred on the screen's middle line. It is a layer the
    whole time (its animation never ends), so it is kept small: it was a
    170vh-wide strip with the bands drawn diagonally across it, 4.3 times
    the pixels for the same picture (30MB at 4K). The bands, path and timing
    are that strip's: its gradient's stops (from 43.44% to 55.01% of its
    270vh/sqrt 2 diagonal) are these, and the middle of the bands crossed
    the screen's middle line 71.86vh further right than this strip's middle
    starts, from 98.14vh off the left to that far past the right.
*/
body::after {
    content: "";
    position: fixed;
    top: 50%;
    left: 0;
    width: 22.09vh;
    height: 180vh;
    margin-top: -90vh;
    z-index: -1;
    pointer-events: none;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, .055) 8.04%,
        rgba(255, 255, 255, .115) 11.75%,
        rgba(255, 255, 255, .055) 15.47%,
        transparent 23.51%,
        transparent 55.75%,
        rgba(255, 255, 255, .065) 71.82%,
        rgba(255, 255, 255, .16) 77.87%,
        rgba(255, 255, 255, .065) 84.01%,
        transparent 100%);
    transform: translateX(-98.14vh) rotate(45deg);
    will-change: transform;
    animation: board-sheen 48s cubic-bezier(.45, 0, .55, 1) infinite;
}

@keyframes board-sheen {
    0%     { transform: translateX(-98.14vh) rotate(45deg); }
    5.87%  { transform: translateX(calc(100vw + 71.86vh)) rotate(45deg); }  /* about 2.8s: half as fast again as it was */
    100%   { transform: translateX(calc(100vw + 71.86vh)) rotate(45deg); }
}

@media (prefers-reduced-motion: reduce) {
    body::after {
        animation: none;
    }
}

.obs {
    --head: 1.5;
    --tower: 2.2;   /* 11 cars fit under the header at 16:9 */
    /*
        1.32 so the stack's worst case -- the race results, a fastest lap and
        a new leader together -- fits with room to spare: at 1.35, once the
        battle plates grew to 12.4, it was 0.24rem short at 1440p, and a
        stack that does not fit squashes its plates. Measured at every 16:9
        size from 720p to 4K: 1.39rem spare at worst. It sizes the battles'
        box too, which is half of what it buys.
    */
    --note: 1.32;

    /*
        The two closest battles kept up, in a box of their own
        (.obs-battles), beside a stack of notes (.obs-notes).
    */
    --battles-max: 2;

    /* The boxes are framed, and run off the right through the page's padding. */
    --framed: yes;
    --page-pad: 2.5rem;

    padding: var(--page-pad);
    display: grid;
    grid-template-columns: max-content 1fr;
    grid-template-rows: max-content 1fr max-content max-content;
    column-gap: 3rem;
    row-gap: 1.5rem;
}

/*
    At least as wide as the tower below it, so the two read as one column:
    they share the grid column, which is as wide as the wider of them, and
    the header stretches to it. (The tower's FL badge hangs outside its row
    and takes no width, so it does not count.)
*/
.obs-top {
    grid-row: 1;
    grid-column: 1;
    justify-self: stretch;
}

/*
    Under the header, from the top down, with the grid's gap doubled so the
    progress bar has room above the tower; a short field ends higher up.
*/
.obs-tower {
    grid-row: 2 / 5;
    grid-column: 1;
    justify-self: start;
    align-self: start;
    margin-top: 1.5rem;
}

/*
    Both boxes down the right. Plates come in from the right-hand edge and
    go back out the same way (--note-from).
*/
.obs-notes,
.obs-battles {
    --note-from: translateX(var(--note-away));
    grid-column: 2;
    justify-self: end;
}

/*
    Up to four notifications (the race results count two). The script
    appends each new note, and column-reverse shows the last one first, so
    the newest is at the top and the rest are pushed down; the oldest, at
    the bottom, is the next to go. The frame runs down to the battles box
    whatever is in it -- the notes are too many shapes to size it for, so it
    is simply never quite full.
*/
.obs-notes {
    --max: 4;
    /*
        The race results and Improvements (up to ten names) do not fit above
        the battles: the notes take the battles' room for them (.is-tall, below).
    */
    --annex: battles;
    grid-row: 1 / 3;
    align-self: stretch;
    flex-direction: column-reverse;
    justify-content: flex-end;
}

/*
    Full height (growNotes): down to where the battles' frame ends, which is
    off the screen meanwhile.
*/
.obs-notes.is-tall {
    grid-row: 1 / 4;
    margin-bottom: 2rem;
}

/*
    The two closest battles, in race order, above the corner panel and clear
    of it, in a frame tinted with the battles' own yellow -- the battle
    plates' strip -- so the box reads as theirs.
*/
.obs-battles {
    --frame-fill: color-mix(in srgb, var(--yellow) 7%, var(--frame-fill-base));
    --frame-edge: color-mix(in srgb, var(--yellow) 45%, transparent);
    --frame-tab: color-mix(in srgb, var(--yellow) 12%, transparent);
    --frame-label: var(--yellow-lit);
    --max: 2;
    --order: place;
    display: flex;
    grid-row: 3;
    align-self: end;
    margin-bottom: 2rem;
}

.obs-foot {
    grid-row: 4;
    grid-column: 2;
    justify-self: end;
    align-self: end;
}

/*
    The frame-rate meter (?fps=1), bottom left: level with the header's left
    edge and the corner panel's bottom, so in by the page's padding.
*/
.obs-fps {
    left: anchor(--board-top left);
    bottom: anchor(--board-foot bottom);
}
