/*
  MST design tokens - see MstTheme.cs for the C#/MudBlazor side of this same
  palette. Kept here too because a few things (tabular numerals for timing
  data, the flag-state pill, the run-control button bar) are plain CSS
  rather than MudBlazor component props, and they need to reference the same
  colours without redefining them by eye a second time.
*/
:root {
    --mst-bg: #0B1220;
    --mst-surface: #1E293B;
    --mst-muted: #334155;
    --mst-danger: #EF4444;
    --mst-accent: #14B8A6;
    --mst-text: #F8FAFC;

    /* Race-control colours - Dan's own canonical spec 2026-09-27 (see
       MST.Domain.Racing.RaceControlPalette, the C# source of truth these
       mirror, and the race-control-button-colors.md project memory).
       Warmup changed from light blue to purple, Smart Start from orange to
       a dark orange - deliberate colour CHANGES from what this file used to
       have, not oversights.
       Safety Car and VSC standardised to the SAME bright yellow as FCY -
       Dan's own correction 2026-09-27, live, superseding an earlier same-day
       pass that gave Safety Car/VSC their own distinct orange/amber shades:
       "the colors look wrong... not sure when we changed safety car color
       to orange??? Across the board, any panel for Safety Car, VSC or FCY
       has to be bright YELLOW. no exceptions... many tracks only have a
       yellow flag, and they combine with SC signs, so we should stick with
       the standard of racing." No separate shade for either any more - the
       button/panel LABEL (SC/VSC/FCY text) is what tells them apart, not
       colour, matching how a real yellow flag looks the same regardless of
       why it's out. */
    --mst-flag-green: #22C55E;
    --mst-flag-yellow: #EAB308;
    --mst-flag-safety-car: #EAB308;
    --mst-flag-red: #EF4444;
    /* Third bucket for stint-compliance colouring (Green/Yellow/Orange/Red
       - Dan's own request 2026-09-28) - no existing race-control colour
       sits between yellow and red, so this is new. */
    --mst-flag-orange: #F97316;
    --mst-flag-checkered: #94A3B8;
    --mst-flag-code60: #D946EF;
    --mst-flag-warmup: #7C3AED;
    /* Start Clock's own colour, distinct from Warmup - Dan's own correction
       2026-09-27, live: "start clock should be electric blue." Same value
       as MstTheme.ColorElectricBluePrimary, not invented fresh here. */
    --mst-flag-startclock: #0066FF;
    --mst-flag-smart-start: #9A3412;
    /* Virtual Safety Car - same bright yellow as Safety Car/FCY, see the
       comment on --mst-flag-safety-car above. Kept as its own variable
       (rather than every VSC consumer just reading --mst-flag-yellow
       directly) purely so a future colour change only ever needs an intent-
       named variable, not a text search for every reuse of yellow. */
    --mst-flag-vsc: #EAB308;

    /* Shared by both header side-boxes (.mst-header-side-box - the event/
       run/clock box AND the logo box, see that class's own comment) so they
       always render the exact same height, instead of two independently-
       tuned numbers drifting apart - Dan's own request 2026-09-27, live:
       "make the mstiming logo block the same height as the active event/
       active run details box." Grew 68px -> 108px the same day once the
       clock became 70px tall, then back down to 88px shortly after - Dan's
       own correction: "the header has gained weight vertically... we can
       lose a lot of that header bar height and still look nice." The 70px
       clock is still the real floor (its own line-box is ~70px), but two
       things that were ALSO inflating the box independently of the clock
       got trimmed the same pass: the flag-status pill moved off its own
       stacked line onto the run-name row (see .mst-header-run-and-flag-row),
       and the icon rail's buttons got shrunk (see .mst-header-iconrail) -
       neither was actually needed to fit the clock, just leftover slack
       from the first pass. Derived from .mst-appbar's own 100px height
       minus a 6px inset top and bottom (matching .mst-header-side-box's own
       top/bottom insets) - if the appbar height ever changes again, update
       both there and here together. */
    /* Shrunk again 88px -> 52px shortly after the note above - Dan's own
       words: "bring the size of each box down 75%... keep the font and
       graphics as large as you can within those two black boxes." Measured
       live first: at 88px, the boxes had almost no real slack against their
       THEN-current font sizes (event name/clock etc.) - width slack was
       only ~31px, and even height slack was modest. So getting genuinely
       smaller meant shrinking the fonts/clock/logo too (see their own
       comments below), not just trimming padding - the box then re-fits
       itself tightly around whatever that smaller content needs. */
    --mst-header-box-height: 52px;
    /* Shared width for the same pair of boxes - Dan's own request 2026-09-27,
       live: "make that box [the logo] the same width as the right side box
       with the flag/Current event/current run and clock in it." One number,
       not two independently-tuned ones, same reasoning as the height above.
       Re-measured (not guessed) against the smaller fonts below, same
       discipline as every other number in this file. */
    --mst-header-side-box-width: 380px;

    /* Font-size knob - adjusted by MainLayout's Font +/- buttons
       (mstDensity.js) and persisted to localStorage, so one control set
       (in the app bar, present on every page) changes every .mst-tabular/
       .mst-tabular-compact table app-wide, and the setting survives both
       page navigation and a browser restart - see that JS file's own
       comment. Default here is the SSR-safe fallback before the JS runs;
       the JS overwrites it from localStorage as its very first action.
       Used to sit alongside matching row-height/row-padding knobs - removed
       2026-09-27 (Dan's own request, live: "remove and unwire the cell
       height and cell padding modification in the header"). */
    --mst-row-font-size-extra: 0rem;
}

html, body {
    background: var(--mst-bg);
    color: var(--mst-text);
    font-family: 'Inter', 'Segoe UI', sans-serif;
}

/* Dan's own report 2026-09-27: "even in full screen mode, we lose a few
   pixels top and side" on his screens - some monitors/TVs overscan or crop
   a sliver at the true edge, clipping whatever sits flush against it.
   zoom (not transform:scale) so every vh/vw/% calculation elsewhere in the
   app - Passings' own calc(100vh - 190px) scroll containers included -
   still resolves correctly against the now-98%-sized viewport, rather than
   being computed against the full one and then visually squashed. */
html {
    zoom: 98%;
}

/* Dan 2026-09-29: the top toolbar (flag controls, clocks) jumped left/right whenever a page's
   height changed enough to show or hide the scrollbar (the Gap Graph did it on every refresh).
   Always keep the scrollbar's space on operator pages (the ones with the app bar) so the width
   never changes. Full-screen display boards have no app bar and keep their whole width. */
html:has(.mst-appbar) {
    scrollbar-gutter: stable;
}

/* Dan's own report 2026-09-27: adding a loop, "I did not realise there were
   6 fields to fill in, because it is not obvious where a text box is to
   fill in... it is nice that it underlines when you hover over one, but if
   you don't see it to start with, that's not much good." MudBlazor's
   default text-field variant (used everywhere in MST - nothing sets
   Variant="Filled"/"Outlined" except two deliberate exceptions, excluded
   below) paints no background at all until hover/focus reveals the
   underline - on a form with several fields, most of them are invisible
   at a glance. This gives every plain text/number/select/date input a
   subtle raised fill so the box itself reads as "a box" before any
   interaction, brightening further on hover/focus for the same affordance
   MudBlazor's own Filled variant already gets - a CSS coat of paint on the
   existing markup rather than switching every field's Variant everywhere
   in the app (a much bigger, more invasive change for the same visual
   result). Targets .mud-input, the same element MudBlazor's own
   .mud-input-filled rule paints - see that selector's own background/
   hover/focus shape in MudBlazor.min.css, mirrored here with this app's
   own colours instead of its hardcoded black. */
.mud-input:not(.mud-input-filled):not(.mud-input-outlined) {
    background-color: rgba(248, 250, 252, 0.05);
    border-radius: 6px;
    padding: 2px 6px;
    transition: background-color 150ms ease;
}
.mud-input:not(.mud-input-filled):not(.mud-input-outlined):hover {
    background-color: rgba(248, 250, 252, 0.08);
}
.mud-input.mud-focused:not(.mud-input-filled):not(.mud-input-outlined) {
    background-color: rgba(248, 250, 252, 0.1);
}

/* Circuit editor's Loops table "Settings" column - Dan's own request
   2026-09-27: "space out the attributes of the loop (X, S, L etc) and show
   them as little letter icons, where a hover over is a tool tip." Replaces
   the old packed "SFLA"-style string with one small badge per active flag
   (CircuitEditDialog.razor's own ActiveSettings), each individually
   hoverable - this is just the badge's own box, the per-badge tooltip text
   is plain MudTooltip. */
.mst-loop-setting-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 3px;
    margin-right: 3px;
    border-radius: 4px;
    background: rgba(248, 250, 252, 0.1);
    font-size: 0.6875rem;
    font-weight: 700;
    cursor: default;
}

/* Circuit editor's bulk-decoder picker (the header row above the Loops
   table's Decoder column) - Dan's own follow-up 2026-09-27: the select
   rendered far wider than the inline Style="width:70px" asked for, then
   left a "stupid wide" gap before the apply-all icon. Root cause: MudBlazor's
   own bundled CSS has `.mud-input-control{width:auto !important}` - an
   inline style can never win against an !important rule regardless of its
   value, so that width was silently ignored. Same specificity (one class,
   !important) beats it here only because this stylesheet loads AFTER
   MudBlazor's own (confirmed via the rendered page's own <link> order) -
   on a tied specificity, cascade order decides, and this one is later. */
.mst-bulk-hardware-picker .mud-input-control {
    width: 180px !important;
}

/* Every column of race numbers (lap times, gaps, positions) needs digits
   that line up vertically between rows - a proportional font without this
   makes a "1" and a "8" occupy different widths and the whole column looks
   crooked. This is the one typographic detail every reference peg gets
   right and a default MudBlazor table does not. */
/* Every data table in MST (leaderboard, passings log, and every future
   tab) needs to show a big field - 60-80+ competitors, hundreds of raw
   crossings - on one screen without scrolling every few rows. MudBlazor's
   own "Dense" table prop only trims padding a little; these overrides go
   further (tight vertical padding, a slightly smaller body font) while
   keeping the horizontal breathing room and hairline row dividers that
   keep a dense table from reading as a cluttered wall of numbers. */
.mst-tabular {
    font-variant-numeric: tabular-nums;
}

/* Centered by default - headers and data need to line up on the SAME
   alignment per column, not a left-aligned header over centered/right
   data. Numeric/delta columns override this to right-aligned below, at
   higher specificity, and get the override applied to both their <MudTh>
   and <MudTd> so the two stay consistent with each other too. */
.mst-tabular .mud-table-cell {
    /* !important on all three - found live 2026-09-25 (Dan's own report:
       "the font button is actually changing the column names header, not
       the grid values"): MudBlazor's own bundled stylesheet sets its own
       font-size (0.875rem/14px, confirmed via getComputedStyle) on
       .mud-table-cell at equal selector specificity to this rule, and
       loads AFTER app.css - so on a plain specificity tie, ITS declaration
       was winning for every DATA cell (a <td>), while this page's header
       cells happened to already be won by a separate, more specific
       selector below (hence height/pad/font all looked "kind of" like they
       worked - only the header was ever actually responding). !important
       is the reliable fix regardless of MudBlazor's own future load order.
       Row height/padding used to also be adjustable knobs here (matching
       the font-size one still below) - fixed back to plain values 2026-09-27
       (Dan's own request, live: "remove and unwire the cell height and cell
       padding modification in the header"). */
    padding: 1px 8px !important;
    font-size: calc(0.6875rem + var(--mst-row-font-size-extra)) !important;
    line-height: 1.15 !important;
    text-align: center;
}

/* Deliberately NOT using --mst-row-font-size-extra - Dan's own request
   2026-09-25: "we want the header bar to have fixed sized font, and the
   grid values to be changed by the font change button." !important for the
   same MudBlazor-override reason as .mud-table-cell above.

   background:#0B1F6B - originally just Passings' own header colour ("give
   the header a dark electric flag background", 2026-09-25), promoted to
   the STANDING column-header background for every table app-wide 2026-09-27,
   Dan's own words, live: "that is a really nice background blue color...
   can we copy that to all of the other pages that have a header, and
   remember that we will always use that for column headers in the future."
   Since .mst-tabular is the shared base class every page's table already
   carries (Passings/Sectors/Microsectors add .mst-tabular-compact ON TOP of
   this, RunControl/Program use it alone), setting it here is the single
   source for that rule - no page needs its own copy. Any NEW table header
   built from now on should get this for free just by using .mst-tabular
   (or a MudTable Class the existing convention derives from it) - don't
   reinvent a different header colour. */
.mst-tabular .mud-table-head .mud-table-cell {
    padding-top: 3px;
    padding-bottom: 3px;
    background: #0B1F6B;
    font-size: 0.625rem !important;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    opacity: 0.7;
}

.mst-tabular .mud-chip {
    height: 16px;
    font-size: 0.5625rem;
}

/* Run Control's own leaderboard header (Pos/No./Driver/Vehicle/Class/...) -
   Dan's own request 2026-09-27, live: "in run control, we need the header
   bar... to be 3px higher." Scoped to .mst-runcontrol-table alone (not the
   shared .mst-tabular base rule above) - nobody asked for this on Program's
   own run list, which also plainly uses .mst-tabular. 3px split evenly
   across top+bottom, same approach as Passings' own header-height bump. */
.mst-runcontrol-table .mud-table-head .mud-table-cell {
    padding-top: 4.5px;
    padding-bottom: 4.5px;
}

/* Cars (GCT) page header - Dan's own request 2026-09-26, live: "make the
   blue header at the top of the data panel 50% higher too please.. and
   font ++2px." Scoped to .mst-cars-table alone, not the shared .mst-tabular
   base rule above - same 3px-base x1.5 = 4.5px idiom RunControl's own "3px
   higher" header just above already established for "50% higher" (this is
   the same 3px base already reused), plus the same "+2px over the base
   font" idiom Passings/PitDetails/Sectors/MicroSectors already use for
   their own bigger headers. !important on font-size for the same reason
   those other pages need it - the shared .mst-tabular header rule further
   up sets its own font-size at equal specificity and loads first. */
.mst-cars-table .mud-table-head .mud-table-cell {
    padding-top: 4.5px;
    padding-bottom: 4.5px;
    font-size: calc(0.625rem + 2px) !important;
}

/* Duplicate-transponder warning icon (Cars.razor) - Dan's own request
   2026-09-26: "put a small red caution icon flashing, with a tooltip to
   say which ones are duplicated." prefers-reduced-motion still gets the
   icon (it's real information, not decoration), just without the pulse. */
.mst-transponder-dup-icon {
    animation: mst-transponder-dup-flash 1s ease-in-out infinite;
}
@keyframes mst-transponder-dup-flash {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.25; }
}
@media (prefers-reduced-motion: reduce) {
    .mst-transponder-dup-icon { animation: none; }
}

/* Numeric/delta columns (laps, best lap, gap, interval) - fixed-width and
   right-aligned so a "+1:23.456"-shaped value never wraps or crowds the
   column next to it as digits change every render. The extra specificity
   (three selector parts, vs two on the centered default above) is
   deliberate - it has to win over .mst-tabular .mud-table-cell's
   text-align:center regardless of which one is written first. */
