/* ==========================================================================
   S3 · Live now: the board, and the line badge used across the page.

   Every colour is a token from about.css :root, except the split-flap tile
   shades the spec gives: #1B1E24 for the top half and the rgba(0,0,0,.6)
   seam. The board resolves those into its own small set of --bd-* / --tile-*
   properties on .board-wrap, and light mode (html[data-theme="light"])
   swaps only that set, in one block after the panel rules: a light board is
   drawn for a light page (pale grey tiles with a darker seam, the app's
   light-mode status inks), not the dark one inverted.

   Layout is mobile first: a stacked three-line row below 900px, a
   four-column table from 900px (direction tucked under BETWEEN) and the
   spec's five columns from 1240px, where BETWEEN has room for real names.
   Each table layout keeps its column tracks in one --board-cols, so alert,
   note, message and overflow rows can never disagree about where STATUS is.

   Whatever the layout, every alert row keeps all five cells in the
   accessibility tree. Cells are only ever hidden with the sr-only pattern,
   never display:none, so a screen reader's column headers stay aligned.
   ========================================================================== */

/* ------------------------------------------------------------ line badges */

.badge {
    --bs: 28px;
    /* Signage keeps its inks on any ground: a Line 1 bullet is yellow with a
       black numeral on a light page too. --bg and --ink swap in light mode,
       so the bullets carry their own pair (the dark theme's two values). */
    --sign-dark: #0F1014;
    --sign-light: #FFFFFF;
    --badge-bg: var(--quiet);
    --badge-ink: var(--ink);
    position: relative;
    display: inline-grid;
    place-items: center;
    flex: none;
    box-sizing: border-box;
    width: var(--bs);
    height: var(--bs);
    border-radius: 50%;
    overflow: hidden;
    vertical-align: middle;
    background: var(--badge-bg);
    color: var(--badge-ink);
    font: 800 calc(var(--bs) * .6)/1 var(--f-display);
    font-variation-settings: "wdth" 100;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
    text-transform: none;
    font-synthesis: none;
}
.badge--inline { --bs: 22px; }
.badge--go {
    width: auto;
    min-width: calc(var(--bs) * 1.45);
    padding: 0 7px;
    border-radius: var(--r-badge-go);
    font-size: 13px;
    letter-spacing: .03em;
}
.badge--inline.badge--go { font-size: 11px; padding: 0 5px; }
.badge-code { display: block; line-height: 1; transform: translateY(.02em); }

/* Signage colours; ink per SPEC §3.3 (all AA). The descendant form colours
   the flap halves inside a board badge as it rolls through the lines. */
.badge[data-line="1"], .badge .flap-h[data-line="1"] { --badge-bg: var(--l1); --badge-ink: var(--sign-dark); }
.badge[data-line="2"], .badge .flap-h[data-line="2"] { --badge-bg: var(--l2); --badge-ink: var(--sign-dark); }
.badge[data-line="4"], .badge .flap-h[data-line="4"] { --badge-bg: var(--l4); --badge-ink: var(--sign-light); }
.badge[data-line="5"], .badge .flap-h[data-line="5"] { --badge-bg: var(--l5); --badge-ink: var(--sign-dark); }
.badge[data-line="6"], .badge .flap-h[data-line="6"] { --badge-bg: var(--l6); --badge-ink: var(--sign-dark); }
.badge[data-line="LW"], .badge .flap-h[data-line="LW"] { --badge-bg: var(--go-lw); --badge-ink: var(--sign-light); }
.badge[data-line="LE"], .badge .flap-h[data-line="LE"] { --badge-bg: var(--go-le-aa); --badge-ink: var(--sign-light); }
.badge[data-line="BR"], .badge .flap-h[data-line="BR"] { --badge-bg: var(--go-br); --badge-ink: var(--sign-light); }
.badge[data-line="KI"], .badge .flap-h[data-line="KI"] { --badge-bg: var(--go-ki); --badge-ink: var(--sign-light); }
.badge[data-line="ST"], .badge .flap-h[data-line="ST"] { --badge-bg: var(--go-st); --badge-ink: var(--sign-light); }
.badge[data-line="RH"], .badge .flap-h[data-line="RH"] { --badge-bg: var(--go-rh); --badge-ink: var(--sign-dark); }
.badge[data-line="MI"], .badge .flap-h[data-line="MI"] { --badge-bg: var(--go-mi); --badge-ink: var(--sign-dark); }
.badge[data-line="UP"], .badge .flap-h[data-line="UP"] { --badge-bg: var(--go-up); --badge-ink: var(--sign-dark); }

/* On a light ground the pale bullets (Line 1's yellow, UP's sky blue) lose
   their edge, so every bullet gets the faint rim a printed sign has. It is
   an overlay rather than a shadow on the fill, so a board bullet's two flap
   halves don't each draw a rim along the seam, and it stays put while the
   halves turn under it. */
html[data-theme="light"] .badge::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
    border-radius: inherit;
    box-shadow: inset 0 0 0 1px rgba(15, 16, 20, .1);
    pointer-events: none;
}

/* ------------------------------------------------------------ split-flap */

.flap {
    position: relative;
    display: block;
    flex: none;
    width: .78em;
    height: 1.25em;
    border-radius: var(--r-tile);
    perspective: 4.5em;
    color: var(--ink-3);
}
.flap-h {
    position: absolute;
    left: 0;
    right: 0;
    height: 50%;
    overflow: hidden;
    background: var(--tile-bot);
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}
.flap-t {
    top: 0;
    border-radius: var(--r-tile) var(--r-tile) 0 0;
    background: var(--tile-top);
    box-shadow: inset 0 1px 0 var(--tile-lip);     /* the key light catches the top edge */
    transform-origin: 50% 100%;
}
.flap-b {
    top: 50%;
    border-radius: 0 0 var(--r-tile) var(--r-tile);
    box-shadow: inset 0 -1px 0 var(--tile-foot);   /* and the lower edge falls into shadow */
    transform-origin: 50% 0;
}
.flap-g {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 200%;
    line-height: 1.25em;
    letter-spacing: 0;
    text-align: center;
}
.flap-b .flap-g { top: -100%; }
.flap-g.is-final { color: var(--flap-ink, var(--ink)); }
.flap-f { z-index: 1; visibility: hidden; }
.flap.is-moving .flap-f { visibility: visible; }   /* at rest an edge-on flap still rasterises a hairline */
.flap-f.flap-b { transform: rotateX(90deg); }
/* Shade the moving flaps as they turn away from the light (animated from JS). */
.flap-f::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: var(--tile-shade);
    opacity: 0;
    pointer-events: none;
}
.flap::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: calc(50% - .5px);
    height: 1px;
    z-index: 2;
    background: var(--tile-seam);
    pointer-events: none;
}

.tiles {
    display: flex;
    align-items: center;
    gap: 2px;
    font-size: var(--tile-fs);
}
.tile-gap { flex: none; width: .3em; }

/* A board badge is one flap: the whole bullet rolls, colour and code. */
.badge--flap { background: var(--tile-bot); }
.badge--flap.badge--go { width: calc(var(--bs) * 1.5); padding: 0; }
.badge--flap .flap {
    width: 100%;
    height: 100%;
    border-radius: inherit;
    perspective: calc(var(--bs) * 2.4);
    color: inherit;
}
.badge--flap .flap-h {
    --badge-bg: var(--tile-bot);
    --badge-ink: var(--ink);
    border-radius: 0;
    background: var(--badge-bg);
    color: var(--badge-ink);
    box-shadow: none;
}
.badge--flap .flap-g { line-height: var(--bs); }
.badge--flap .flap::after { opacity: 0; transition: opacity var(--d-micro) var(--ease-ui); }
.badge--flap .flap.is-moving::after { opacity: .45; transition: none; }   /* a real bullet has no seam at rest */