.mst-tabular .mud-table-cell.mst-num-cell {
    text-align: right;
    white-space: nowrap;
    min-width: 5.5em;
}

/* Same fixed-width/no-wrap behaviour as .mst-num-cell above, but centered -
   Sectors/Microsectors' segment-time columns (Dan's own steer 2026-09-20:
   "the data [needs to be] centred in the column with the header too").
   A separate class rather than just overriding mst-num-cell everywhere -
   RunControl's leaderboard genuinely wants right-alignment (a "+1:23.456"
   gap column reads better with its digits stacking on the right), this is
   a real, deliberate difference in what suits each page, not an
   inconsistency to unify away. */
.mst-tabular .mud-table-cell.mst-num-cell-centered {
    text-align: center;
    white-space: nowrap;
    min-width: 5.5em;
}

/* Passings specifically needs to show far more rows than the leaderboard -
   it's a raw log, not a small field of competitors - so this trims further
   still: near-zero vertical padding, and a font-weight bump to keep small
   text crisp instead of thin/blurry at this size. */
.mst-tabular-compact .mud-table-cell {
    /* Base line-height tightened from 1.05 to 0.95 (2026-09-19, Dan's own
       request - "please please reduce the cell height... so we can see
       more passings"). !important on all three - see .mst-tabular
       .mud-table-cell's own comment for the MudBlazor-override this
       guards against. Row height/padding used to be adjustable knobs from
       this baseline (matching the font-size one still below) - fixed back
       to plain values 2026-09-27 (Dan's own request, live). */
    padding: 0px 3px !important;
    font-size: calc(0.6875rem + var(--mst-row-font-size-extra)) !important;
    font-weight: 500;
    line-height: 0.95 !important;
}

/* Fixed, not --mst-row-font-size-extra-driven - see .mst-tabular .mud-table-head .mud-table-cell's own comment (Dan's request: header stays a fixed size, only the grid values respond to the font button). */
.mst-tabular-compact .mud-table-head .mud-table-cell {
    padding: 1px 3px;
    font-size: 0.625rem !important;
}

/* Passings specifically - Dan's own request 2026-09-25: "reduce the
   vertical cell height by 25%." Scoped to Passings alone (not the shared
   .mst-tabular-compact baseline every other dense table also uses, e.g.
   Sectors/MicroSectors, which nobody asked to shrink) - 0.95 base x 0.75 =
   0.7125. Used to be further adjustable from this baseline by a row-height
   knob - fixed back to a plain value 2026-09-27 (Dan's own request, live:
   "remove and unwire the cell height and cell padding modification in the
   header"). */
.mst-passings-table.mst-tabular-compact .mud-table-cell {
    line-height: 0.7125 !important;
}

/* Fixed, locked column widths - Dan's own request 2026-09-25: "lock all
   cells to data you watch coming in... so the columns are not constantly
   adjusting." table-layout:fixed takes column widths from this FIRST row's
   (the header's) own cells; every column below gets an explicit width
   except .mst-col-flex (Team/Driver, Current Driver) - deliberately left
   with NO width at all, so table-layout:fixed's own default behaviour
   (split whatever's left over the columns with no explicit width) does the
   "evenly share the remaining space" job on its own, without risking the
   layout bugs a hand-picked percentage-on-top-of-fixed-pixels mix can
   produce.

   Per-column widths used to live here as thead th:nth-child(N) rules -
   moved directly onto each MudTh's own Style in Passings.razor 2026-09-21,
   when the Test Mode Seq column (conditionally present) and the Info/Edit
   icon columns were added: position-based selectors here would have needed
   a second, hand-synced copy for every column shift, and already broke
   once (Seq column's own comment). A width on the actual header cell can
   never drift out of sync with what column it's describing. */
.mst-passings-table.mud-table {
    table-layout: fixed;
}

/* .mst-col-flex cells (both th and td) must never wrap onto their own
   internal min-width floor - .mst-num-cell-centered's own 5.5em min-width
   doesn't apply here, but the flex columns still need to be allowed to
   actually shrink/grow with real name text rather than fighting it. */
.mst-passings-table .mst-col-flex {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* Dan's own request 2026-09-25: "align the team/driver name aligned
       left" - overrides .mst-tabular .mud-table-cell's centered default.
       Applied to both flex columns (Team/Driver, Current Driver) for the
       same reason they share one class in the first place - a name reads
       naturally left-aligned, and having the two differ would look like an
       inconsistency, not a deliberate choice. */
    text-align: left !important;
}

/* Passings' own header row - Dan's own request 2026-09-25: "double the
   height of the header cell... add 2px to the font, and give the header a
   dark electric blue background" (that background is now the standing
   convention for every table's header - see .mst-tabular .mud-table-head
   .mud-table-cell's own comment - so it's no longer set here specifically,
   just inherited). Padding scoped to Passings alone, same reasoning as the
   row-height-25%-shorter rule above - nobody asked for this on Sectors/
   MicroSectors' own dense tables. Font-size here is a fixed +2px over the
   base, NOT --mst-row-font-size-extra-driven - Dan's own follow-up request
   the same day: "we want the header bar to have fixed sized font, and the
   grid values to be changed by the font change button." Padding bumped a
   further 1.5px/side 2026-09-27 (live: "the table header... needs to be
   3px higher" - 3px split evenly across top+bottom). */
.mst-passings-table.mst-tabular-compact .mud-table-head .mud-table-cell {
    /* !important required on the padding too, not just font-size - without
       it this loses outright to .mst-tabular-compact .mud-table-cell's own
       "padding: 0px 3px !important" a few rules above (which also matches
       header <th> cells, since MudTh renders with the same .mud-table-cell
       class body cells use). A plain, non-!important declaration here -
       however much higher its own selector specificity - never beats an
       !important one; confirmed live 2026-09-27 via computed-style: this
       rule's padding was silently resolving to 0px the whole time, despite
       the file's own long-standing comment claiming an 8px header height
       Dan asked for back on 2026-09-25 - a real, previously-undetected bug,
       not something this session's own 3px bump introduced. */
    padding-top: 9.5px !important;
    padding-bottom: 9.5px !important;
    font-size: calc(0.625rem + 2px) !important;
}

/* FAST MODE (Passings.razor.js mstPassings.fastTable) - Dan's own request
   2026-09-25: "make that page super efficient and fast with all rows
   loaded, even if it involves making it look plain as crap with a few
   java boxes instead of the pretty stuff." Deliberately minimal: plain
   flex rows, no MudBlazor table chrome, fixed-width monospace-ish cells so
   ~150,000 of them cost nothing to lay out (only ~40-60 ever exist in the
   DOM at once - see fastTable._draw's own comment). rowHeight here MUST
   match fastTable.rowHeight in the JS (22px) - they're two halves of the
   same measurement, kept in sync by hand since one's CSS and the other's a
   JS constant. */
.mst-fast-row {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 22px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 6px;
    border-left: 4px solid transparent;
    font-family: var(--mst-tabular-font, monospace);
    font-size: 12px;
    white-space: nowrap;
    cursor: pointer;
    box-sizing: border-box;
}
.mst-fast-row:hover {
    background: rgba(255, 255, 255, 0.06);
}
.mst-fast-cell {
    overflow: hidden;
    text-overflow: ellipsis;
}
.mst-fast-car { width: 44px; flex-shrink: 0; font-weight: 700; text-align: right; }
.mst-fast-drv { flex: 2 1 0; min-width: 0; }
.mst-fast-loop { width: 90px; flex-shrink: 0; opacity: 0.85; }
.mst-fast-time { width: 100px; flex-shrink: 0; font-variant-numeric: tabular-nums; }
.mst-fast-race { width: 90px; flex-shrink: 0; font-variant-numeric: tabular-nums; opacity: 0.85; }

/* Full Passings list (Passings.razor.js mstPassings.grid) - one CSS grid
   template shared by the header and every row, so columns can never drift.
   Row height MUST match mstPassings.grid.rowHeight (24px). Column order:
   Seq, No., Team/Driver, [menu][edit][flag], Class, Lap, Ldr Lap, Last Lap,
   Time, Race Time, Transponder, Loop, Speed, Lap Speed, Driver In Car, Pos,
   Hits, Battery, Noise, Flags. */
.mst-grid-cols {
    display: grid;
    grid-template-columns: 56px 48px minmax(150px, 1.4fr) 24px 24px 24px 110px 44px 50px 88px 96px 84px 92px 76px 58px 62px minmax(120px, 1fr) 40px 42px 50px 44px 64px;
    align-items: center;
    column-gap: 6px;
}
.mst-grid-header {
    position: sticky; top: 0; z-index: 3;
    background: #0B1F6B; color: #E2E8F0;
    font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
    padding: 7px 6px 7px 10px; border-bottom: 1px solid var(--mst-muted);
}
.mst-grid-header > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; }
.mst-grid-header > span.g-l { text-align: left; }
.mst-grid-row {
    position: absolute; top: 0; left: 0; right: 0; height: 24px;
    padding: 0 6px 0 6px;
    border-left: 4px solid transparent;
    font-family: var(--mst-tabular-font, monospace); font-variant-numeric: tabular-nums;
    font-size: 12px; white-space: nowrap; box-sizing: border-box;
    border-bottom: 1px solid rgba(255,255,255,0.04);
}
.mst-grid-row:not(.mst-grid-flag) { display: grid;
    grid-template-columns: 56px 48px minmax(150px, 1.4fr) 24px 24px 24px 110px 44px 50px 88px 96px 84px 92px 76px 58px 62px minmax(120px, 1fr) 40px 42px 50px 44px 64px;
    align-items: center; column-gap: 6px; }
.mst-grid-row:not(.mst-grid-flag):hover { background: rgba(255,255,255,0.07) !important; }
.mst-grid-row .g-c { overflow: hidden; text-overflow: ellipsis; text-align: center; }
.mst-grid-row .g-l { text-align: left; }
.mst-grid-row .g-car { font-weight: 800; }
.mst-grid-row .g-dim { opacity: 0.7; }
.mst-grid-row .g-unknown { color: var(--mst-flag-red); font-weight: 800; }
.mst-grid-row .g-alert { background: #DC2626; color: #fff; border-radius: 3px; }
.mst-grid-row .g-bad { color: var(--mst-flag-red); font-weight: 800; }
.mst-grid-row .g-warn { color: var(--mst-flag-yellow); font-weight: 700; }
.mst-grid-row .g-badges { font-size: 10px; font-weight: 800; color: #F472B6; }
.mst-grid-row .g-i { cursor: pointer; display: flex; justify-content: center; opacity: 0.75; }
.mst-grid-row .g-i:hover { opacity: 1; }
.mst-grid-row .g-i img { width: 16px; height: 16px; }
.mst-grid-st1 { background: rgba(148,163,184,0.17); } /* lap band - made more obvious 2026-10-01 (was 0.035 white) */
.mst-grid-st2 .g-lastlap { background: rgba(244,114,182,0.28); text-decoration: line-through; }
.mst-grid-st3 { background: rgba(203,213,225,0.12); text-decoration: line-through; }
.mst-grid-st4 { background: rgba(56,189,248,0.12); }
/* Smart Start SEEN record - a real crossing kept for the record, never timed. */
.mst-grid-st5 { opacity: 0.55; font-style: italic; }
.mst-grid-flag {
    display: flex; align-items: center; gap: 24px; padding-left: 14px;
    color: #0B1220; font-weight: 800; cursor: context-menu;
}
.mst-grid-flag .mst-grid-flagname { letter-spacing: 0.06em; }

/* Pit Details/Sectors/Microsectors' own header rows, matched to Passings'
   exact size - Dan's own request 2026-09-27, live: "the size and color
   scheme of the header block of the passings... is absolutely beautiful.
   We need to make that same setting for the data header block in 'PIT
   DETAILS', 'SECTORS' and 'MICROSECTORS' pages." The colour half of that
   (#0B1F6B) was already shared app-wide via the plain .mst-tabular rule
   above - this is just the size half Passings ALSO got (bigger padding,
   +2px font) that these three pages hadn't. Same !important requirement as
   Passings' own rule above, for the same reason - the blanket compact-cell
   rule elsewhere in this file also matches header <th> cells and would
   otherwise win. */
.mst-pitdetails-table .mud-table-head .mud-table-cell,
.mst-sectors-table .mud-table-head .mud-table-cell,
.mst-microsectors-table .mud-table-head .mud-table-cell {
    padding-top: 9.5px !important;
    padding-bottom: 9.5px !important;
    font-size: calc(0.625rem + 2px) !important;
}

/* Pit Details' own data rows (the "cars pane") - Dan's own request
   2026-09-27, live: "pit details needs to be 1px larger on font, and 3px
   higher per row in the details." Scoped to the table body only (not
   .mud-table-head) - the header just got its own separate size bump above,
   matching Passings/Sectors/Microsectors instead of this. 3px split evenly
   across top+bottom, same approach as every other "N px higher" request
   this session. */
.mst-pitdetails-table .mud-table-body .mud-table-cell {
    font-size: calc(0.6875rem + var(--mst-row-font-size-extra) + 1px) !important;
    padding-top: 2.5px !important;
    padding-bottom: 2.5px !important;
}

.mst-tabular-compact .mud-table-row {
    height: auto;
}

/* Passings.razor (and, since 2026-09-19, Sectors/MicroSectors) scroll
   their own wrapper div, not MudTable's built-in FixedHeader mechanism
   (that needed an ancestor chain to shrink correctly, which it wasn't
   reliably doing - see that page's own comment) - so the sticky header
   has to be done by hand here instead. Needs an opaque background or
   table rows would show through as they scroll underneath it.

   This was silently NOT WORKING at all, on every page, until confirmed
   and root-caused 2026-09-19 (Dan: "make sure the header bar is always
   visible... don't let the rows scroll the header bar out of view" -
   turned out it never actually had been, on any page, despite looking
   fine in static screenshots). MudTable wraps its own <table> in a
   `.mud-table-container` div that carries `overflow:auto` regardless of
   whether IT ever actually needs to scroll - CSS position:sticky
   resolves against the NEAREST ancestor with a non-visible overflow,
   found by walking up the tree, not the nearest one that's actually
   scrolling. Since `.mud-table-container` sits between the sticky thead
   and the real scrolling wrapper div outside it, sticky was resolving
   against that inert, non-scrolling container instead - inside which the
   header was already sitting exactly at its own top edge, so it had
   nothing to visibly "do", and the whole container (header included)
   just scrolled away with everything else. Neutralising its overflow
   here removes it as a competing scroll-container candidate, letting
   sticky resolve to the real one instead - confirmed live with a direct
   scrollTop test (not just eyeballing a screenshot, which can't
   distinguish "stuck" from "coincidentally still visible"). */
.mst-tabular-compact .mud-table-container {
    overflow: unset;
}

.mst-tabular-compact thead.mud-table-head {
    position: sticky;
    top: 0;
    z-index: 2;
    /* #0B1F6B - the standing column-header background (see .mst-tabular
       .mud-table-head .mud-table-cell's own comment) - a real colour here,
       not just var(--mst-surface), so a sticky header still shows the same
       blue full-bleed across the row (including any cell-border gaps) as
       it scrolls over rows underneath. */
    background: #0B1F6B;
}

/* Program's run list specifically - Dan's own request 2026-09-27, live:
   "make the run cells 3px less in height and replace that with a 3px high
   solid light grey line" - trims the cell's own vertical padding by 3px
   and puts a real divider line in the space that frees up, rather than
   just shrinking the row. border-collapse on the table keeps adjacent
   rows' borders from doubling up. Line thinned to 1px same day, his own
   follow-up ("can we change that to 1px please") - row height itself
   stays at the already-trimmed size, only the line got thinner. */
.mst-program-table {
    border-collapse: collapse;
}
.mst-program-table .mud-table-cell {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-bottom: 1px solid #94A3B8 !important;
}

/* Sectors specifically - Dan's own request 2026-09-21: "squish that whole
   page up a bit, because we cannot see all of the entries... reduce the
   vertical padding in the cells" (keeping .mst-race-number's own fixed
   badge size untouched - only the cell's own padding/line-height shrinks,
   not its content). Tighter than the shared .mst-tabular-compact baseline,
   which still left this specific page too tall to show a full field at once
   once the per-row "In Sector" progress indicator was in play. */
.mst-sectors-table.mst-tabular-compact .mud-table-cell {
    padding-top: 0;
    padding-bottom: 0;
    /* 0.85 base +10% (2026-09-22, Dan's own follow-up: "the sectors page is
       much better, but slightly squished... add 10% to the vertical
       height") - still well below the shared 0.95 baseline above. Used to
       be further adjustable by a row-height knob - fixed back to a plain
       value 2026-09-27 (Dan's own request, live). */
    line-height: 0.935;
}

/* Row-by-row zebra striping - Sectors and MicroSectors (2026-09-22, Dan's
   own request: "background alternation... on a row by row basis for the
   microsectors and sectors, which makes it easy to look across a line to
   see all of the details on one car at a time"). Plain nth-of-type on the
   <tr> works with zero C# involvement - every <td> in a row with no
   condition-specific background of its own (the "in progress"/"field
   fastest"/"current segment" highlights all set their own opaque
   background only on the one cell they apply to) stays transparent and
   lets this show through underneath. See Passings.razor's own
   RowStyleForTimeline for the DIFFERENT, lap-grouped alternation used
   there instead - that one flips on "the leader just crossed the main
   line", not on plain row position, so it can't be done in CSS alone. */
.mst-zebra-rows tbody tr.mud-table-row:nth-of-type(even) {
    background: rgba(96, 165, 250, 0.14); /* same light blue everywhere (Dan 2026-10-01) */
}

/* Bottom-left server performance monitor (NavMenu.razor) - deliberately
   matches MST-Display's own SystemHealthWidget (C:\BB\MST-Display\
   SystemHealthWidget.cs) look: near-black panel, bold uppercase title,
   three label+value+dot+sparkline rows. margin-top:auto on the flex column
   wrapper pushes the whole block to the bottom of the drawer regardless of
   how many nav links are above it. */
.mst-perf-monitor {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px 8px 12px;
    border-top: 1px solid var(--mst-muted);
    background: #121214;
    font-variant-numeric: tabular-nums;
    cursor: default;
}

.mst-perf-title {
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: #D3D3D3;
    white-space: nowrap;
    overflow: hidden;
}

.mst-perf-row {
    display: flex;
    align-items: center;
    gap: 4px;
}

.mst-perf-label {
    width: 22px;
    flex-shrink: 0;
    font-size: 0.625rem;
    font-weight: 700;
    color: #C0C0C0;
}

.mst-perf-value {
    width: 40px;
    flex-shrink: 0;
    font-family: "Consolas", monospace;
    font-size: 0.625rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
}

.mst-perf-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
}

.mst-perf-graph {
    flex: 1 1 auto;
    min-width: 0;
    height: 20px;
    background: #0A0A0C;
    border: 1px solid #323237;
    border-radius: 2px;
}

/* Passings status-column badges - Dan's own request (2026-09-21): "show a
   graphically generated 'DL' icon... or 'DT' icon... a graphic exclamation
   mark" for disallowed-lap/disallowed-time-only/modified-time, each with
   its own hover explanation (the `title` attribute on the span, set in
   Passings.razor). Same "small solid-colour rounded badge" language as
   .mst-race-number below, just sized for a dense multi-badge cell instead
   of a single always-present number. */
.mst-status-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 15px;
    min-width: 15px;
    padding: 0 3px;
    border-radius: 3px;
    font-weight: 800;
    font-size: 0.5625rem;
    line-height: 1;
    cursor: default;
}