/* ------------------------------------------------------------ the panel */

/* The board's own palette, resolved once here so light mode is one block
   (below) instead of an override per rule. Dark values are the spec's. */
.board-wrap {
    /* panel */
    --bd-panel: var(--bg-sunk);
    --bd-edge: var(--hair);
    --bd-hover: var(--bg-raise);
    /* split-flap tiles */
    --tile-top: #1B1E24;
    --tile-bot: var(--bg-raise-2);
    --tile-lip: var(--hair);
    --tile-foot: transparent;
    --tile-seam: rgba(0, 0, 0, .6);
    --tile-shade: var(--bg-sunk);
    /* status as text on the tiles. --red is 4.4:1 on the tiles, under the
       spec's 5:1 floor for red text, so NO SERVICE is lifted a fifth of the
       way to white (5.5:1 on both tile halves). */
    --bd-delay-ink: var(--amber);
    --bd-susp-ink: color-mix(in srgb, var(--red) 80%, var(--ink));
    --bd-ok-ink: var(--ok);
    /* status as marks on the mini strips, which keep the pure tokens */
    --bd-delay-mark: var(--amber);
    --bd-susp-mark: var(--red);
    --bd-band: var(--quiet);
    --bd-tick: var(--ink);
    --bd-tick-o: .5;
    --bd-end: var(--ink);
    --bd-end-ring: transparent;
    /* White on --shuttle is 3.7:1. As with LE's --go-le-aa, the fill steps
       down toward the ground instead (white on it is 5.3:1), so the chip
       keeps the spec's white ink and still reads as the shuttle blue. The
       token lives in about.css; the fallback is the same mix. */
    --bd-chip: var(--shuttle-aa, color-mix(in srgb, var(--shuttle) 78%, var(--bg)));
    --bd-chip-ink: #FFFFFF;

    --board-pad: 16px;
    --tile-fs: clamp(13px, 1.9vw, 16px);
    position: relative;
    max-width: 1200px;
    margin-top: var(--s-7);
    overflow: hidden;
    isolation: isolate;
    background: var(--bd-panel);
    border: 1px solid var(--bd-edge);
    border-radius: 20px;
    box-shadow: var(--sh-card);
    color: var(--ink);
}

/* Light: a departures board printed for daylight. The panel is the raised
   card of the light page; the tiles are two pale greys (the lit top half a
   step lighter, as the key light is above, and a faint shadow along the
   foot) and a falling flap greys as it turns away. The seam is a step darker
   than either half and opaque, as the dark board's nearly is: where it
   crosses a letter it reads as the gap between the flaps, a pale cut, rather
   than a dark rule struck through the word.

   Status inks start from the page's light text tokens and go a step
   darker where a tile's grey needs it, to the spec's 5:1 for red and amber
   text (ratios on the top / lower halves): --amber-text is 5.0:1 on white
   but 4.1 on the lower tile, so 15% ink takes it to 5.6 / 5.2; --red-text
   is 5.8 / 5.3 as it is; the note's green is --ok halfway to ink, 5.8 /
   5.3. The strips' marks need 3:1 against the white panel, not 4.5: --red
   already is (3.8:1); amber goes halfway to --amber-text to reach it
   (3.1:1) and stays recognisably the alert orange. Their glows add nothing
   on white, so they go (.mini-lit). The quiet band is the page's light
   --quiet, with the ticks a little darker on it. */
html[data-theme="light"] .board-wrap {
    --bd-panel: var(--bg-raise);
    --bd-edge: var(--hair-strong);
    --bd-hover: color-mix(in srgb, var(--ink) 3.5%, var(--bd-panel));
    --tile-top: #F2F3F5;
    --tile-bot: #E8E9EC;
    --tile-lip: rgba(255, 255, 255, .9);
    --tile-foot: rgba(15, 16, 20, .07);
    --tile-seam: #CFD1D6;
    --tile-shade: #6B6E76;
    --bd-delay-ink: color-mix(in srgb, var(--amber-text) 85%, var(--ink));
    --bd-susp-ink: var(--red-text);
    --bd-ok-ink: color-mix(in srgb, var(--ok) 50%, var(--ink));
    --bd-delay-mark: color-mix(in srgb, var(--amber) 50%, var(--amber-text));
    --bd-tick-o: .55;
    --bd-end: var(--bd-panel);
    --bd-end-ring: var(--ink);
    /* Toward the app's light shuttle text (#1D4ED8): white on it is 5.4:1,
       and it stays the clear shuttle blue on white, where --shuttle-aa's
       step toward the dark ground goes dull. */
    --bd-chip: color-mix(in srgb, var(--shuttle) 35%, #1D4ED8);
}
.board-wrap[data-enter="pending"] { clip-path: inset(0 0 100% 0 round 20px); }

.board {
    display: block;
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
}
.board thead,
.board tbody { display: block; }
.board th,
.board td { padding: 0; text-align: left; font-weight: inherit; }

/* Board type: Archivo 700, wdth 75, caps, tabular. Visual layers only, so
   the sr-only copy keeps its sentence case for screen readers. */
.board .v,
.board .tiles,
.board .more {
    font: 700 var(--t-board)/1 var(--f-display);
    font-variation-settings: "wdth" 75;
    font-variant-numeric: tabular-nums;
    letter-spacing: .02em;
    text-transform: uppercase;
    font-synthesis: none;
}
.board .tiles { font-size: var(--tile-fs); }

/* Header: eyebrow style. Visually hidden on phones, where rows stack. */
.board thead tr {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}
.board th {
    font: 700 var(--t-eyebrow)/1 var(--f-display);
    font-variation-settings: "wdth" 100;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ink-3);
    white-space: nowrap;
}

/* Rows: stacked on phones.
   [badge][STATUS tiles][SHUTTLE]  /  BETWEEN · DIRECTION  /  mini strip */
.board tr {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
        "line status status"
        "between between dir"
        "strip strip strip";
    align-items: center;
    column-gap: 12px;
    row-gap: 10px;
    padding: 14px var(--board-pad);
}
.board tbody tr + tr { border-top: 1px solid var(--hair); }
.board tr.row--note,
.board tr.row--msg,
.board tr.row--more {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: none;
}
.c-line, .board thead th:nth-child(1) { grid-area: line; }
.c-between, .board thead th:nth-child(2) { grid-area: between; min-width: 0; }
.c-strip, .board thead th:nth-child(3) { grid-area: strip; min-width: 0; }
.c-dir, .board thead th:nth-child(4) { grid-area: dir; min-width: 0; }
.c-status, .board thead th:nth-child(5) { grid-area: status; min-width: 0; }
.c-line .v,
.c-strip .v { display: block; }

/* LINE */
.c-line .badge { display: grid; }

/* BETWEEN: the row's link. Its ::after covers the whole row so the row is
   the tap target; the ring is drawn on that overlay. */
.between {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    color: var(--ink);
    text-decoration: none;
    outline: none;
    -webkit-tap-highlight-color: transparent;
}
.between .v {
    display: block;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    padding-block: .12em;           /* room for the caps' overshoot inside the clip */
}
.dec-b { color: var(--ink-3); }
.between::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: 12px;
}
.between:focus-visible::after {
    outline: 3px solid var(--focus, var(--halo));   /* the halo on dark, ink on light */
    outline-offset: -4px;
}

/* STRETCH. --mark is the row's status colour for the lit stretch and ring. */
.mini { --mark: var(--bd-delay-mark); display: block; overflow: visible; max-width: 100%; }
.sev-suspended .mini { --mark: var(--bd-susp-mark); }
.mini-band { stroke: var(--bd-band); stroke-width: 4; stroke-linecap: round; }
.mini-tick { fill: var(--bd-tick); opacity: var(--bd-tick-o); }
/* Union's capsule at the start of a GO strip: a step stronger than the
   ticks, since it is the one fixed point every GO line shares. */