.mst-status-badge-dt {
    background: var(--mst-flag-yellow);
    color: #000;
}

.mst-status-badge-dl {
    background: var(--mst-flag-red);
    color: #fff;
}

.mst-status-badge-modified {
    border-radius: 50%;
    background: #38BDF8;
    color: #000;
    font-size: 0.625rem;
}

/* Passings' Loop Filter - rebuilt from a dropdown back to an always-visible
   grid 2026-09-28, live, Dan's own mockup: real checkboxes ("the X is a
   checkbox, make it a nice one"), packed tight so it doesn't eat header
   space the way the old spread-out pill row did. grid-auto-flow:column with
   a fixed row count reads top-to-bottom then wraps into a new column,
   matching his own mockup's 3-ish narrow columns for however many loops/
   tags this run has. */
/* Shared bounding box for the grid + its Select All/None actions - Dan's
   own follow-up, live: they need to visually read as ONE unit ("they need
   to look like they apply to the loop select, not the filter box"), not as
   the actions belonging to whatever sits next to them in the row. */
.mst-loopfilter-panel {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 6px 12px;
    border: 1px solid var(--mst-muted);
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.02);
}

.mst-loopfilter-grid {
    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(6, auto);
    column-gap: 18px;
    row-gap: 3px;
    align-items: center;
}

.mst-loopfilter-item {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    user-select: none;
    touch-action: manipulation;
    -webkit-touch-callout: none;
    font-weight: 700;
    font-size: 0.8rem;
    /* Was a bright red/coral - Dan's own mockup used pink/red purely as a
       "look, this is what I'm pointing at" marker, not an actual colour
       choice ("that was just so it was obvious what I was changing... can
       you make them a much nicer color"). Same teal family as FAST MODE
       below (his own request: "maybe a different shade of whatever you
       choose") - a lighter tint here since this is plain body text read
       constantly, not a single glanceable state pill. */
    color: #5EEAD4;
    white-space: nowrap;
}

.mst-loopfilter-item:hover {
    opacity: 0.8;
}

/* Loop Filter colour-by-type scheme - Dan's own spec 2026-09-27, live,
   right after a real operational trap: "i couldn't find any pit main
   crossings... because i forgot that this track does not have a pit
   main... we use pit exit as pit main as well as pit exit." Priority
   order computed in Passings.razor's own LoadAsync (first match wins):
   CountAsLap, then pit lane, then a sector boundary, then a plain
   position line (TreatAsTimingLoop), then a Speedtrap Entry/Exit loop -
   everything else keeps the existing default colour above (#5EEAD4)
   unchanged, per his own "no need to change their order.. just change
   the colors." currentColor (used by .mst-loopfilter-check's own border
   and X glyph) picks these up automatically, no separate override needed
   there. */