.mini-hub { fill: var(--bd-tick); opacity: calc(var(--bd-tick-o) + .3); }
.mini-lit {
    fill: none;
    stroke: var(--mark);
    stroke-width: 4;
    stroke-linecap: round;
    filter: drop-shadow(0 0 3px color-mix(in srgb, var(--mark) 45%, transparent));
}
html[data-theme="light"] .mini-lit { filter: none; }   /* a glow adds nothing on white */
/* End dots: white on the dark board. On the light one they are the app's
   light-map station markers, a white dot in a dark ring, so they read as
   stations on the orange instead of dark holes in it. The ring is thin
   enough that the shrunk dots of a dense or short stretch keep a white
   centre. */
.mini-end { fill: var(--bd-end); stroke: var(--bd-end-ring); stroke-width: 1.1; }
.mini-ring { fill: var(--bd-panel); stroke: var(--mark); stroke-width: 2; }
.mini-end,
.mini-ring { transform-box: fill-box; transform-origin: center; }

/* DIRECTION */
.c-dir .v {
    display: flex;
    align-items: center;
    gap: 7px;
    white-space: nowrap;
    color: var(--ink-2);
}
.dir-ico {
    flex: none;
    width: .62em;
    height: .62em;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
    color: var(--ink-3);
}
.dir-e { transform: rotate(90deg); }
.dir-s { transform: rotate(180deg); }
.dir-w { transform: rotate(-90deg); }
.dir-hub { fill: currentColor; stroke: none; }   /* GO inbound / outbound: the Union capsule the arrow meets or leaves */
.dir-text { overflow: hidden; text-overflow: ellipsis; }

/* STATUS: inks from the board palette (see .board-wrap for the contrast). */
.row--alert { --flap-ink: var(--bd-delay-ink); }
.row--alert.sev-suspended { --flap-ink: var(--bd-susp-ink); }
.c-status .v {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 10px;
}
.chip {
    display: inline-flex;
    align-items: center;
    height: 22px;
    padding: 0 8px;
    border-radius: var(--r-chip);
    background: var(--bd-chip);     /* contrast notes with the palette on .board-wrap */
    color: var(--bd-chip-ink);
    font: 700 12px/1 var(--f-display);
    font-variation-settings: "wdth" 100;
    letter-spacing: .06em;
    white-space: nowrap;
}
.chip[hidden] { display: none; }
.row-go {
    flex: none;
    font: 700 .8em/1 var(--f-display);
    color: var(--ink-2);
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity var(--d-ui) var(--ease-ui), transform var(--d-ui) var(--ease-ui);
    pointer-events: none;
}

/* A row sliding to a new place on refresh covers whatever it passes over. */
.board tr.is-sliding { z-index: 2; background: var(--bd-panel); box-shadow: 0 -1px 0 var(--hair), 0 1px 0 var(--hair); }

/* Hover and keyboard focus lift the row a step. */
.row--alert { transition: background-color var(--d-ui) var(--ease-ui); }
@media (hover: hover) {
    .row--alert:hover { background: var(--bd-hover); }
    .row--alert:hover .row-go { opacity: 1; transform: none; }
}
.row--alert:focus-within { background: var(--bd-hover); }
.row--alert:focus-within .row-go { opacity: 1; transform: none; }

/* Network note: "TTC SUBWAY · NO ACTIVE ALERTS". */
.row--note { --flap-ink: var(--bd-ok-ink); }
.row--note.tone-off { --flap-ink: var(--ink-3); }
.c-note { grid-column: 1 / -1; }
.c-note .v {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr);
    grid-template-areas: "dot name" ". tiles";
    align-items: center;
    column-gap: 12px;
    row-gap: 10px;
}
.note-dot {
    grid-area: dot;
    justify-self: center;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--ok);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 18%, transparent);
}
.tone-off .note-dot { background: var(--ink-4); box-shadow: none; }
.note-name { grid-area: name; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-block: .12em; }
.note-sep { display: none; color: var(--ink-4); }
.c-note .tiles { grid-area: tiles; }

/* Loading / warming / error: one plain row of copy. */
.c-msg {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 22px;
    min-height: 60px;
}
.msg-dot {
    flex: none;
    width: 8px;
    height: 8px;
    margin-inline: 10px 0;
    border-radius: 50%;
    background: var(--ink-4);
}
.tone-wait .msg-dot { background: var(--ink-3); }
.msg {
    margin: 0;
    font: 400 var(--t-body)/1.45 var(--f-text);
    color: var(--ink-2);
    text-wrap: pretty;
}
.msg a {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--ink-4);
    text-underline-offset: .2em;
    text-decoration-thickness: 1px;
    transition: text-decoration-color var(--d-ui) var(--ease-ui);
}
.msg a:hover { text-decoration-color: var(--ink); }

/* "+3 more on the live map →" */
.c-more { grid-column: 1 / -1; }
.more {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    margin-left: 40px;
    color: var(--ink-2);
    text-decoration: none;
    font-size: min(var(--t-board), 1.0625rem);
    letter-spacing: .06em;
    transition: color var(--d-ui) var(--ease-ui);
}
.more-arrow { display: inline-block; transition: transform var(--d-micro) var(--ease-ui); }
.more:hover { color: var(--ink); }
.more:hover .more-arrow { transform: translateX(3px); }
.board tr.row--more { padding-block: 4px; }

/* Pre-flip: rows wait blank until the board is scrolled to. */
.row.is-blank .c-dir .v,
.row.is-blank .chip,
.row.is-blank .mini,
.row.is-blank .note-dot,
.row.is-blank .msg,
.row.is-blank .msg-dot,
.row.is-blank .more { opacity: 0; }

/* Under the board. It waits with the panel and follows the wipe in (board.js). */
.board-wrap[data-enter="pending"] + .board-meta { opacity: 0; }
/* With no "Updated" line (loading, warming, error) the link keeps its
   right-hand place instead of sliding over to where that line was. */
.board-updated:empty + .link-arrow { margin-left: auto; }
.board-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px 24px;
    max-width: 1200px;
    margin-top: var(--s-5);
    font-size: var(--t-small);
    color: var(--ink-3);
}
.board-updated:empty { display: none; }
.board-updated {
    min-height: 1.45em;
    margin: 0;
    line-height: 1.45;
    font-variant-numeric: tabular-nums;
    text-wrap: pretty;
}
.upd-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-right: 10px;
    vertical-align: .08em;
    border-radius: 50%;
    background: var(--ok);
}
.board-updated[data-tone="stale"] .upd-dot { background: var(--ink-4); }
.upd-text { color: var(--ink-2); }
/* The live dot breathes only while motion is allowed: Pause motion and
   lite (Low Power) take the animation off entirely rather than racing it
   on specificity. */
.motion:not(.motion-paused):not(.lite) .board-updated[data-tone="ok"] .upd-dot {
    animation: board-live var(--d-breathe) ease-in-out infinite;
}
@keyframes board-live {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 45%, transparent); }
    50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--ok) 0%, transparent); }
}

/* ------------------------------------------------------------ ≥ 900px */