.mst-loopfilter-item.mst-loopfilter-cat-countaslap { color: #FB923C; }
.mst-loopfilter-item.mst-loopfilter-cat-pit { color: #60A5FA; }
.mst-loopfilter-item.mst-loopfilter-cat-sector { color: #FDE047; }
.mst-loopfilter-item.mst-loopfilter-cat-position { color: #C084FC; }
.mst-loopfilter-item.mst-loopfilter-cat-speedtrap { color: #F472B6; }

/* The checkbox itself - unchecked is just the outline; checked shows an X
   glyph inside it, not a checkmark, per Dan's own spec ("the X is a
   checkbox"). Plain CSS box + pseudo-element rather than a native
   <input type=checkbox> - the div it lives in is already the whole
   clickable/toggleable target (see the markup's own comment), so this is
   purely a visual indicator, not a second independent control. */
.mst-loopfilter-check {
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-radius: 3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.mst-loopfilter-check-on::after {
    content: "\2715";
    font-size: 11px;
    line-height: 1;
    font-weight: 900;
}

.mst-loopfilter-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

.mst-loopfilter-actionbtn {
    min-width: 64px !important;
}

/* FAST MODE pill - restyled 2026-09-28, live, Dan's own words: "why can't
   we just use FAST MODE all the time... can we not make it pretty? does it
   need to look like 1970s fortran?" A real coloured pill instead of a
   plain outlined MudButton, matching his own mockup's shape - muted/
   outlined off, solid with a soft glow on, same "colour tells you the
   state at a glance" convention every other race-control button already
   uses (see race-control-button-colors.md memory). Colour itself switched
   from the mockup's pink/magenta to the app's own teal accent
   (--mst-accent) the same day - his own correction: "the pink... was just
   so it was obvious what I was changing [in the mockup]... make them a
   much nicer color." Deliberately NOT pink/magenta regardless - #EC4899
   already means "Stop Run" on this exact page (.mst-race-btn-stoprun),
   and reusing it here would blur two unrelated buttons together. */
.mst-fastmode-btn, .mst-fastmode-btn:disabled {
    color: var(--mst-accent) !important;
    background: transparent !important;
    border: 2px solid var(--mst-accent) !important;
    font-weight: 800 !important;
    border-radius: 999px !important;
    padding: 0 16px !important;
}

.mst-fastmode-btn-on, .mst-fastmode-btn-on:disabled {
    color: #fff !important;
    background: var(--mst-accent) !important;
    border: 2px solid #5EEAD4 !important;
    box-shadow: 0 0 10px 2px rgba(20, 184, 166, 0.65);
}

/* Race Control's "Drivers" column - Dan's own request 2026-09-28: both
   drivers' names, current stint time (ticking) and lap%, colour-coded
   green/yellow/orange/flashing-white-on-red by proximity to the run's own
   CategoryStintRule. One .mst-stint-driver-row per driver on the car -
   the currently-driving one gets a subtle highlight so it's obvious at a
   glance which name the ticking time belongs to. */
/* 2026-10-01: a grid so every row lines up - name | laps badge | current stint (text, right). */
.mst-stint-driver-row {
    display: grid;
    /* Fixed columns so every car's rows line up whatever the name length (Dan 2026-10-01: "cell it up so it's all
       uniform"). Long names are cut with ... and shown in full on hover. */
    grid-template-columns: max-content;
    align-items: center;
    column-gap: 8px;
    font-size: 0.78rem;
    line-height: 1.5;
    white-space: nowrap;
}

/* No minimum set for the run - neutral, never a misleading green. */
.mst-stint-none {
    background: #9CA3AF;
    color: #fff;
}

/* Current stint: plain text, green while inside the limit, then yellow / orange / flashing red. */
.mst-stint-time { font-weight: 800; font-variant-numeric: tabular-nums; text-align: center; cursor: help; }
.mst-stint-time-green { color: var(--mst-flag-green); }
.mst-stint-time-yellow { color: var(--mst-flag-yellow); }
.mst-stint-time-orange { color: var(--mst-flag-orange); }
.mst-stint-time-red { color: var(--mst-flag-red); animation: mst-stint-text-flash 0.8s step-start infinite; }
@keyframes mst-stint-text-flash { 50% { color: #fff; } }
.mst-stint-badge { cursor: help; }
.mst-stint-driver-row .mst-stint-badge { text-align: center; }
.mst-stint-driver-row .mst-stint-driver-name { min-width: 0; }
/* Each piece in its own cell (Dan 2026-10-01: "cell the driver name and stint total"). */
.mst-stint-driver-row + .mst-stint-driver-row { margin-top: 2px; }
/* Name + that driver's laps joined in ONE outlined cell (Dan 2026-10-01: "a single outside 1px line"). */
/* The driver in the car: the same frame also takes in the current stint time - "who is in the car, and how long
   they have been there" (Dan 2026-10-01). */
.mst-stint-pair {
    display: grid; grid-template-columns: 20px 130px 92px; align-items: stretch;
    border: 1px solid var(--mst-muted); border-radius: 3px; overflow: hidden;
}
.mst-stint-pair > .mst-stint-driver-name { padding: 0 6px; overflow: hidden; text-overflow: ellipsis; }
.mst-stint-pair > .mst-stint-badge { border-radius: 0; font-weight: inherit; font-size: inherit; padding: 0 4px; }
.mst-stint-pair-current { grid-template-columns: 20px 130px 92px 70px; }
/* Skinny driver-number cell (yellow bold) + the driver in the car's name in green (Dan 2026-10-01). */
.mst-stint-driver-no { color: #FACC15; font-weight: 800; text-align: center; border-right: 1px solid var(--mst-muted); cursor: help; }
.mst-stint-pair-current > .mst-stint-driver-name { color: var(--mst-flag-green); }
/* Minimum not met yet, plenty of race left - plain, so green only ever means MET. */
.mst-stint-pending { background: transparent; color: inherit; }
.mst-stint-pair > .mst-stint-time { font-size: inherit; font-weight: inherit; }

.mst-stint-driver-current {
    font-weight: 700;
}

.mst-stint-driver-name {
    min-width: 80px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mst-stint-badge {
    display: inline-block;
    padding: 0 5px;
    border-radius: 3px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: #0B1220;
}

.mst-stint-green {
    background: var(--mst-flag-green);
}

.mst-stint-yellow {
    background: var(--mst-flag-yellow);
}

.mst-stint-orange {
    background: var(--mst-flag-orange);
    color: #fff;
}

.mst-stint-red {
    background: var(--mst-flag-red);
    color: #fff;
    animation: mst-stint-flash 0.8s step-start infinite;
}

@keyframes mst-stint-flash {
    50% {
        background: #fff;
        color: var(--mst-flag-red);
    }
}

/* Header flag badges (Green/Safety Car/FCY) - Dan's own request 2026-09-25:
   "3 times bigger", and built to match the rounded-square colour-coded
   artwork he attached (a bold centred "GO"/"SC"/"FCY" on a solid colour
   with a soft outer glow) - recreated here as styled elements rather than
   the literal PNG files, which weren't reachable on disk from the
   conversation (swap to <img> easily if Dan drops them somewhere
   readable). ~3x a MudIconButton Size.Small's own ~14px icon. */
.mst-flag-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 9px;
    font-weight: 900;
    font-size: 0.8rem;
    letter-spacing: 0.02em;
    color: #0B1220;
    cursor: pointer;
    user-select: none;
    margin: 0 2px;
}

.mst-flag-badge-go {
    background: var(--mst-flag-green);
    box-shadow: 0 0 7px 2px rgba(34, 197, 94, 0.65);
}

.mst-flag-badge-sc {
    background: var(--mst-flag-safety-car);
    box-shadow: 0 0 7px 2px rgba(245, 158, 11, 0.65);
}

.mst-flag-badge-fcy {
    background: var(--mst-flag-yellow);
    box-shadow: 0 0 7px 2px rgba(234, 179, 8, 0.65);
}

/* VSC - Dan's own request 2026-09-27, live: "add VSC into the topmost
   header bar with those other controls... exactly the same look and size
   please." Same .mst-flag-badge base as GO/SC/FCY, just its own colour. */
.mst-flag-badge-vsc {
    background: var(--mst-flag-vsc);
    box-shadow: 0 0 7px 2px rgba(217, 119, 6, 0.65);
}

.mst-flag-badge-disabled {
    opacity: 0.3;
    cursor: default;
    pointer-events: none;
    box-shadow: none;
}

/* Race control button bar (RunControl.razor/Passings.razor's own copy) -
   Dan's own request 2026-09-27, live: "we need to change all of the
   control bar icons to be solid color with text, just like Start clock
   and Finish are currently... memorise these values for all buttons
   related to control of the race." Values match MST.Domain.Racing.
   RaceControlPalette exactly - see that class's own doc comment and the
   race-control-button-colors.md project memory for the standing spec.
   !important throughout: MudButton's own Color prop paints a background at
   equal-or-higher specificity, loaded before this stylesheet. */
/* :disabled is a real pseudo-class here (MudButton's Disabled param renders
   a genuine HTML disabled attribute), not a MudBlazor CSS class - so it has
   to be listed explicitly on every single selector below. Found live
   2026-09-27: MudBlazor's own bundled rule targets `.mud-button-filled-
   default:disabled` (two classes + a pseudo-class), which beats a bare
   `.mst-race-btn[disabled]`/`.mst-race-btn.mud-disabled` attempt at this
   specificity even with !important on both sides - every disabled button
   was silently falling back to MudBlazor's own default grey. */
.mst-race-btn, .mst-race-btn:disabled {
    color: #fff !important;
    font-weight: 800 !important;
    border: none !important;
    min-width: 96px;
}
.mst-race-btn:disabled {
    opacity: 0.35 !important;
}
.mst-race-btn-warmup, .mst-race-btn-warmup:disabled {
    background-color: var(--mst-flag-warmup) !important;
}
/* Start Clock's own colour, distinct from Warmup - Dan's own correction
   2026-09-27, live, the same day he'd first said "Start clock, same [as
   Warmup]": "stuffed up.. start clock should be electric blue." */
.mst-race-btn-startclock, .mst-race-btn-startclock:disabled {
    background-color: var(--mst-flag-startclock) !important;
}
.mst-race-btn-smartstart, .mst-race-btn-smartstart:disabled {
    background-color: var(--mst-flag-smart-start) !important;
}
/* Smart Start button states (SmartStartButton.razor) - Dan's spec 2026-09-28. */
.mst-ss-armed { animation: mst-ss-flash 1s steps(2, jump-none) infinite; }
@keyframes mst-ss-flash {
    0% { filter: brightness(1); box-shadow: none; }
    100% { filter: brightness(1.7); box-shadow: 0 0 12px var(--mst-flag-smart-start); }
}
.mst-ss-disabled, .mst-ss-disabled:disabled { background-color: #475569 !important; color: #CBD5E1 !important; }
.mst-ss-counting, .mst-ss-counting:disabled { background-color: #16A34A !important; color: #fff !important; font-variant-numeric: tabular-nums; box-shadow: 0 0 10px rgba(22,163,74,0.6); }
.mst-race-btn-green, .mst-race-btn-green:disabled {
    background-color: var(--mst-flag-green) !important;
}
/* White text on all three, same as every other button - Dan's own
   correction 2026-09-27, live, same message as the Start Clock colour fix:
   "fonts on safety car, vsc and fcy would look better in white" (an
   earlier pass this same day had them on black). */
.mst-race-btn-safetycar, .mst-race-btn-safetycar:disabled {
    background-color: var(--mst-flag-safety-car) !important;
}
.mst-race-btn-vsc, .mst-race-btn-vsc:disabled {
    background-color: var(--mst-flag-vsc) !important;
}
.mst-race-btn-fcy, .mst-race-btn-fcy:disabled {
    background-color: var(--mst-flag-yellow) !important;
}
.mst-race-btn-red, .mst-race-btn-red:disabled {
    background-color: var(--mst-flag-red) !important;
}
.mst-race-btn-stoprun, .mst-race-btn-stoprun:disabled {
    background-color: #EC4899 !important;
}
.mst-race-btn-reset, .mst-race-btn-reset:disabled {
    background-color: #334155 !important;
}
/* Finish - Dan's own spec: "black background with a 75% opaque checkered
   flag - no text required." A real checker pattern (repeating-conic-
   gradient, not an image) so it scales cleanly to any button size. */
.mst-race-btn-finish, .mst-race-btn-finish:disabled {
    background-color: #000 !important;
    background-image: repeating-conic-gradient(rgba(255, 255, 255, 0.75) 0% 25%, transparent 0% 50%) !important;
    background-size: 16px 16px;
}

/* Hardware connection status strip - Dan's own request 2026-09-27: "little
   boxes that say 'X2 Main' in green... 'Dorian1' in red." One box per open
   LiveIngestionService connection - see MainLayout.razor/LiveHardwareStatusTracker. */
.mst-hardware-status-box {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 32px;
    padding: 4px 12px;
    border-radius: 8px;
    font-weight: 800;
    font-size: 0.76rem;
    letter-spacing: 0.02em;
    color: #fff;
    white-space: nowrap;
    border: 1.5px solid rgba(255, 255, 255, 0.55);
}

.mst-hardware-status-ok {
    background: var(--mst-flag-green);
    box-shadow: 0 0 7px 2px rgba(34, 197, 94, 0.65);
}

.mst-hardware-status-down {
    background: var(--mst-flag-red);
    box-shadow: 0 0 7px 2px rgba(239, 68, 68, 0.65);
}

/* Passing-activity pulse - Dan's own request 2026-09-27: "a small round dot
   with a dark blue ring... blink a light blue background with a dark blue
   'P'... for 50ms." Idle: just the ring, no fill, letter invisible. Active
   (.mst-passing-pulse-active, toggled from MainLayout's own OnPassingRecorded):
   light blue fill, dark blue letter. No CSS transition - a real instant
   on/off blink, not a fade, matching "blink" literally. */
.mst-passing-pulse {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    margin-right: 8px;
    border-radius: 50%;
    border: 2px solid #1E3A8A;
    background: transparent;
    font-weight: 900;
    font-size: 0.7rem;
    color: transparent;
}

.mst-passing-pulse-active {
    /* Deliberately NOT --mst-flag-warmup (#38BDF8) - the app bar's own
       background IS that colour while a run is in Warmup, which made this
       fill invisible against it (confirmed live, screenshot-caught 2026-09-27).
       A genuinely pale blue instead, visually distinct from every flag-state
       background the bar can take, not just the one that happened to clash. */
    background: #E0F2FE;
    color: #1E3A8A;
    box-shadow: 0 0 6px 2px rgba(224, 242, 254, 0.85);
}

/* Muted (long-pressed off) - Dan's own request 2026-09-27: "leave the blue
   circle with a small blue X in it when it is not activated." Same ring
   (no rule needed here beyond the base .mst-passing-pulse one - this class
   exists mainly so the markup's ternary can never combine it with
   -active), never fills/blinks while muted (OnPassingRecorded's own
   early-return) - the X is what tells "muted" and "idle but still
   watching" apart at a glance. */
.mst-passing-pulse-muted {
    opacity: 0.7;
}
.mst-passing-pulse-muted-x {
    color: #1E3A8A;
    font-size: 0.65rem;
    font-weight: 900;
    line-height: 1;
}

/* Recorded before Green was shown - SEEN, not yet a scoring PASSING. See
   Run.FirstGreenAtUtc's own doc comment. Muted/outline rather than a solid
   colour - unlike DL/DT/modified, this isn't flagging a problem, just a
   normal pre-race state. */
.mst-status-badge-seen {
    background: transparent;
    border: 1px solid var(--mst-muted);
    color: var(--mst-text-secondary, rgba(255, 255, 255, 0.6));
    font-size: 0.5rem;
    padding: 0 2px;
}

/* Resolved from a backup transponder (BackupTransponderTracker.PromoteFailover) -
   informational like SEEN, not itself a problem: the primary-silent event
   this crossing is a symptom of already raised its own Attention alert. */
.mst-status-badge-backup {
    background: transparent;
    border: 1px solid #38BDF8;
    color: #38BDF8;
    font-size: 0.5rem;
    padding: 0 2px;
}

/* Passings' hover/press page-lock - replaces the old manual Pause button
   (2026-09-22, Dan's own words: "let's remove the pause etc"). Toggled
   purely in JS (Passings.razor.js's attachIdColumnLock) the instant the
   pointer enters the trigger column, with zero server round trip - the
   whole point is instant feedback regardless of how backed up the
   circuit's own update queue is. td:nth-child(3) is the Status column
   (2026-09-23 - was the crossing-ID column before that column was removed
   from the table entirely; the lock's trigger zone moved onto Status,
   which landed at this same 3rd position) - see the header row's own
   column order comment if that ever changes again. !important because a
   disallowed/deleted/modified row already sets its own row-level
   background (RowStyleFunc) that would otherwise show through a plain
   background on this one cell at equal specificity. */
#passings-scroll.mst-id-locked td:nth-child(3) {
    background: var(--mst-flag-yellow) !important;
    color: #0B1220 !important;
}

/* Every row cell's inner div (the one carrying data-passing-id and the
   @oncontextmenu/@ondblclick handlers) must cover its ENTIRE cell, not just
   its own content's natural size - otherwise a right-click landing in the
   small leftover gap around that content (a flex row's own auto width, or
   a short text div shorter than the row's padded height) falls through to
   nothing with a handler attached, and the browser's OWN context menu
   shows instead - confirmed real 2026-09-23 (Dan's own report: "when i
   first right click, i get the chrome right click options... when i do it
   again" [it lands correctly]). height:100% on a direct child of a table
   CELL is a genuine CSS special case (unlike an ordinary block element,
   which needs an explicit ancestor height for a percentage height to
   resolve at all) - already proven working for the flag-colour strip
   cell's own identical inline width:100%; height:100%. This makes that the
   default for every such div in the table body, rather than repeating it
   by hand in every one of Passings.razor's ~13 per-column cells. */
#passings-scroll tbody .mud-table-cell > div:first-child {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
}

/* Race-number badge - the same convention every reference timing display
   uses: black text on a solid orange rounded rectangle, ALL numbers at the
   identical badge size (1 digit up to 3) so the column reads as a uniform
   strip rather than badges that grow/shrink with the number's width. */
.mst-race-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px; /* nudged up from 30px alongside the +2px font so a 3-digit number doesn't clip */
    height: 19px; /* nudged up from 18px for the same reason */
    border-radius: 5px;
    background: #F97316;
    color: #000;
    font-weight: 800;
    font-size: 0.8125rem; /* +2px over the table's base 0.6875rem, per Dan's own request 2026-09-19 */
    line-height: 1;
}

/* Plain-HTML app shell (2026-09-22, replacing MudLayout/MudAppBar/MudDrawer
   in MainLayout - see that file's own comment for why: any Blazor-bound
   event handler in that persistent layout broke click dispatch everywhere
   else). Fixed app bar at top, fixed-width nav rail below it, main content
   offset by both - the same visual shape MudLayout provided, just plain
   CSS instead of relying on Mud's own layout-detection machinery. */
.mst-shell {
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.mst-shell-body {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

/* MainLayout sets --mst-current-flag-color inline per-element when a run
   has an active flag; the fallback keeps the normal surface colour the
   rest of the time (no run, or no flag set yet). Deliberately NOT
   !important - that would always beat the inline custom-property value
   regardless of what it's set to, defeating the whole point. */
/* Three-zone header - Dan's own request 2026-09-27, live ("some cosmetic
   changes... in the topmost header bar"). padding-left:0 here (the 50px
   gutter comes from .mst-header-left's own margin-left instead) so that
   number is exact, not "50px plus whatever this bar's own padding already
   was". Height grown from the old fixed 64px to fit the doubled event/run
   text and the centre box comfortably, not just barely. */
.mst-appbar {
    background: var(--mst-current-flag-color, var(--mst-surface));
    border-bottom: 1px solid var(--mst-muted);
    transition: background-color 0.3s ease;
    position: relative;
    height: 64px;
    flex: 0 0 auto;
    color: var(--mst-text);
}

/* MudAppBar renders its own inner <div class="mud-toolbar..."> as the REAL
   flex row - Class="mst-appbar" only reaches the outer <header>, which
   doesn't cascade flex/justify-content down to a nested block element.
   Confirmed live 2026-09-27 via the rendered DOM - .mst-header-left was
   centring ITSELF (the only item left in normal flow once .mst-header-
   center/-right below go position:absolute) because THIS inner div still
   had MudBlazor's own default justify-content:center, unaffected by any
   rule aimed at .mst-appbar itself. !important beats MudBlazor's own
   bundled rule at equal specificity, loaded earlier in the cascade.
   Height grown 80px -> 120px 2026-09-27, live, same pass as the 70px clock,
   then back down to 100px, then to 64px shortly after that ("bring the
   size of each box down 75%... keep the font and graphics as large as you
   can within those two black boxes") - see --mst-header-box-height's own
   comment for the fonts/clock/logo that shrank the same pass. 64px happens
   to be MudBlazor's own untouched default AppBar height - not a
   coincidence chased on purpose, just where the numbers landed. MstTheme.cs's
   LayoutProperties.AppbarHeight MUST be kept in sync with this value - see
   that field's own doc comment for the nav-drawer-clipping bug this
   prevents. */
.mst-appbar .mud-toolbar {
    justify-content: flex-start !important;
    height: 64px !important;
    padding: 0 16px 0 0 !important;
}

.mst-header-left {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: 50px;
    flex: 0 0 auto;
    z-index: 1;
}

/* Shared box style for BOTH header side-boxes - the event/run/clock box
   (normal flow, inside .mst-header-left) and the logo box (position:
   absolute, see .mst-header-logo-box below) - Dan's own request 2026-09-27,
   live: "make that box [the logo] the same width as the right side box...
   swap the current event info and the mstiming logo." One shared class for
   the dimensions/background/radius both boxes need identical, rather than
   tuning two selectors to match by eye - same "no drift" reasoning as the
   --mst-header-box-height variable itself. Background not pure black, but
   the same almost-black colour as the sidebar (Dan's own request 2026-09-27:
   "make the backgrounds of these boxes not pure black, but the same almost
   black color as the background of the menu tree") - var(--mud-palette-
   drawer-background) IS that colour (MstTheme's ColorBackground, #0B1220,
   is what DrawerBackground is set to for every dark-ish palette), so this
   tracks the theme picker instead of being a second hardcoded value that
   can drift out of sync with the sidebar. */
.mst-header-side-box {
    box-sizing: border-box;
    height: var(--mst-header-box-height);
    width: var(--mst-header-side-box-width);
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--mud-palette-drawer-background);
    color: #F8FAFC;
    border-radius: 10px;
    padding: 2px 12px;
    overflow: hidden;
}

/* Purple ring on the active-event box - Dan's own spec 2026-09-22, live:
   "put a purple ring around the active event title bar." Inset box-shadow
   rather than border, so it doesn't add to the box's own width/height (that
   width is shared with the logo box via --mst-header-side-box-width - a
   real border would throw the two out of sync). Same #7C3AED as
   RaceControlPalette.Purple/the drawer's own NavAccentColor - not
   reinvented here. Always on - this box always shows the active event, see
   MainLayout's own _eventName comment - unlike the editing box below, which
   is conditional. */
.mst-header-active-ring {
    box-shadow: 0 0 0 3px #7C3AED inset;
}

/* Purple event-name text - Dan's own follow-up request 2026-09-22, live,
   same pass as the ring-conditionality fix above: "make [eventname] text
   purple." Same #7C3AED, same condition (_isHeaderBoxActiveEvent) as the
   ring itself - text and ring always agree. Only the event-name line, not
   the run-name line below it (mst-event-run-line-run-big keeps its own
   colour) - this is specifically about identifying the EVENT as active. */
.mst-header-eventname-active {
    color: #7C3AED;
}

/* "BEING EDITED" box - Dan's own spec 2026-09-22, live: "IF we are EDITING
   a different event, we add a box the same height and 2/3 of the width
   with the electric blue ring around it, with electric blue text saying
   '[EventName] BEING EDITED'... this can then be seen from every page."
   Only rendered (MainLayout.razor) while SystemSettings.EditingMeetingId
   points at a real, non-archived Meeting DIFFERENT from the active one -
   sits in normal flow right after the active-event box, not position:
   absolute like the logo box, since there's no space permanently reserved
   for it. Same #0066FF as RaceControlPalette.ElectricBlue. */
.mst-header-editing-box {
    box-sizing: border-box;
    height: var(--mst-header-box-height);
    width: calc(var(--mst-header-side-box-width) * 2 / 3);
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    background: var(--mud-palette-drawer-background);
    border-radius: 10px;
    padding: 2px 10px;
    overflow: hidden;
    box-shadow: 0 0 0 3px #0066FF inset;
    color: #0066FF;
}

.mst-header-editing-box-name {
    font-weight: 700;
    font-size: 0.95rem;
    line-height: 1.1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

.mst-header-editing-box-label {
    font-weight: 900;
    font-size: 0.8rem;
    letter-spacing: 0.5px;
    line-height: 1.1;
}

/* A field that genuinely has a value stands out - Dan's own live request
   2026-09-28, looking at Modify Run's Categories tab: "it's probably not a
   bad idea to have the print bolded (and possibly even electric blue on
   fields which we have filled in.. It's not enough that the text is
   bolded.. you want any changed stuff to stand out." Same #0066FF as
   RaceControlPalette.ElectricBlue/the header's own "BEING EDITED" box
   above, applied to the closed input's own displayed text (not just the
   label) - the field's OWN value is what should visually announce itself,
   not a blank one waiting to be filled in. Applied per-field (Class bound
   to a "has this got a real value" check) rather than globally, so an
   intentionally-blank optional field stays visually quiet. Started on
   Modify Run's Categories tab (Category/Classes) - a reusable class, not
   a one-off style, so extending the same treatment to this dialog's other
   tabs later is just adding the same Class binding, no new CSS needed. */
.mst-field-filled input,
.mst-field-filled .mud-select-input,
.mst-field-filled .mud-input-slot {
    font-weight: 800 !important;
    color: #0066FF !important;
}

/* The logo box's own instance of .mst-header-side-box - position:absolute
   (it's no longer inside .mst-header-left's normal flow, now that the
   event/run box took its spot there - see MainLayout's own comment on the
   2026-09-27 swap), inset from the bar's true right edge to clear the icon
   rail (.mst-header-iconrail) sitting even further right. justify-content:
   space-between spreads its two children across the box's own width.
   Class name kept even though the logo itself is gone (see .mst-header-logo
   below) - still "the box on the right, opposite the event/run box," same
   width/position either way; renaming it would just be churn until the
   logo's new home is decided. */
.mst-header-logo-box {
    position: absolute;
    right: 72px;
    top: 50%;
    transform: translateY(-50%);
    justify-content: space-between;
}
/* The MS Timing logo itself - removed from this box 2026-09-24, live,
   Dan's own words: "ditch the MS Timing logo for now... we will find
   another place for it." Rule kept (unused for now, no element references
   it) for whenever that new spot is decided - the sizing work below isn't
   worth redoing from scratch. TIME TO GO (.mst-header-timetogo) took its
   old slot in the box instead - Maximised within its box - Dan's own
   request 2026-09-27, live: "try and maximise the size of the logo... it
   seems to have lots of spare black around the words." The source PNG
   itself is already tightly cropped (a ~8px transparent margin on a
   4395x1066 image, confirmed live via a pixel-bbox scan) - the "spare
   black" was this height being only 36px inside a box that was, at the
   time, var(--mst-header-box-height) (68px) tall, not padding in the
   image. Grew to 56px when the box grew to 108/88px, shrunk back to 32px
   once the box itself shrank to 52px ("bring the size of each box down
   75%... keep the font and graphics as large as you can within those two
   black boxes") - same "maximised for this box's own height" reasoning
   throughout, just re-applied to each new box size rather than a number
   picked once and left stale. */
.mst-header-logo {
    height: 32px;
    width: auto;
    display: block;
}

/* TIME TO GO - countdown to the live run's scheduled finish, took the
   logo's old slot in the box (see .mst-header-logo's own comment) - Dan's
   own request 2026-09-24, live: "the countdown timer for when the event
   finishes." Stacked label-over-value so it reads clearly at a glance
   despite sharing the box with the clock; the value itself reuses
   .mst-header-clock as-is (Dan's own follow-up: "that time to go needs to
   be the same as the clock") rather than a second, slightly-different
   copy of that styling. */
.mst-header-timetogo {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.mst-header-timetogo-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--mst-flag-startclock);
    opacity: 0.8;
}

/* TIME TO GO colour states - Dan's own spec 2026-09-27, live: "that clock
   should be different colors.. green when running, yellow when 3 mins to
   go, bright orange at 1min (with a computer alarm tone too) and then
   bright red when the clock hits zero." Driven by mstClock.js setting one
   of these classes on #mst-header-timetogo-value every tick - the default
   .mst-header-clock electric-blue colour/glow stays as the "not running"
   (no target set, showing --:--:--) state, these four override it only
   while a real countdown is live. Glow colour matches each state's own
   text colour (swapped, not just the text) so the box reads clearly at a
   glance from across a room, same "text-shadow announces state" idea the
   base clock already uses. */
#mst-header-timetogo-value.mst-ttg-running {
    color: #22C55E;
    text-shadow: 0 0 14px rgba(34, 197, 94, 0.6);
}

#mst-header-timetogo-value.mst-ttg-warn {
    color: #EAB308;
    text-shadow: 0 0 14px rgba(234, 179, 8, 0.6);
}

#mst-header-timetogo-value.mst-ttg-critical {
    color: #F97316;
    text-shadow: 0 0 16px rgba(249, 115, 22, 0.7);
    animation: mst-ttg-pulse 1s ease-in-out infinite;
}

#mst-header-timetogo-value.mst-ttg-expired {
    color: #EF4444;
    text-shadow: 0 0 16px rgba(239, 68, 68, 0.75);
}

@keyframes mst-ttg-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
    #mst-header-timetogo-value.mst-ttg-critical {
        animation: none;
    }
}

/* ACTIVE FOR - elapsed time since the live run went green, Dan's own
   request 2026-09-27: "add 'Active For' with the running counter since
   the session started." Purple - his own words: "Active for should be
   purple (all active references are purple)" - same #7C3AED (--mst-flag-
   warmup) every OTHER "this is the active thing" indicator in the app
   already uses (the active-event header box/ring). */
#mst-header-activefor-value {
    color: #7C3AED;
    text-shadow: 0 0 14px rgba(124, 58, 237, 0.6);
}

/* RUN TIME/DURATION-or-TIME TO GO/CURRENT TIME on the kiosk display
   boards' own session header row (BroadcastLiveScene, RaceControlDisplay,
   RaceDirectorDisplay) - Dan's own request 2026-09-27, live, refined
   across several follow-ups (see BroadcastLiveScene.razor's own markup
   comment for the full quote trail) - smaller than MainLayout's own 38px
   header clock (this row has three of these plus everything else already
   in it, not one clock alone), but as large as the row's own established
   height allows: "make the font as big as possible on the 3 clocks,
   without breaking out of the cell." font-variant-numeric here (not just
   the .mst-tabular class on the plain-div DURATION/LAPS case) so
   ClientTickedValue's own rendered div - which only ever receives THIS
   class, never .mst-tabular too - lines its digits up identically to
   DURATION's own, matching Dan's own "the current duration font is bigger
   than the other 2" report (proportional digits reading visibly smaller
   than DURATION's tabular ones at the identical declared font-size, not a
   genuine size difference). A default colour only (var(--disp-accent-
   bright), same as DURATION's own value colour) since the
   #mst-header-timetogo-value.mst-ttg-(state) / #mst-header-activefor-value
   rules above already override colour by ID wherever they apply,
   regardless of what page the element lives on. */
.mst-broadcast-clock-value {
    font-size: 1.7rem;
    font-weight: 800;
    color: var(--disp-accent-bright);
    font-variant-numeric: tabular-nums;
}

/* CHECKERED flag pill - real checkerboard, not a flat colour - see
   BroadcastLiveScene.razor's own markup comment for the full story. 14px
   squares (smaller than the top strip's own 24px - this pill is a much
   shorter box) so at least 2-3 full squares show across its own height. */
.mst-flagpill-checkered {
    background-image:
        linear-gradient(45deg, #000 25%, transparent 25%, transparent 75%, #000 75%, #000),
        linear-gradient(45deg, #000 25%, #fff 25%, #fff 75%, #000 75%, #000);
    background-size: 14px 14px;
    background-position: 0 0, 7px 7px;
    color: #fff;
    text-shadow:
        -1.5px -1.5px 0 #000, 1.5px -1.5px 0 #000,
        -1.5px 1.5px 0 #000, 1.5px 1.5px 0 #000,
        0 2px 8px rgba(0,0,0,0.6);
}

/* Track Map Tracer dialog sizing - Dan's own request 2026-09-27: "as close
   to full size as you can go, so i can see everything." Enforced on the
   dialog's own OUTER Paper (the real .mud-dialog element), not just its
   inner content - the earlier attempt sized only the inner content area,
   so the title bar + action buttons' own height got added ON TOP of that,
   pushing the whole dialog taller than the viewport and leaving stray
   scrollbars instead of a genuinely full-size window. Covers both
   possible ways MudDialog's own Class parameter could land in the DOM
   (directly on .mud-dialog, or on a wrapping element) so this can't
   silently no-op if that changes in a future MudBlazor version.
   Maximize/restore toggle (TrackMapTracerDialog.razor) swaps between the
   two - starts at 90%, can go further via the title bar's own button.

   REAL BUG found live 2026-09-28 (Dan: "the maximise window function does
   not work on the track map"): the global ".mud-dialog-container
   .mud-dialog" rule further down this file has the SAME specificity
   (two classes) as the plain ".mst-tracer-dialog .mud-dialog" selectors
   below, and appears LATER in source order - on an equal-specificity tie,
   CSS resolves by source order (last declared wins), so that global rule's
   own width/max-width silently won regardless of maximize state. Only
   HEIGHT was ever actually toggling. Fixed by adding a 3-class variant of
   each selector (".mud-dialog-container .mst-tracer-dialog .mud-dialog"),
   which now GENUINELY outranks the global rule's specificity rather than
   relying on staying below it in the file - safe regardless of future
   edits moving either rule around. Also bumped the maximized size to 99vw/
   99vh (was 98) - Dan's own literal "as close to full size as you can go". */
.mst-tracer-dialog.mud-dialog, .mst-tracer-dialog .mud-dialog, .mud-dialog-container .mst-tracer-dialog .mud-dialog {
    width: 90vw !important;
    max-width: 90vw !important;
    height: 90vh !important;
    max-height: 90vh !important;
}
.mst-tracer-dialog-max.mud-dialog, .mst-tracer-dialog-max .mud-dialog, .mud-dialog-container .mst-tracer-dialog-max .mud-dialog {
    width: 99vw !important;
    max-width: 99vw !important;
    height: 99vh !important;
    max-height: 99vh !important;
}

/* Trace New Track Map - one compact toolbar row, a small hint line, the map gets the rest (Dan 2026-10-02). */
.mst-tracer-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.mst-tracer-bar .mud-input-control { margin: 0 !important; flex: 0 0 auto; }
.mud-dialog.mst-tracer-dialog, .mud-dialog.mst-tracer-dialog-max { display: flex !important; flex-direction: column !important; }
.mst-tracer-dialog .mud-dialog-content, .mst-tracer-dialog-max .mud-dialog-content { flex: 1 1 auto !important; min-height: 0 !important; max-height: none !important; display: flex; flex-direction: column; overflow: hidden !important; }
.mst-tracer-hint { font-size: 0.72rem; opacity: 0.7; margin: -2px 0 2px 2px; line-height: 1.2; }
.mst-tracer-dialog .mud-dialog-title, .mst-tracer-dialog-max .mud-dialog-title { padding: 8px 16px !important; }
.mst-tracer-dialog .mud-dialog-content, .mst-tracer-dialog-max .mud-dialog-content { padding: 0 16px 12px !important; }

/* TV TEST / DEBUGGING banner (renamed + split from the combined "VIDEO
   TEST" box 2026-09-25, live - see SystemSettings.TvTestModeEnabled/
   DebuggingModeEnabled's own doc comments) - Dan's own original spec
   2026-09-22, live: "when in test mode, we should have a big red TEST MODE
   white letters in a black box on the right side topmost header," then
   2026-09-25: "modify the button... so it's the same height as the flag
   controls button... change the version font to white and centre it in the
   button." Pinned to the same right:460px slot as before (flush against
   the logo box's own left edge, landing in the empty grey strip between
   the flag-bar centre group and the logo box). Height now matches
   .mst-flag-badge (40px, the GO/SC/FCY/VSC controls in the same header
   row) instead of growing to fit two absolutely-positioned elements -
   label + version stamp are both real children now, stacked in a column
   and centred, not separately positioned. Only ever rendered while
   TvTestModeEnabled or DebuggingModeEnabled is true - see MainLayout's own
   _tvTestModeEnabled/_debuggingModeEnabled fields and ModeBannerText. */
.mst-header-videotest-box {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    right: 460px;
    height: 40px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    background: #000000;
    border: 3px solid #EF4444;
    border-radius: 6px;
    padding: 0 14px;
    white-space: nowrap;
    z-index: 2;
}

.mst-header-videotest-label {
    color: #FFFFFF;
    font-weight: 900;
    font-size: 0.85rem;
    letter-spacing: 0.05em;
    line-height: 1.1;
}

/* Build version stamp - Dan's own request 2026-09-22, live: "if you are in
   EDIT MODE, it shows the version number." Moved INSIDE the box above
   2026-09-25, live: "change the version font to white and centre it in the
   button" (previously its own absolutely-positioned black-text element
   sitting just below the box). */
.mst-header-version-stamp {
    color: #FFFFFF;
    font-size: 0.55rem;
    font-family: Consolas, 'Courier New', monospace;
    line-height: 1;
    opacity: 0.85;
}

/* Event Entrants' "a Run has no drivers yet" warning triangle - Dan's own
   request 2026-09-28: "can we have the warning triangle flashing and twice
   the size." Size is set inline on the icon itself (Entrants.razor); this
   is just the flash. */
@keyframes mst-flash {
    0%, 49% { opacity: 1; }
    50%, 100% { opacity: 0.25; }
}
.mst-empty-runs-warning {
    animation: mst-flash 1s step-end infinite;
}

/* Any cell/panel that only appears because Debugging Mode is on - Dan's own
   request 2026-09-28: "should have a red ring around like the 'TV TEST +
   DEBUGGING' has in the topmost header bar." Same red/radius as
   .mst-header-videotest-box's own border, applied generically. */
.mst-debug-ring {
    border: 3px solid #EF4444 !important;
    border-radius: 6px !important;
}

/* Chequered-flag "took the flag" indicator - Dan's own request 2026-09-28:
   "a simple cell with a chequered pattern is fine here.. no special
   graphic." Pure CSS checkerboard (two overlaid 45deg gradients), shown
   next to a competitor's position on every leaderboard the instant
   Participation.State becomes Finished - car by car as the field crosses
   the line under the chequered flag, not all at once when the run ends.
   Sized as a small square swatch, not a full-cell fill, so it reads as an
   icon-like marker inside a narrow column. */
.mst-checkered-cell {
    display: inline-block;
    width: 16px;
    height: 16px;
    border-radius: 2px;
    background-color: #fff;
    background-image:
        linear-gradient(45deg, #111 25%, transparent 25%, transparent 75%, #111 75%, #111),
        linear-gradient(45deg, #111 25%, transparent 25%, transparent 75%, #111 75%, #111);
    background-size: 6px 6px;
    background-position: 0 0, 3px 3px;
}

/* Palette picker + font size, in a skinny vertical column at the bar's true
   right edge - Dan's own request 2026-09-27, live: "move the 3 icons top
   left of topmost header bar... across to the far right hand side of the
   header bar, and mount them vertically in a skinny column." Originally
   height:var(--mst-header-box-height) with justify-content:space-between
   to line up with the logo/event boxes - dropped once the box shrank to
   52px (see that variable's own comment): 3 buttons at any legible size
   no longer fit inside 52px, and space-between on an over-full container
   just overflows unpredictably rather than shrinking anything. height:auto
   + a small explicit gap sizes this to exactly what the 3 (now 20px)
   buttons need - it doesn't have to match the other boxes' height, it's a
   separate element just vertically centred alongside them via top:50%. */
.mst-header-iconrail {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 1px;
    align-items: center;
}
/* Shrunk from MudIconButton's own default ~40-48px touch target - Dan's own
   spec 2026-09-27, live, the same pass that shrank the appbar back down:
   "reduce the pallete/font tools if they are not efficient and causing it
   to bloat." At default size, 3 stacked icon buttons needed more vertical
   room than the clock itself did, making THIS (not the clock) the real
   height floor - shrinking them removes that as a constraint entirely.
   Shrunk again 24px -> 16px shortly after, alongside the box itself
   ("bring the size of each box down 75%") - 3x16px + 2 small gaps fits
   inside the new 52px box height, where 3x24px no longer would have.
   !important beats MudBlazor's own bundled button/icon sizing, same
   convention as .mst-race-btn's own overrides elsewhere in this file. */
/* R (recalculate) + C, their own column just left of the icon rail - Dan 2026-09-29. */
.mst-header-actionrail {
    position: absolute;
    right: 40px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: center;
}
.mst-header-iconrail button {
    width: 20px !important;
    height: 20px !important;
    padding: 1px !important;
}
.mst-header-iconrail svg {
    width: 15px !important;
    height: 15px !important;
}

/* Dead centre of the bar regardless of how wide the left/right zones end
   up being - a child of position:relative .mst-appbar, not just "next in
   flex flow" (which would only look centred if left/right happened to be
   equal width). Solid black, like the event/run box - readable over
   whatever flag colour the bar itself is showing. */
/* Centres the GROUP (Safety Car icon + this box + Safety Car icon), not
   just this box alone - see .mst-header-center-wrap below, which now owns
   the position:absolute/left/top/transform centring this rule used to have
   itself. */
.mst-header-center-wrap {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    gap: 14px;
}

.mst-header-center {
    display: flex;
    align-items: stretch;
    background: #000;
    border-radius: 12px;
    overflow: hidden;
}

/* Safety Car mode indicator either side of the GO/SC/VSC/FCY + status box -
   Dan's own request 2026-09-27, live: "when we are in safety car mode, can
   we put the icon... evenly on either side of the top controls/status box
   ... as large as possible without affecting the height or damaging other
   assets in the header." Swapped from a static badge PNG to an animated GIF
   2026-09-27, live - first a large banner, then swapped again the same day
   to a small pre-cropped transparent flashing version (SafetyCarFlashing.gif,
   native 135x70) once Dan supplied one. Same sizing rule applies regardless
   of source size - an animated GIF in an <img> just plays natively.
   Capped at --mst-header-box-height (same shared height every other header
   box uses) so it can only ever be as tall as the bar already comfortably
   allows - never taller, never forcing the appbar itself to grow, and
   never pushing the logo/status boxes it's centred alongside. width:auto
   keeps the source image's own aspect ratio (no stretching/distortion). */
.mst-header-safetycar-icon {
    height: var(--mst-header-box-height);
    width: auto;
    display: block;
}

.mst-header-center-left {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 8px;
    height: 60px;
    margin: 6px;
    padding: 0 8px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-radius: 9px;
}

/* box-sizing:border-box + an explicit height matching .mst-header-center-left
   EXACTLY, rather than trusting padding/content to coincidentally add up
   the same on both sides - a 1px grey line instead of that one's thicker,
   lighter border, everything else the same. Dan's own spec 2026-09-27,
   live: "put a 1px grey line around the server status and crossings
   indicator, exactly the same height as the one around the GO SC FCY." */
.mst-header-center-right {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 60px;
    margin: 6px 6px 6px 0;
    padding: 0 14px;
    border: 1px solid #94A3B8;
    border-radius: 9px;
}

/* Event/run name stack - the flexible half of the left side-box, giving
   whatever width is left over to the clock (.mst-header-clock, sized to its
   own content via flex:0 0 auto) - Dan's own spec 2026-09-27, live: "break
   the event name/run name box up, with the event name etc taking up 70% of
   the box," later widened again to make room for a 70px clock (see that
   class's own comment) - a fixed 70/30 split stopped making sense once the
   clock's own footprint grew well past 30% of the box, so this now just
   takes "the rest" instead of a tuned percentage. min-width:0 is required
   for a flex child to actually shrink/ellipsis instead of overflowing its
   row - text-overflow on the individual line rules below is what does the
   actual truncating. */
/* Now the ONLY child of the event/run box (the clock moved out to the logo
   box - see .mst-header-clock's own comment) - flex:1 1 auto just means
   "fill the box," which now means the whole box's width instead of sharing
   it with the clock. */
.mst-header-right-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    overflow: hidden;
}

/* Live wall clock (HH:MM:SS, ticked client-side by mstClock in
   MainLayout.razor.js - never a Blazor re-render, so it can tick every
   second without any server round-trip) - Dan's own spec 2026-09-27, live:
   "we need a very clear electric blue clock with HH:MM:SS," then "make the
   text for the clock 70px high," then moved into the logo box ("fit it in
   the spare space next to the MSTIMING logo to fill the gap, ignore the
   height requirement") where 70px comfortably fit after all. Shrunk to
   38px shortly after, alongside the box itself: "bring the size of each
   box down 75%... keep the font and graphics as large as you can within
   those two black boxes" - 38px is close to the real ceiling the new
   52px-tall box allows (line-height:1, so the line-box is ~38px, leaving a
   little clearance top/bottom rather than touching the box edges).
   Electric blue = the same --mst-flag-startclock token Start Clock's own
   button uses, not a fresh colour invented here. Tabular numerals so the
   digits don't visibly jitter in width every second. */
.mst-header-clock {
    text-align: right;
    font-weight: 900;
    font-size: 38px;
    line-height: 1;
    letter-spacing: 0.01em;
    font-variant-numeric: tabular-nums;
    color: var(--mst-flag-startclock);
    text-shadow: 0 0 14px rgba(0, 102, 255, 0.55);
}

/* Run-name (or NO ACTIVE RUN) + flag-status pill, sharing one row - Dan's
   own request 2026-09-27, live: "move the flag indicator in the top left
   black window across and down to the right of that window... because of
   the smaller text of the run name, it will never collide there." The run
   name is short enough that it never reaches the pill pinned to the row's
   right end (space-between, 2 children) - confirmed live, same discipline
   as every other "does this actually fit" check in this file. min-width:0
   on the run-name text lets IT ellipsis first in the rare case it doesn't. */
.mst-header-run-and-flag-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

/* Flag status in words - Dan's own request 2026-09-27, live: "the only
   addition is the addition of flag status in words." Background/text
   colours set inline per-render (MainLayout's own StatusDescription,
   driven by RaceControlPalette.DescribeStatus) since they change with
   whatever the run's current flag actually is - this rule is just the
   box shape, not any specific colour. No longer its own stacked line
   (align-self/margin-bottom dropped) - it now just sits at the end of
   .mst-header-run-and-flag-row, see that class's own comment. */
.mst-header-status-pill {
    flex: 0 0 auto;
    font-weight: 800;
    font-size: 0.62rem;
    letter-spacing: 0.03em;
    padding: 1px 8px;
    border-radius: 4px;
    line-height: 1.3;
    white-space: nowrap;
}

/* Event name - grown from 1.05rem to 1.8rem 2026-09-27, live ("swap the
   current event info and the mstiming logo so we can make the Event name
   and the run name text larger"), then back down to 1.3rem shortly after
   once the box itself shrank to 52px tall ("bring the size of each box
   down 75%... keep the font and graphics as large as you can within those
   two black boxes") - 1.3rem is close to the real ceiling for TWO stacked
   lines (this one plus the run-name row) to both fit inside 52px without
   clipping. */
.mst-event-run-line-big {
    text-align: left;
    font-weight: 800;
    font-size: 1.3rem;
    line-height: 1.15;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mst-event-run-line-run-big {
    font-weight: 500;
    opacity: 0.85;
    font-size: 1rem;
    line-height: 1.15;
    min-width: 0; /* lets it actually shrink/ellipsis inside .mst-header-run-and-flag-row instead of pushing the pill out */
}

/* No genuinely Active/SmartStartArmed run anywhere - same red "NO ACTIVE
   RUN" this box has always shown, matched to the run-name line above. */
.mst-event-run-line-noactive-big {
    font-weight: 800;
    color: #F87171;
    font-size: 1rem;
    line-height: 1.15;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Program.razor's run-list action icons - Dan's own request 2026-09-27:
   "the action buttons look terrible... make those action cells equally
   fixed width and height so the look is uniform" - one real MudTd column
   per action (Open/Active/Activate-Deactivate/Edit/Duplicate/Delete), not
   a packed flex cell (his own follow-up: "you did not create them in a
   cell.. they look all confusing"). mst-action-col matches width on the
   MudTh side so header and body columns line up. Icon source PNGs are
   pre-cropped to their own opaque bounding box (see MST-SOURCES's own
   icon-processing notes) rather than trimmed with CSS, so this box can
   show them as large as the slot allows - Dan's own follow-up: "is that
   as big as the icons can be?? can we crop them so they are as big as
   the actual picture is." */
.mst-action-col {
    width: 52px;
    text-align: center;
}
.mst-action-icon-slot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 6px;
    cursor: pointer;
    flex: 0 0 auto;
}
.mst-action-icon-slot:hover {
    background: rgba(255, 255, 255, 0.08);
}
.mst-action-icon-slot img {
    width: 32px;
    height: 32px;
    object-fit: contain;
}
.mst-action-icon-slot.mst-action-disabled {
    cursor: default;
    pointer-events: none;
    opacity: 0.25;
}

/* Passings' own Info/Edit row-action icons - Dan's own request 2026-09-21,
   replacing per-cell double-click/right-click/long-press (see Passings.razor
   HeaderContent's own comment on why). Much smaller than .mst-action-icon-
   slot above (44px) - that size is for Program/Events' own normal-height
   rows, this table's rows are ~10px tall (see MaxRows' own comment on the
   measured real row height), so the icon has to fit inside that, not the
   other way round. */
.mst-passings-row-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    cursor: pointer;
}
.mst-passings-row-icon img {
    width: 12px;
    height: 12px;
    object-fit: contain;
    opacity: 0.65;
}
.mst-passings-row-icon:hover img {
    opacity: 1;
}

/* The ACTIVE/INACTIVE status column - same fixed-box idea as the icon
   slots above, sized for text instead. Informational only - see
   Program.razor's own markup comment (clicking it does nothing, by
   design). */
.mst-action-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 28px;
    border-radius: 6px;
    font-weight: 800;
    font-size: 0.68rem;
    letter-spacing: 0.04em;
}
.mst-run-status-active {
    background: #16A34A;
    color: #fff;
}
.mst-run-status-inactive {
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.35);
}

/* Events.razor's own icon-cell system, added 2026-09-27 (Dan's own request:
   "remake the Events page with the same icons... including with the status
   bar and flip icon") - the ARCHIVED tag sits under the SELECTED/NOT
   SELECTED pill above (.mst-action-pill, reused as-is) only when true, and
   the Archive/Restore "flip" icon gets a faint amber ring once a row is
   already archived, so restoring it reads as a distinct action from the
   default archive one even though both share the same icon/column. */
.mst-event-status-archived {
    margin-top: 4px;
    background: rgba(217, 119, 6, 0.18);
    color: #F59E0B;
}

/* "NOT SELECTED"/"ARCHIVED" run noticeably longer than ACTIVE/INACTIVE ever
   does - the shared .mst-action-pill's fixed 72px width (sized for the
   shorter pair) wrapped/clipped it. Auto-width + nowrap instead, kept as
   its own modifier rather than widening the shared class app-wide (that
   would just make Program's own ACTIVE/INACTIVE pills unnecessarily wide). */
.mst-action-pill-wide {
    width: auto;
    white-space: nowrap;
    padding: 0 10px;
}
.mst-action-icon-slot-restore {
    box-shadow: inset 0 0 0 1.5px rgba(245, 158, 11, 0.55);
}

/* Mirrors MudDrawer's own Mini variant sizing (a narrow icon-only rail by
   default, a wider labelled one when toggled) - see mstLayout.toggleDrawer
   (MainLayout.razor.js), which just flips this class. */
.mst-drawer {
    flex: 0 0 auto;
    width: 260px;
    background: var(--mst-surface);
    border-right: 1px solid var(--mst-muted);
    overflow-y: auto;
    overflow-x: hidden;
    transition: width 0.2s ease;
}

.mst-drawer.mst-drawer-mini {
    width: 56px;
}

.mst-drawer.mst-drawer-mini .mud-nav-link-text {
    display: none;
}

.mst-main {
    background: var(--mst-bg);
    flex: 1 1 auto;
    overflow: auto;
    min-width: 0;
}

.mst-run-actions .mud-button-root {
    font-weight: 700;
}

/* Global popup (MudDialog) sizing/text fix - Dan's own report 2026-09-23:
   "the popup window as usual is nowhere near big enough... we should reduce
   the size of text globally in the popup windows.. they are way too big...
   you need to make the popup screen sizes bigger." Confirmed via
   MudBlazor's own bundled CSS: every dialog defaults to MaxWidth.Small
   (max-width:600px, .mud-dialog-width-sm) with stock Material typography
   (body1 16px, h6 20px, inputs 14px) - much bigger than the rest of MST's
   own compact/dense look (.mst-tabular's own base row size is 11px) and,
   for anything with real content (like the Show queue editor's per-item
   rows), narrower than the content itself wants to be. Scoped to .mud-dialog
   only - every OTHER typography instance in the app (tables, headers,
   pages) is untouched, exactly "in the popup windows."
   Sizing: overriding .mud-dialog directly beats MudBlazor's own
   .mud-dialog-width-sm/-md/-lg/-xl classes (same specificity, same element,
   !important forces it regardless of load order). Text: MudBlazor's
   typography sizes are CSS custom properties (--mud-typography-*-size) that
   genuinely cascade - redefining them on .mud-dialog affects every
   MudText/MudButton/MudTextField etc. inside without touching the global
   :root values every other page relies on. .mud-input-root's own font-size
   is hard-coded (not a variable) so it needs its own explicit override. */
.mud-dialog-container .mud-dialog {
    width: min(92vw, 1300px) !important;
    max-width: min(92vw, 1300px) !important;
}

.mud-dialog .mud-dialog-content {
    max-height: 84vh;
}

/* Dan's own live report 2026-09-26, GCT -> Edit Competitor: "reduce the cell
   padding, as the whole profile does not fit on the popup... a lot of these
   popups, the buttons are squashed... if these are click buttons, they
   should look like a click button". max-height above raised from 75vh to
   84vh (less scrolling needed at all); this rule guarantees every button in
   a dialog - regardless of its own Size - reads as a real clickable button
   rather than a thin sliver, without having to touch every button's markup
   one by one. */
.mud-dialog .mud-button-root {
    min-height: 34px;
}

.mud-dialog {
    --mud-typography-h4-size: 1.5rem;
    --mud-typography-h5-size: 1.15rem;
    --mud-typography-h6-size: 1.1rem;
    --mud-typography-subtitle1-size: 0.85rem;
    --mud-typography-subtitle2-size: 0.8rem;
    --mud-typography-body1-size: 0.85rem;
    --mud-typography-body2-size: 0.8rem;
    --mud-typography-button-size: 0.78rem;
    --mud-typography-caption-size: 0.68rem;
    --mud-typography-overline-size: 0.68rem;
    --mud-typography-default-size: 0.8rem;
}

.mud-dialog .mud-input-root,
.mud-dialog .mud-input-label,
.mud-dialog .mud-chip-content,
.mud-dialog .mud-alert-message {
    font-size: 0.8rem !important;
}

/* Displays/Competitor Settings hub pages - Dan's own request 2026-09-24,
   live, reorganising the sidebar: convert those two inline-expanding nav
   trees into their own dedicated pages, each just a big grid of buttons to
   whatever that tree used to list. Shared between DisplaysHub.razor and
   CompetitorSettingsHub.razor rather than duplicated per-page CSS, since
   both want the exact same "grid of big tappable tiles" look. */
.mst-hub-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px;
}

.mst-hub-tile {
    justify-content: flex-start !important;
    height: 56px;
}

/* Glass-look hub tiles - Dan's own request 2026-09-27: "embellish the
   whole rowset in a really modern glass look... just like what you have
   done with the RD popup for 'Pit Lane'... let's use it a bit more."
   Exact same colours/treatment as RaceDirectorDisplay's own Pit Lane box
   (dark glass background, cyan glow border) - see that markup's own
   comment for the original this was copied from. Menu rework across
   Displays/Tools/Settings/Competitor Settings, 2026-09-27. */
.mst-glass-section-header {
    /* Translucent, exactly like Pit Lane's own header band - Dan's own
       correction 2026-09-27, after an earlier "opaque" pass made this
       solid instead: "i want you to copy the Pit Lane popup EXACTLY...
       it is transparent, and you can see the background... this is what
       i want for all the menu rows." The see-through IS the look.
       --mst-glass-opacity is set once, in MainLayout, from the active
       WhitelabelScheme's own OperationalPanelTranslucencyPercent - the
       SAME variable .mst-glass-tile reads below, scaled here by the ratio
       between this header tint's own original alpha (0.16) and the
       tile's (0.88) so the two stay in proportion as the one slider moves. */
    background: rgba(34, 211, 238, calc(var(--mst-glass-opacity, 0.6) * 0.1818));
    color: #22D3EE;
    font-weight: 800;
    font-size: 1.6rem;
    letter-spacing: 0.06em;
    padding: 10px 16px;
    border-radius: 8px;
    border: 1px solid rgba(34, 211, 238, 0.35);
    /* Dan's own follow-up 2026-09-27: "vertically separate these rows a
       bit more? keep their title bar close, but expand the sets" - all
       the extra space goes ABOVE each header (separating it from the
       PREVIOUS section's tiles), none of it between a header and its own
       row right below. The first header on a page just sits a bit lower
       than before - fine, there's nothing above it to separate from. */
    margin-top: 40px;
}

.mst-glass-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 14px;
}

.mst-glass-tile {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    /* --mst-glass-opacity - Dan's own request 2026-09-27: "the translucent
       needs to let more through. Let's make that an adjustable item from
       0-100% translucency in the whitelabelling." Set once, in
       MainLayout, from the active WhitelabelScheme's own
       OperationalPanelTranslucencyPercent (0=opaque, 100=fully
       see-through) - fallback 0.6 matches that field's own default. */
    background: rgba(5, 7, 13, var(--mst-glass-opacity, 0.6));
    border: 2px solid #22D3EE;
    box-shadow: 0 0 16px rgba(34, 211, 238, 0.35), 0 8px 28px rgba(0, 0, 0, 0.5);
    border-radius: 10px;
    padding: 14px 36px 14px 16px;
    cursor: pointer;
    color: #fff;
    text-decoration: none;
    transition: transform 0.1s ease, box-shadow 0.15s ease;
    min-height: 56px;
    box-sizing: border-box;
}

.mst-glass-tile:hover {
    box-shadow: 0 0 22px rgba(34, 211, 238, 0.5), 0 8px 28px rgba(0, 0, 0, 0.6);
    /* No transform/translateY here on purpose - Dan's own bug report
       2026-09-27: "the tooltip icons... when you hover, it moves up, un
       hovering it again." Hovering the info icon (a child of this tile)
       also counts as hovering the tile itself in CSS - a lift-on-hover
       transform here shifted the icon out from under the cursor, which
       un-hovered it, which un-lifted the tile, which moved the icon back
       under the cursor, which re-hovered it - a genuine flicker loop, not
       just a cosmetic nitpick. */
}

.mst-glass-tile.mst-glass-disabled {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

.mst-glass-tile-title {
    font-weight: 800;
    font-size: 1.1rem;
    color: #fff;
}

/* Bottom-right info icon on every glass tile - Dan's own request: "a
   tooltip hover over each of these buttons (maybe a little information
   icon in the bottom right corner of them??) with a description." */
.mst-glass-tile-info {
    position: absolute;
    right: 8px;
    bottom: 6px;
    opacity: 0.6;
    font-size: 1.35rem !important; /* Dan's own follow-up: "the tooltip icons... is small" */
}
.mst-glass-tile-info:hover {
    opacity: 1;
}

/* Two-column "title left, description right" row layout - Dan's own spec
   2026-09-27 specifically for the Competitor Settings hub: 400px-wide
   rows, title on the left, smaller plain-white description on the right,
   no hover effect on the description text itself (the row as a whole is
   still the clickable tile). */
.mst-glass-row {
    justify-content: space-between !important;
    width: 720px; /* Dan's own follow-up 2026-09-27: "these columns can be 80% wider" (400px base) */
    max-width: 100%;
}

.mst-glass-row-desc {
    font-size: 0.78rem;
    color: #fff;
    opacity: 0.85;
    text-align: right;
    font-weight: 400;
}

/* Touchscreen Mode - a real, finger-grabbable scrollbar for a horizontally
   scrolling strip. Dan's own live spec 2026-09-28, correcting an earlier
   pass that mistakenly made the CONTENT bigger instead: "didn't want the
   information display bigger.. duh.. want the slider bar to be 60px high
   so i can slide using my finger." WebKit-only (::-webkit-scrollbar has no
   Firefox equivalent that supports an exact pixel size - Firefox falls
   back to its own normal thin scrollbar here, a harmless degradation on a
   kiosk that's virtually always Chrome/Edge anyway). The element this
   class is applied to also needs EXTRA height itself to fit a 60px
   scrollbar underneath its own content without clipping - see
   RaceControlDisplay.razor's own race-messages strip for the first real
   use (94px total = its normal ~34px content row + this 60px bar). */
.mst-touch-scrollbar::-webkit-scrollbar {
    height: 60px;
}
.mst-touch-scrollbar::-webkit-scrollbar-track {
    background: var(--disp-surface-2, #121A2E);
    border-radius: 8px;
}
.mst-touch-scrollbar::-webkit-scrollbar-thumb {
    background: var(--disp-accent, #3B82F6);
    border-radius: 8px;
    border: 4px solid var(--disp-surface-2, #121A2E);
}
.mst-touch-scrollbar::-webkit-scrollbar-thumb:active {
    background: var(--disp-accent-bright, #60A5FA);
}

/* Passings page was ~6% taller than the screen and scrolled the whole page -
   Dan 2026-09-28: "reduce height by 6% or so". Overrides the scroller's inline
   calc(100vh - 213px); !important is what lets a stylesheet rule beat an
   inline style. */
/* Superseded 2026-09-29 by a measured fit (Passings.razor.js attachMinimap -> fit). */

/* Car picker (CarNumberPicker.razor) - Dan 2026-09-29: every car choice is a
   row of race-number chips, up to 30 per line, black on orange (the same look
   as .mst-race-number), one selected at a time with a bright yellow ring. */
.mst-car-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(38px, 1fr));
    gap: 6px;
    max-width: calc(30 * 38px + 29 * 6px);
    padding: 4px 3px;
}
.mst-car-chip {
    height: 28px;
    border: none;
    border-radius: 6px;
    background: #F97316;
    color: #000;
    font-weight: 800;
    font-size: 0.875rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    font-variant-numeric: tabular-nums;
}
.mst-car-chip:hover:not(:disabled) { filter: brightness(1.12); }
.mst-car-chip:disabled { opacity: 0.45; cursor: default; }
.mst-car-chip-selected { box-shadow: 0 0 0 3px #FFE600, 0 0 10px 2px rgba(255, 230, 0, 0.55); }
.mst-car-chip-clear { grid-column: span 2; background: #475569; color: #fff; font-size: 0.7rem; letter-spacing: 0.05em; }

/* Loop picker (LoopPicker.razor) - Dan 2026-09-29: loops as white-on-blue
   buttons, one selected (bright yellow ring, same as the car chips). */
.mst-loop-picker { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 3px; }
.mst-loop-chip {
    display: inline-flex; align-items: center; gap: 6px;
    height: 30px; padding: 0 10px; border: none; border-radius: 6px;
    background: #1D4ED8; color: #fff; font-weight: 700; font-size: 0.8rem;
    cursor: pointer; white-space: nowrap;
}
.mst-loop-chip:hover:not(:disabled) { filter: brightness(1.15); }
.mst-loop-chip:disabled { opacity: 0.45; cursor: default; }
.mst-loop-chip-nr { font-weight: 900; font-variant-numeric: tabular-nums; }
.mst-loop-chip-name { font-weight: 600; opacity: 0.9; }

/* Mandatory field still empty (see MainLayout.razor.js "Mandatory fields") -
   red underline so it jumps out; normal again once filled. Dan 2026-09-29. */
.mud-input-control.mud-input-required.mst-required-empty .mud-input-underline:before {
    border-bottom: 2px solid #EF4444 !important;
}
.mud-input-control.mud-input-required.mst-required-empty .mud-input-outlined-border {
    border-color: #EF4444 !important;
}


/* RC race-message strip - Dan 2026-09-29: each event in its own glass box, WHAT on
   top, WHEN underneath, 1px glass-blue border. */
.mst-rc-strip {
    flex-shrink: 0; display: flex; align-items: center; gap: 10px;
    overflow-x: auto; overflow-y: hidden; white-space: nowrap;
    background: var(--disp-surface); border: 1px solid var(--disp-border); border-radius: 6px;
    padding: 6px 12px; min-height: 62px; box-sizing: border-box;
    box-shadow: 0 0 0 1px rgba(59,130,246,0.05), 0 4px 20px rgba(0,0,0,0.35);
}
.mst-rc-strip-touch { scrollbar-width: none; } /* the big slider below replaces it */
.mst-rc-strip-touch::-webkit-scrollbar { display: none; }
.mst-rc-event {
    flex-shrink: 0; display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px;
    padding: 4px 12px; border-radius: 8px;
    border: 1px solid rgba(96, 165, 250, 0.55);
    background: linear-gradient(180deg, rgba(255,255,255,0.09) 0%, rgba(255,255,255,0.02) 55%, rgba(59,130,246,0.06) 100%);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.12), 0 0 10px rgba(59,130,246,0.18);
    backdrop-filter: blur(6px);
}
.mst-rc-event-what { font-size: 0.85rem; line-height: 1.15; }
.mst-rc-event-when { font-size: 0.75rem; line-height: 1.1; color: var(--disp-text-dim); }

/* Touchscreen finger slider (MainLayout.razor.js touch slider) - 50px tall, big thumb. */
.mst-touch-slider {
    -webkit-appearance: none; appearance: none; width: 100%; height: 52px; min-height: 52px; margin: 4px 0 0;
    background: var(--disp-surface-2, #121A2E); border-radius: 10px; flex-shrink: 0; cursor: pointer;
}
.mst-touch-slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none; width: 140px; height: 52px; border-radius: 10px;
    background: var(--disp-accent, #3B82F6); border: 3px solid var(--disp-surface-2, #121A2E);
}
.mst-touch-slider::-moz-range-thumb {
    width: 140px; height: 44px; border-radius: 10px; background: var(--disp-accent, #3B82F6); border: 3px solid var(--disp-surface-2, #121A2E);
}
.mst-touch-slider:disabled { opacity: 0.35; }

/* CHEQUERED NOW armed (ChequeredNowButton) - pulses until clicked or 30 s pass. */
.mst-chequered-now-armed { animation: mst-chequered-now-pulse 0.8s ease-in-out infinite alternate; }
@keyframes mst-chequered-now-pulse { from { box-shadow: 0 0 0 0 rgba(253,224,71,0.9); } to { box-shadow: 0 0 0 6px rgba(253,224,71,0.0); } }


/* BC / L1/L2 on-screen map editor (BroadcastLiveScene) - cog only visible while the
   pointer is over the map. Dan 2026-09-29. */
.mst-map-cog {
    position: absolute; top: 8px; right: 8px; z-index: 5; opacity: 0; transition: opacity 0.2s;
    background: rgba(0,0,0,0.5); border: none; border-radius: 8px; color: var(--disp-text-dim);
    font-size: 1.1rem; cursor: pointer; padding: 6px 9px; line-height: 1;
}
.mst-map-editable:hover .mst-map-cog { opacity: 1; }
.mst-map-editor {
    position: absolute; top: 46px; right: 8px; z-index: 6; display: flex; flex-direction: column; gap: 8px; align-items: center;
    background: rgba(5,7,13,0.94); border: 1px solid var(--disp-border); border-radius: 10px; padding: 10px 12px;
    box-shadow: 0 8px 28px rgba(0,0,0,0.5); font-size: 0.75rem; color: var(--disp-text-dim);
}
.mst-map-editor-row { display: flex; align-items: center; gap: 6px; }
.mst-map-editor-row > span { width: 3.6em; }
.mst-map-editor-row > b { min-width: 3.2em; text-align: center; font-weight: 600; }
.mst-map-editor button {
    width: 2em; height: 2em; border: 1px solid var(--disp-border); border-radius: 6px;
    background: var(--disp-surface-2, #121A2E); color: var(--disp-text, #E2E8F0); cursor: pointer; font-size: 0.9rem;
}
.mst-map-editor-pad { display: grid; grid-template-columns: repeat(3, 2em); grid-template-rows: repeat(3, 2em); gap: 4px; }

/* Cluster (2026-09-29): race buttons on a server NOT IN CONTROL - visible but not pressable. */
.mst-race-locked .mst-race-btn { pointer-events: none !important; opacity: 0.35; filter: grayscale(0.6); }

/* ---- Stewards (desktop /stewards page + its dialogs) - Dan 2026-09-29: HD monitor, people "not very good with
   computers, so we need to make it simple": big text, big buttons, plain colours. ---- */
/* Dan 2026-09-29 second pass: "way too big and wasting space" - buttons at 75%, less padding everywhere. */
.stw-btn { font-family: inherit; font-weight: 900; letter-spacing: 0.05em; font-size: 0.8rem; padding: 8px 15px; border-radius: 8px;
    border: 2px solid #475569; background: #1E293B; color: #F1F5F9; cursor: pointer; min-height: 38px; }
.stw-btn:hover:not(:disabled) { filter: brightness(1.15); }
.stw-btn:disabled { opacity: 0.4; cursor: default; }
.stw-btn-sm { font-size: 0.7rem; padding: 4px 9px; min-height: 27px; }
.stw-btn-red { background: #DC2626; border-color: #DC2626; color: #fff; }
.stw-btn-green { background: #16A34A; border-color: #16A34A; color: #fff; }
.stw-btn-blue { background: #0066FF; border-color: #0066FF; color: #fff; }
.stw-btn-outline { background: transparent; }
.stw-btn-outline-red { background: transparent; border-color: #DC2626; color: #FCA5A5; }
.stw-btn-outline-green { background: transparent; border-color: #16A34A; color: #86EFAC; }
.stw-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 8px; }
.stw-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.stw-grid section, .stw-card { background: rgba(15, 23, 42, 0.8); border: 1px solid #334155; border-radius: 10px; padding: 6px 10px; }
.stw-grid h3, .stw-card h3 { margin: 0 0 4px; font-size: 0.8rem; letter-spacing: 0.08em; font-weight: 900; color: #93C5FD; }
.stw-row { display: flex; align-items: center; gap: 8px; padding: 3px 4px; border-bottom: 1px solid rgba(148, 163, 184, 0.15); }
.stw-empty { opacity: 0.6; padding: 6px 2px; }
.stw-chip { color: #fff; font-weight: 900; font-size: 0.7rem; letter-spacing: 0.04em; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.stw-status { font-weight: 900; padding: 1px 10px; border-radius: 6px; font-size: 0.75rem; letter-spacing: 0.05em; }
.stw-status-ok { background: #1E293B; color: #CBD5E1; }
.stw-status-dsq { background: #DC2626; color: #fff; }
.stw-status-ret { background: #B45309; color: #fff; }
.stw-status-nc { background: #6B21A8; color: #fff; }
.stw-laps { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 4px 12px; }
.stw-lap { display: flex; justify-content: space-between; padding: 3px 6px; border-radius: 6px; }
.stw-lap-best { background: rgba(168, 85, 247, 0.3); }

/* /stewards carries its own header, so the app bar is gone there - reclaim its height for the content and the nav drawer. */
.mst-no-appbar { --mud-appbar-height: 0px; }
.mst-no-appbar .mud-main-content { padding-top: 0 !important; }
.mst-no-appbar .mud-drawer { top: 0 !important; height: 100% !important; }

/* SettingFrame - Dan 2026-10-01: purple = inherited from another setting, green = important question answered,
   red = important question blank/conflicting, yellow = mismatch to check. Settings still save either way. */
.mst-setting { border: 2px solid transparent; border-radius: 6px; padding: 4px 8px 6px; }
.mst-setting-inherited { border-color: #8B5CF6; background: rgba(139, 92, 246, 0.07); }
.mst-setting-answered { border-color: #16A34A; background: rgba(22, 163, 74, 0.07); }
.mst-setting-missing { border-color: #DC2626; background: rgba(220, 38, 38, 0.08); }
.mst-setting-warning { border-color: #EAB308; background: rgba(234, 179, 8, 0.10); }
.mst-setting-note { font-size: 0.75rem; font-weight: 700; margin-top: 2px; }
.mst-setting-inherited .mst-setting-note { color: #7C3AED; }
.mst-setting-answered .mst-setting-note { color: #15803D; }
.mst-setting-missing .mst-setting-note { color: #DC2626; }
.mst-setting-warning .mst-setting-note { color: #A16207; }

/* Alternate-row shading - Dan 2026-10-01: "a subtle light blue background on alternating rows so we can separate the
   information rows". Add class mst-zebra to a MudTable to use it. Rows with their own highlight colour keep it. */
.mst-zebra tbody tr:nth-child(even) { background-color: rgba(96, 165, 250, 0.14); }
.mst-zebra tbody tr:nth-child(even):hover { background-color: rgba(96, 165, 250, 0.22); }
/* The same shading on the leaderboard displays (RC, L1/L2, Broadcast) - class set per row by position. */
.mst-row-alt { background-color: rgba(96, 165, 250, 0.16); }

/* File-drawer tabs (Modify Run) - every tab on show in one row, folder-tab shape, the open one joined to the page below. */
.mst-file-tabs .mud-tabs-tabbar { background: transparent; border-bottom: 2px solid var(--mst-accent, #3B82F6); }
.mst-file-tabs .mud-tabs-scroll-button { display: none; }
.mst-file-tabs .mud-tabs-tabbar-wrapper { transform: none !important; }
.mst-file-tabs .mud-tab {
    padding: 6px 12px; margin-right: 3px; font-size: 0.8rem; letter-spacing: 0.02em;
    border: 1px solid rgba(148,163,184,0.45); border-bottom: none; border-radius: 8px 8px 0 0;
    background: rgba(148,163,184,0.12);
}
.mst-file-tabs .mud-tab.mud-tab-active {
    background: var(--mst-accent, #3B82F6); color: #fff !important; border-color: var(--mst-accent, #3B82F6);
}
.mst-file-tabs .mud-tab-slider { display: none; }

/* Run Control header + compact table (Dan 2026-10-01: less wasted header space, ~28 cars visible, then scroll). */
.mst-rc-actions { display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap; }
.mst-rc-actions-left { display: flex; flex-direction: column; gap: 6px; }
.mst-race-btn-placeholder {
    width: 96px; height: 36px; border: 1px dashed rgba(148,163,184,0.35); border-radius: 6px;
}
.mst-rc-compact .mud-table-cell { padding-top: 0 !important; padding-bottom: 0 !important; font-size: 0.8rem; line-height: 1.2; }
.mst-rc-compact .mud-table-head .mud-table-cell { padding-top: 3px !important; padding-bottom: 3px !important; }
.mst-rc-compact .mst-stint-driver-row { font-size: 0.68rem; line-height: 1.0; }
.mst-rc-compact .mst-stint-driver-row > * { padding-top: 0; padding-bottom: 0; }
.mst-rc-compact .mst-stint-driver-row + .mst-stint-driver-row { margin-top: 0; }
.mst-rc-compact .mst-stint-pair { border-radius: 2px; }
.mst-rc-compact .mud-table-cell { font-size: 0.76rem; }
.mst-rc-compact .mud-table-body .mud-table-cell .mud-button-root,
.mst-rc-compact .mud-table-body .mud-icon-button { padding: 0 !important; }
.mst-rc-compact .mud-table-body .mud-checkbox { margin: 0; }
.mst-rc-compact .mud-table-body .mud-checkbox .mud-icon-button { padding: 0 !important; }

/* "?" Help button left of the nav collapse strip (Dan 2026-10-01). */
.mst-nav-help {
    display: flex; align-items: center; justify-content: center; min-width: 22px; padding: 0 6px;
    font-weight: 900; font-size: 0.8rem; color: #fff; background: #2563EB; text-decoration: none; border-radius: 0 0 4px 0;
}
.mst-nav-help:hover { background: #1D4ED8; }

/* Flag / event bands in the Passings grid (Dan 2026-10-01): the flag's colour across the whole row (chequer pattern for the
   chequered flag), on the same column grid as the crossing rows; name under Team / Driver, times under Time / Race Time. */
.mst-grid-row.mst-grid-band {
    /* NOT !important - the grid hides rows with an inline display:none, which must win (2026-10-01 bug). */
    display: grid; gap: 0; padding-left: 6px;
    grid-template-columns: 56px 48px minmax(150px, 1.4fr) 24px 24px 24px 110px 44px 50px 88px 96px 84px 92px 76px 58px 62px minmax(120px, 1fr) 40px 42px 50px 44px 64px;
    column-gap: 6px; align-items: center;
}
.mst-grid-row.mst-grid-band.mst-grid-chequered { background: repeating-conic-gradient(#0B1220 0% 25%, #F8FAFC 0% 50%) 0 0 / 12px 12px !important; }
.mst-band-box { background: rgba(11,18,32,0.92); color: #fff; font-weight: 900; padding: 0 7px; border-radius: 3px; line-height: 19px; white-space: nowrap; text-align: center; overflow: hidden; text-overflow: ellipsis; }
.mst-band-name { grid-column: 3 / 11; justify-self: start; max-width: 100%; letter-spacing: 0.06em; }
.mst-band-time { grid-column: 11; }
.mst-band-race { grid-column: 12; }

/* Passings: a finger-sized scrollbar - Dan 2026-10-01: "the skinny slider... expand in size by 220%" (the thin ~11px bar
   -> 24px), while the flag minimap beside it went to 30% of its width (48px -> 14px). The standard scrollbar-width /
   scrollbar-color must be reset to auto or Chrome ignores the ::-webkit-scrollbar rules. */
#passings-scroll { scrollbar-width: auto; scrollbar-color: auto; }
#passings-scroll::-webkit-scrollbar { width: 24px; }
#passings-scroll::-webkit-scrollbar-track { background: var(--mst-surface, #1a2030); border-radius: 6px; }
#passings-scroll::-webkit-scrollbar-thumb { background: #8a93a6; border-radius: 6px; border: 4px solid var(--mst-surface, #1a2030); min-height: 40px; }
#passings-scroll::-webkit-scrollbar-thumb:hover, #passings-scroll::-webkit-scrollbar-thumb:active { background: #c4c9d4; }

/* MS Timing branded reconnect screen - officials' apps (html.mst-branded, set by OfficialsAppLayout) - Dan 2026-10-02. */
.mst-brand-reconnect { display: none; }
html.mst-branded #components-reconnect-modal { position: fixed !important; inset: 0 !important; outline: none !important; width: 100vw !important; height: 100dvh !important; max-width: none !important; max-height: none !important;
    margin: 0 !important; padding: 0 !important; border: none !important; border-radius: 0 !important; background: radial-gradient(circle at 50% 40%, #13213F 0%, #0B1220 55%, #05070D 100%) !important;
    color: #E2E8F0; box-shadow: none !important; }
html.mst-branded #components-reconnect-modal::backdrop { background: #05070D; }
html.mst-branded #components-reconnect-modal .components-reconnect-container { display: block !important; height: 100%; padding: 0 !important; }
html.mst-branded #components-reconnect-modal .components-reconnect-container > :not(.mst-brand-reconnect) { display: none !important; }
html.mst-branded #components-reconnect-modal .mst-brand-reconnect { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; height: 100%; }
.mst-brand-reconnect img { width: 150px; height: auto; filter: drop-shadow(0 8px 30px rgba(0, 140, 255, 0.35)); }
.mst-brand-wheel { width: 30px; height: 30px; border-radius: 50%; background: conic-gradient(from 0deg, rgba(0, 102, 255, 0), #0066FF 60%, #38BDF8);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px)); animation: mst-brand-spin 0.85s linear infinite; }
.mst-brand-text { font-family: 'Inter', 'Segoe UI', sans-serif; font-weight: 800; letter-spacing: 0.2em; font-size: 0.85rem; color: #94A3B8; text-transform: uppercase; }
@keyframes mst-brand-spin { to { transform: rotate(360deg); } }

/* FOLDER TABS - Dan 2026-10-02: "it would be much nicer if the items were joined together like an old style filing
   cabinet. It's not obvious that these are tabbed page entry points." Put Class="mst-folder-tabs" on a MudTabs:
   each tab is a raised folder tab (rounded top, its own border), they sit shoulder to shoulder, and the chosen one is
   the panel's own colour and joins straight onto it - the panel below is its folder. */
.mst-folder-tabs { --folder-bg: #263449; --folder-off: #182235; --folder-edge: #3E5170; --folder-accent: #2DD4BF; }
.mst-folder-tabs .mud-tabs-tabbar { background: transparent !important; border-bottom: 1px solid var(--folder-edge); overflow: visible; }
.mst-folder-tabs .mud-tabs-tabbar .mud-tabs-tabbar-inner { min-height: 0 !important; align-items: flex-end; overflow: visible; }
.mst-folder-tabs .mud-tab-slider { display: none !important; }
.mst-folder-tabs .mud-tab {
    min-height: 34px !important; height: 34px; margin: 8px 3px -1px 0; padding: 4px 18px !important;
    background: var(--folder-off); color: #94A3B8 !important; opacity: 1 !important;
    border: 1px solid var(--folder-edge); border-bottom: none; border-radius: 10px 10px 0 0;
    font-weight: 700; letter-spacing: 0.04em; box-shadow: inset 0 -6px 8px -6px rgba(0, 0, 0, 0.5);
    transition: background 0.15s, color 0.15s, height 0.15s, margin 0.15s;
}
.mst-folder-tabs .mud-tab:hover { background: #1F2B40; color: #E2E8F0 !important; }
.mst-folder-tabs .mud-tab.mud-tab-active {
    height: 42px; margin-top: 0; background: var(--folder-bg); color: #fff !important;
    border-top: 3px solid var(--folder-accent); box-shadow: 0 -3px 10px rgba(0, 0, 0, 0.35); position: relative; z-index: 1;
}
/* covers the bar's bottom line under the chosen tab, so tab and panel are one piece */
.mst-folder-tabs .mud-tab.mud-tab-active::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 3px; background: var(--folder-bg); }
.mst-folder-tabs .mud-tabs-panels {
    background: var(--folder-bg); border: 1px solid var(--folder-edge); border-top: none;
    border-radius: 0 0 10px 10px; padding: 12px 14px;
}
/* Same height for every tab (Dan 2026-10-02: "pick the tallest option page, and keep that size for all... because it
   centres, the tabs move"). With KeepPanelsAlive="true" every page is rendered; they are stacked in one grid cell and
   the inactive ones are only made invisible, so the folder is always the tallest page's height and nothing jumps. */
.mst-folder-tabs .mud-tabs-panels { display: grid; }
.mst-folder-tabs .mud-tabs-panels > .mud-tab-panel { display: block !important; grid-area: 1 / 1; min-width: 0; }
.mst-folder-tabs .mud-tabs-panels > .mud-tab-panel:not(.mud-tab-panel-active) { visibility: hidden; pointer-events: none; }