@media (min-width: 900px) {
    /* STATUS is exactly as wide as its longest word, SIGNIFICANT DELAY: 16
       tiles at .78em, one .3em word gap and 16 flex gaps of 2px. The tiles
       grow with --t-board, so a fixed track that fits them at 900px is 21px
       short by 1085px, where --t-board stops growing, and they ran into the
       panel padding. Sized from --tile-fs, the tiles end on the column edge,
       24px in from the panel like the badge on the left, and BETWEEN keeps
       more than 300px at 900. NO SERVICE and its SHUTTLE BUSES chip wrap to
       two lines here. */
    .board-wrap {
        --board-pad: 24px;
        --tile-fs: calc(var(--t-board) * .8);
        --board-cols: 56px minmax(0, 1fr) 124px calc(var(--tile-fs) * 12.78 + 32px);
        margin-top: var(--s-8);
    }
    .board thead tr {
        position: static;
        width: auto;
        height: auto;
        overflow: visible;
        clip-path: none;
        white-space: normal;
        min-height: 0;
        padding-block: 18px 16px;
        border-bottom: 1px solid var(--hair);
    }
    .board thead th:nth-child(4) {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
    }
    .board tr {
        grid-template-columns: var(--board-cols);
        grid-template-areas:
            "line between strip status"
            "line dir strip status";
        column-gap: 20px;
        row-gap: 5px;
        min-height: 64px;
        padding: 12px var(--board-pad);
        align-content: center;
    }
    /* The header row has no DIRECTION to tuck under BETWEEN (its header is
       visually hidden), so it is one row. On the two-row template BETWEEN
       sat in the top row, 2.5px above the headers centred across both. */
    .board thead tr {
        grid-template-areas: "line between strip status";
        min-height: 0;
        padding-block: 18px 16px;
    }
    .c-dir .v { font-size: .75em; color: var(--ink-3); }
    .c-strip .v { display: flex; align-items: center; }

    .c-note,
    .c-more,
    .c-msg {
        display: grid;
        grid-template-columns: subgrid;
        align-items: center;
    }
    .c-note .v { display: contents; }
    .note-dot { grid-column: 1; justify-self: start; margin-left: 9px; }
    .note-name { grid-column: 2 / -2; }
    .c-note .tiles { grid-column: -2 / -1; }
    .more { grid-column: 2 / -1; margin-left: 0; }
    .board tr.row--note,
    .board tr.row--msg,
    .board tr.row--more { grid-template-columns: var(--board-cols); }
    .board tr.row--more { min-height: 56px; }
    .c-msg { min-height: 88px; }

    /* A message (loading, warming, error) is not a table to read across:
       drop the column headers from view, keep them for screen readers. */
    .board-wrap[data-view="message"] .board thead tr {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        border: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
    .msg-dot { grid-column: 1; margin-left: 10px; }
    .msg { grid-column: 2 / -1; }
}

/* ------------------------------------------------------------ ≥ 1240px: the spec's five columns */

/* STATUS is the spec's 280px plus 8, taken from DIRECTION (its longest,
   NORTHBOUND, is 120px): NO SERVICE with its SHUTTLE BUSES chip is 284px on
   one line, and BETWEEN keeps its width. The cell can still wrap, so
   SIGNIFICANT DELAY with the chip (394px) puts the chip under the tiles
   instead of running into the panel padding. */
@media (min-width: 1240px) {
    .board-wrap { --board-cols: 72px minmax(0, 1fr) 136px 142px 288px; }
    .board thead th:nth-child(4) {
        position: static;
        width: auto;
        height: auto;
        overflow: visible;
        clip-path: none;
    }
    .board tr,
    .board thead tr { grid-template-areas: "line between strip dir status"; }
    .board tr {
        column-gap: 24px;
        padding-block: 0;
    }
    .board thead tr { padding-block: 18px 16px; }
    .c-dir .v { font-size: 1em; color: var(--ink-2); }
}

/* ------------------------------------------------------------ stacked rows (< 900px) */

@media (max-width: 899px) {
    .c-dir .v { font-size: .8em; }
    .row-go { display: none; }

    /* A row with no strip to draw (a GO row on /about, which loads no GO
       geometry, or stations that didn't resolve) drops the strip line from
       its grid, so the row's padding stays even; the cell stays in the
       accessibility tree, visually hidden. */
    .board tr.row--alert.no-strip {
        grid-template-areas:
            "line status status"
            "between between dir";
    }
    .row--alert.no-strip .c-strip {
        position: absolute;
        grid-area: auto;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

@media (prefers-reduced-motion: reduce) {
    .row--alert,
    .row-go,
    .more,
    .more-arrow { transition: none; }
}
