/* MeetPlatform dark theme — tuned for high-contrast meet-day displays (scoreboard, warm-up, overlay). */
:root {
    --mp-bg: #0d1117;
    --mp-surface: #161b22;
    --mp-surface-2: #1f2630;
    --mp-border: #2d333b;
    --mp-text: #e6edf3;
    --mp-muted: #9aa7b4;
    --mp-accent: #f0a500;       /* barbell gold */
    --mp-good: #2ea043;         /* good lift / white light */
    --mp-nolift: #d92d20;       /* no lift / red light */
    --mp-info: #1f6feb;

    /* ---- Dark control tokens (Setup redesign, fable-spec §6.2 / WP0 §2 rule 6) ----
       Semantic roles for form controls, layered on top of the surface tokens above with safe fallbacks so a
       future theme can override --mp-accent-2 without touching this file. Applied under .mp-setup-scope only
       (see platform.css "Setup tab professional redesign" below) so other pages/forms are not regressed. */
    --mp-control-bg: #171e28;
    --mp-control-bg-hover: #1a222d;
    --mp-control-border: #354253;
    --mp-control-border-focus: var(--mp-accent-2, #f0b94d);
    --mp-control-placeholder: #5e6978;
    --mp-nested-surface: #141b24;
}

body {
    background-color: var(--mp-bg);
    color: var(--mp-text);
    /* The app palette is dark — tell the browser so native controls (date-picker calendar icon + popup,
       scrollbars, etc.) render light-on-dark instead of an invisible black icon. */
    color-scheme: dark;
}

a { color: var(--mp-accent); }
a:hover { color: #ffc233; }

.mp-shell { min-height: 100vh; }

.mp-navbar {
    background: var(--mp-surface);
    border-bottom: 1px solid var(--mp-border);
    padding: 0.75rem 1.25rem;
    display: flex;
    align-items: center;
    gap: 1.25rem;
}
.mp-brand { font-weight: 800; letter-spacing: -0.02em; font-size: 1.15rem; color: var(--mp-text); text-decoration: none; }
.mp-brand span { color: var(--mp-accent); }
/* Strength Meet brand lock-up (BrandLockup.razor). Desktop mark height sits in the 30-32px navbar target
   (spec §7); the wordmark text hides itself under 720px so the Full variant compacts to mark-only on phones
   without a second DOM node, and the mark itself steps down into the 28-30px compact range at the same
   breakpoint. */
.mp-brand-lockup { display: inline-flex; align-items: center; gap: 0.5rem; }
.mp-brand-mark { height: 32px; width: auto; display: block; }
.mp-brand-word { white-space: nowrap; }
@media (max-width: 720px) {
    .mp-brand-full .mp-brand-word { display: none; }
    .mp-brand-lockup .mp-brand-mark { height: 28px; }
}
/* min-width:0 lets this flex item actually shrink to its widest single link (and wrap the rest) instead of the
   default flex min-width:auto forcing the whole row's natural width onto its flex-basis, which was pushing a
   couple of px past the viewport at very narrow widths (meets-ui fable-spec §10.3 phone no-overflow contract). */
.mp-nav-links { display: flex; gap: 1rem; flex-wrap: wrap; min-width: 0; }
.mp-nav-links a { color: var(--mp-muted); text-decoration: none; font-weight: 600; }
.mp-nav-links a:hover, .mp-nav-links a.active { color: var(--mp-text); }

/* Full width by default; the top-right toggle adds html.mp-narrow to constrain it. Horizontal padding scales
   with viewport (meets-ui fable-spec §6.1) so wide/4K layouts don't carry a fixed narrow gutter, while narrow
   viewports keep a sane minimum. */
.mp-container { max-width: none; margin: 0 auto; padding: 1.75rem clamp(1rem, 1.4vw, 2rem) 4rem; }
html.mp-narrow .mp-container { max-width: 1100px; }

.mp-width-toggle {
    background: var(--mp-surface-2); color: var(--mp-text); border: 1px solid var(--mp-border);
    border-radius: 6px; padding: 0.3rem 0.6rem; cursor: pointer; font-weight: 600; font-size: 0.85rem; white-space: nowrap;
}
.mp-width-toggle:hover { border-color: var(--mp-accent); }
.mp-width-toggle .when-narrow { display: none; }
html.mp-narrow .mp-width-toggle .when-wide { display: none; }
html.mp-narrow .mp-width-toggle .when-narrow { display: inline; }
/* Below small-phone widths the toggle is INERT — full-width and the 1100px-max "narrow" container render
   identically when the viewport is far under 1100px — yet its nowrap label still forced the navbar ~27px past a
   320px viewport (document-level horizontal overflow on every page). Hide the control where it does nothing. */
@media (max-width: 480px) { .mp-width-toggle { display: none; } }

/* Secondary (in-meet) navigation bar. */
.mp-meet-nav {
    display: flex; flex-wrap: wrap; gap: 1.1rem; align-items: center;
    background: var(--mp-surface); border: 1px solid var(--mp-border); border-radius: 10px;
    padding: 0.6rem 1rem; margin-bottom: 1.25rem;
}
.mp-meet-nav a { padding: 0.15rem 0; }
.mp-meet-nav a.active { color: var(--mp-accent); border-bottom: 2px solid var(--mp-accent); }

/* ---- Registration grid (ag-grid-style inline editing) ---- */
/* A full-height scroll viewport: headers stay pinned (vertical scroll), and it scrolls horizontally when wider.
   The height below is only a no-JS fallback — registration-grid.js pins the exact height (viewport minus the
   chrome above it) at runtime so the page itself never scrolls and the grid's own scrollbars stay visible. */
.mp-reg-wrap { height: calc(100vh - 13rem); min-height: 18rem; overflow: auto; border: 1px solid var(--mp-border); border-radius: 10px; background: var(--mp-surface); }
.mp-reg { border-collapse: separate; border-spacing: 0; width: max-content; min-width: 100%; font-size: 0.85rem; }
.mp-reg thead th {
    position: sticky; top: 0; z-index: 3; background: var(--mp-surface);
    border-bottom: 2px solid var(--mp-border); padding: 0.5rem 0.65rem; text-align: left;
    white-space: nowrap; font-weight: 700; color: var(--mp-muted);
}
.mp-reg tbody td { border-bottom: 1px solid var(--mp-border); padding: 0; white-space: nowrap; vertical-align: middle; }
.mp-reg tbody tr:hover td { background: color-mix(in srgb, var(--mp-accent) 7%, transparent); }
/* Editors read like plain cells until focused — a single click puts the cell into edit mode. */
.mp-reg .form-control {
    border: 1px solid transparent; background: transparent; border-radius: 0; box-shadow: none;
    width: 100%; min-width: 5rem; padding: 0.4rem 0.65rem; font: inherit; color: var(--mp-text); height: 2.2rem;
}
.mp-reg td > .form-control:hover { background: color-mix(in srgb, var(--mp-accent) 10%, transparent); }
.mp-reg td > .form-control:focus {
    border-color: var(--mp-accent); background: var(--mp-bg); outline: none;
    box-shadow: inset 0 0 0 1px var(--mp-accent); position: relative; z-index: 1;
}
/* The multiselect cells blend into the grid: borderless until opened, matching the inline editors. */
.mp-reg .mp-multiselect > summary.msd-control { border-color: transparent; background: transparent; min-height: 2.2rem; border-radius: 0; }
.mp-reg td:hover > .mp-multiselect > summary.msd-control { background: color-mix(in srgb, var(--mp-accent) 10%, transparent); }
.mp-reg .mp-multiselect[open] > summary.msd-control { background: var(--mp-bg); border-color: var(--mp-accent); }

/* Sortable + filterable column headers — single line: label (sort) on the left, filter funnel on the right. */
.mp-reg .mp-rhead { display: flex; align-items: center; gap: 0.4rem; justify-content: space-between; }
.mp-reg .mp-rsort-label { cursor: pointer; user-select: none; display: inline-flex; align-items: center; gap: 0.25rem; white-space: nowrap; }
.mp-reg .mp-rsort-label:hover { color: var(--mp-text); }
.mp-reg .mp-rsort-ind { font-size: 0.65rem; color: var(--mp-accent); }
.mp-reg .mp-rsort-ord { font-size: 0.6rem; color: var(--mp-muted); margin-left: -0.15rem; }
/* Filter funnel: a popover anchored to the header; the icon glows accent when a filter is active. */
.mp-reg .mp-rfilter-wrap { position: relative; flex: none; }
.mp-reg .mp-rfilter-wrap > summary {
    list-style: none; cursor: pointer; color: var(--mp-muted); display: inline-flex; line-height: 1; padding: 2px; border-radius: 4px;
}
.mp-reg .mp-rfilter-wrap > summary::-webkit-details-marker { display: none; }
.mp-reg .mp-rfilter-wrap > summary:hover { color: var(--mp-text); background: color-mix(in srgb, var(--mp-accent) 12%, transparent); }
.mp-reg .mp-rfilter-wrap.mp-filter-on > summary { color: var(--mp-accent); }
.mp-reg th.mp-rsort:has(.mp-rfilter-wrap[open]) { z-index: 5; }
.mp-reg .mp-rfilter-pop {
    position: absolute; right: 0; top: 100%; z-index: 6; margin-top: 3px;
    background: var(--mp-surface); border: 1px solid var(--mp-border); border-radius: 6px; padding: 6px; box-shadow: 0 6px 18px rgba(0,0,0,0.35);
}
.mp-reg .mp-rfilter {
    width: 150px; box-sizing: border-box; padding: 0.3rem 0.4rem; font-size: 0.8rem; font-weight: 400;
    border: 1px solid var(--mp-border); border-radius: 4px; background: var(--mp-bg); color: var(--mp-text);
}
.mp-reg .mp-rfilter:focus { outline: none; border-color: var(--mp-accent); }

/* Cells without a full-bleed editor provide their own padding (the tds themselves have none). */
.mp-reg td.mp-reg-center { text-align: center; padding: 0.3rem 0.5rem; }
.mp-reg td.mp-reg-center input[type=checkbox] { margin: 0 auto; display: block; }
.mp-reg td.mp-reg-pad { padding: 0.25rem 0.4rem; }
/* "Not applicable" dash in a cell that otherwise holds an inline editor (weigh-ins openers/racks). */
.mp-reg .mp-reg-na { display: block; padding: 0.45rem 0.65rem; color: var(--mp-muted); }

/* ---- Shared data-grid foundation (director-ui-spec §8.3 / WP2) ----
   Net-new, reusable primitives extracted from the proven Registration grid above: sticky header, bounded
   horizontal + vertical scroll, dense hoverable rows, and data-driven sortable/filterable headers. Driven by
   data-grid.js off column data-attributes (data-dg-numeric) and stable .mp-dg-* hooks rather than page-specific
   selectors, so any page (Entries, future grids) can consume it. Registration/WeighIns deliberately still use the
   .mp-reg-* rules above — see WP2 notes; migrating them is a separate safe step. Adds a sticky-LEFT column
   capability (Entries needs a pinned Lifter column) that the Registration original never had. */
.mp-data-grid-wrap { height: calc(100vh - 13rem); min-height: 18rem; overflow: auto; border: 1px solid var(--mp-border); border-radius: 10px; background: var(--mp-surface); }
.mp-data-grid { border-collapse: separate; border-spacing: 0; width: max-content; min-width: 100%; font-size: 0.85rem; }
.mp-data-grid thead th {
    position: sticky; top: 0; z-index: 3; background: var(--mp-surface);
    border-bottom: 2px solid var(--mp-border); padding: 0.5rem 0.65rem; text-align: left;
    white-space: nowrap; font-weight: 700; color: var(--mp-muted);
}
.mp-data-grid tbody td { border-bottom: 1px solid var(--mp-border); padding: 0.4rem 0.65rem; white-space: nowrap; vertical-align: middle; }
.mp-data-grid tbody tr:hover td { background: color-mix(in srgb, var(--mp-accent) 7%, transparent); }

/* Sticky-LEFT column (e.g. Entries lifter name). The body cell needs an OPAQUE background so horizontally
   scrolled cells don't bleed through it; the header corner (sticky top AND left) must sit above everything. */
.mp-data-grid .mp-dg-sticky-left { position: sticky; left: 0; z-index: 2; background: var(--mp-surface); }
.mp-data-grid tbody tr:hover td.mp-dg-sticky-left { background: color-mix(in srgb, var(--mp-accent) 12%, var(--mp-surface)); }
.mp-data-grid thead th.mp-dg-sticky-left { z-index: 6; }

/* Sortable + filterable header — label (sort, keyboard-activatable) on the left, filter funnel on the right. */
.mp-data-grid .mp-dg-head { display: flex; align-items: center; gap: 0.4rem; justify-content: space-between; }
.mp-data-grid .mp-dg-sort-label { cursor: pointer; user-select: none; display: inline-flex; align-items: center; gap: 0.25rem; white-space: nowrap; border-radius: 4px; }
.mp-data-grid .mp-dg-sort-label:hover { color: var(--mp-text); }
.mp-data-grid .mp-dg-sort-label:focus-visible { outline: 2px solid var(--mp-accent); outline-offset: 2px; }
.mp-data-grid .mp-dg-sort-ind { font-size: 0.65rem; color: var(--mp-accent); }
.mp-data-grid .mp-dg-sort-ord { font-size: 0.6rem; color: var(--mp-muted); margin-left: -0.15rem; }
.mp-data-grid .mp-dg-filter-wrap { position: relative; flex: none; }
.mp-data-grid .mp-dg-filter-wrap > summary {
    list-style: none; cursor: pointer; color: var(--mp-muted); display: inline-flex; line-height: 1; padding: 2px; border-radius: 4px;
}
.mp-data-grid .mp-dg-filter-wrap > summary::-webkit-details-marker { display: none; }
.mp-data-grid .mp-dg-filter-wrap > summary:hover { color: var(--mp-text); background: color-mix(in srgb, var(--mp-accent) 12%, transparent); }
.mp-data-grid .mp-dg-filter-wrap > summary:focus-visible { outline: 2px solid var(--mp-accent); outline-offset: 1px; }
.mp-data-grid .mp-dg-filter-wrap.mp-dg-filter-on > summary { color: var(--mp-accent); }
.mp-data-grid th:has(.mp-dg-filter-wrap[open]) { z-index: 7; }
.mp-data-grid .mp-dg-filter-pop {
    position: absolute; right: 0; top: 100%; z-index: 8; margin-top: 3px;
    background: var(--mp-surface); border: 1px solid var(--mp-border); border-radius: 6px; padding: 6px; box-shadow: 0 6px 18px rgba(0,0,0,0.35);
}
.mp-data-grid .mp-dg-filter {
    width: 150px; box-sizing: border-box; padding: 0.3rem 0.4rem; font-size: 0.8rem; font-weight: 400;
    border: 1px solid var(--mp-border); border-radius: 4px; background: var(--mp-bg); color: var(--mp-text);
}
.mp-data-grid .mp-dg-filter:focus { outline: none; border-color: var(--mp-accent); }
.mp-data-grid td.mp-dg-center { text-align: center; }
.mp-data-grid .mp-dg-empty { padding: 1rem; text-align: center; color: var(--mp-muted); }

/* Collapsible "Add competitor" panel. */
.mp-add-panel { border: 1px solid var(--mp-border); border-radius: 10px; background: var(--mp-surface); margin-bottom: 0.75rem; }
.mp-add-panel > summary { cursor: pointer; padding: 0.6rem 0.9rem; font-weight: 700; list-style: none; display: flex; align-items: center; gap: 0.5rem; }
.mp-add-panel > summary::-webkit-details-marker { display: none; }
.mp-add-panel > summary::before { content: "▸"; color: var(--mp-accent); transition: transform 0.15s; }
.mp-add-panel[open] > summary::before { transform: rotate(90deg); }
.mp-add-panel .mp-add-body { padding: 0 0.9rem 0.9rem; }
/* Themed inputs in the Add-competitor form, matching the Divisions/Events multiselect controls. */
.mp-add-panel .form-control {
    background: var(--mp-bg); color: var(--mp-text); border: 1px solid var(--mp-border); border-radius: 6px;
    padding: 0.4rem 0.5rem; font: inherit; box-shadow: none;
}
.mp-add-panel .form-control::placeholder { color: var(--mp-muted); }
.mp-add-panel .form-control:hover { border-color: color-mix(in srgb, var(--mp-accent) 45%, var(--mp-border)); }
.mp-add-panel .form-control:focus {
    outline: none; border-color: var(--mp-accent); background: var(--mp-bg); color: var(--mp-text);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--mp-accent) 25%, transparent);
}
.mp-add-panel label.mp-muted { display: block; margin-bottom: 0.15rem; }

/* ---- Meet-day boards ---- */
.mp-board-fullscreen { position: fixed; inset: 0; z-index: 1000; overflow: auto; padding: 1rem 1.25rem; background: var(--mp-bg); }
/* A fullscreen board only visually covers the app chrome; z-index occlusion alone leaves the navbar's links
   keyboard-Tab-reachable on a kiosk/audience screen. display:none removes them from the tab order and the
   accessibility tree. The shell observes the board structurally with :has() because MainLayout renders
   statically (SSR) and cannot see the interactive board island's Present state toggle at runtime. */
.mp-shell:has(.mp-board-fullscreen) .mp-navbar { display: none; }
/* Presentation mode: only the boards show; the Exit button stays out of the way until hovered. */
.mp-sb-present { padding: 0.5rem 0.75rem; }
.mp-sb-exit { position: fixed; top: 0.5rem; right: 0.5rem; z-index: 1100; opacity: 0.25; transition: opacity 0.15s; }
.mp-sb-exit:hover { opacity: 1; }
.mp-board-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-bottom: 0.75rem; flex-wrap: wrap; }
.mp-board-title { font-weight: 800; font-size: 1.25rem; }
.mp-board-logo { height: 32px; vertical-align: middle; margin-right: 0.5rem; }
.mp-board-platform { margin-bottom: 1.5rem; }
.mp-board-platform:last-child { margin-bottom: 0; }
.mp-board-current { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 0.85rem; background: var(--mp-surface); border: 1px solid var(--mp-border); border-left: 4px solid var(--mp-accent); border-radius: 8px; padding: 0.6rem 1rem; margin-bottom: 0.75rem; }
.mp-board-table th, .mp-board-table td { padding: 0.35rem 0.55rem; font-variant-numeric: tabular-nums; }
.mp-board-table td { border-bottom: 1px solid var(--mp-border); }
.mp-row-current { background: color-mix(in srgb, var(--mp-accent) 18%, transparent); }
/* Flight separator band: each flight in a platform board gets a labelled header row; the flight lifting now is highlighted, the others are dimmed. */
.mp-board-table .mp-sb-flightrow td { background: var(--mp-surface-2, #1b222c); color: var(--mp-muted); font-weight: 800; text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.78rem; border-top: 2px solid var(--mp-border); border-bottom: 1px solid var(--mp-border); }
.mp-board-table .mp-sb-flightrow.current td { color: var(--mp-accent); background: color-mix(in srgb, var(--mp-accent) 14%, var(--mp-surface)); }
.mp-board-table tr.mp-sb-otherflight td { opacity: 0.6; }
.mp-board-table td.mp-cell-sub { font-weight: 700; }
.mp-cell-good { color: var(--mp-good); font-weight: 800; }
.mp-cell-nolift { color: var(--mp-nolift); font-weight: 800; text-decoration: line-through; }
.mp-cell-bomb { color: var(--mp-nolift); font-weight: 800; }
.mp-cell-current { outline: 2px solid var(--mp-accent); outline-offset: -2px; }

/* ==== Scoreboard/Livestream WP5: condensed scoreboard + play links (spec §3.1/§5.1) ==== */
.mp-sb-toggle-group { display: inline-flex; border-radius: 8px; overflow: hidden; }
.mp-sb-toggle-group .mp-btn { border-radius: 0; }

/* Sticky first column (place + forecast + name) so the identity stays visible while the attempt columns scroll
   horizontally at narrow widths. Needs an OPAQUE background matching whatever the row underneath would show,
   otherwise horizontally-scrolled cells show through the sticky column. */
.mp-sb-sticky {
    position: sticky; left: 0; z-index: 2; text-align: left;
    background: var(--mp-surface); min-width: 9rem; max-width: 15rem;
}
tr.mp-row-current .mp-sb-sticky { background: color-mix(in srgb, var(--mp-accent) 18%, var(--mp-surface)); }
.mp-sb-place { font-weight: 800; }
/* Forecast transition ("9 → 8"): visually marked as a PROJECTION (arrow + accent colour), distinct from the plain
   current-place number beside it — spec §3.1 "never as the current place". */
.mp-sb-forecast { display: inline-flex; align-items: center; gap: 0.1rem; margin-left: 0.35rem; color: var(--mp-accent); font-weight: 800; font-size: 0.78rem; }
.mp-sb-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 14rem; }

/* Result glyphs: colour is never the only signal (spec §3.1/§12) — a tick/cross renders alongside the good/no-lift
   colour classes already applied to the cell. */
.mp-sb-glyph { font-size: 0.72rem; margin-left: 0.2rem; }
.mp-sb-glyph.good { color: var(--mp-good); }
.mp-sb-glyph.nolift { color: var(--mp-nolift); }

/* Play control: a real link (never a bare onclick div), touch target held at >=44x44 CSS px even though the glyph
   itself is small (spec §3.1 "must remain at least 44 x 44 CSS px as a touch target, even if its visible glyph is
   smaller"). Present in both full and condensed modes (spec §5.1); absent whenever a completed cell has no Ready
   clip (Razor renders nothing — no dead/broken link, spec §12). */
.mp-lift-video {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin-left: 0.15rem; vertical-align: middle;
    border-radius: 8px; color: var(--mp-text); text-decoration: none; font-size: 0.85rem;
    background: color-mix(in srgb, var(--mp-accent) 12%, transparent);
}
.mp-lift-video:hover, .mp-lift-video:focus-visible {
    background: color-mix(in srgb, var(--mp-accent) 28%, transparent);
    outline: 2px solid var(--mp-accent); outline-offset: 1px;
}
/* The condensed grid's glyph is smaller (compact numeric cells) but the tappable box itself never shrinks below 44px. */
.mp-sb-condensed-table .mp-lift-video { font-size: 0.68rem; }

/* Present mode: belt-and-braces (spec §5.1/§13 acceptance example 5). The Razor condition already never renders a
   play link while _present is true — this rule is the defensive second layer named in the WP brief, so a play
   control can never surface even if a future change forgets the Razor guard. */
.mp-sb-present .mp-lift-video { display: none !important; }

/* Fit at 390px with compact numeric cells (spec §3.1); a horizontal scrollbar on the TABLE'S OWN wrapper (never the
   outer page) covers narrower widths and the extra column a fourth-attempt meet adds. */
.mp-sb-condensed-wrap { overflow-x: auto; }
.mp-sb-condensed-table th, .mp-sb-condensed-table td { text-align: center; font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 480px) {
    .mp-sb-condensed-table th, .mp-sb-condensed-table td { padding: 0.3rem 0.4rem; font-size: 0.82rem; }
    .mp-sb-sticky { min-width: 7rem; max-width: 9rem; }
    .mp-sb-name { max-width: 8rem; }
}

/* ---- Inline editable run-board cells (edit happens in the cell, not a popover) ---- */
.mp-edit-cell { cursor: pointer; min-width: 2.6rem; }
.mp-edit-cell.editing { background: var(--mp-surface); outline: 2px solid var(--mp-accent); outline-offset: -2px; min-width: 150px; }
.mp-cell-val { display: block; }
/* The editor replaces the value in place: while editing, hide the displayed value and show the input overtop. The
   editor fills the (widened) cell exactly — width:100% with no min-width so it never spills past the cell's edges. */
.mp-edit-cell.editing .mp-cell-val { display: none; }
.mp-cell-edit { display: none; width: 100%; min-width: 0; box-sizing: border-box; }
.mp-edit-cell.editing .mp-cell-edit { display: block; }
.mp-cell-weight { flex: 1 1 3rem; min-width: 3rem; padding: 0.25rem 0.35rem; box-sizing: border-box;
    border: 1px solid var(--mp-border); border-radius: 6px; font-size: 0.95rem; background: var(--mp-bg); color: var(--mp-text); }
.mp-cell-actions { display: flex; gap: 0.2rem; flex: 1 1 100%; }
/* Collapsed non-active lift: click the summary to expand an editor for all 3 attempts. */
.mp-collapsed-cell .mp-cell-val { cursor: pointer; }
.mp-cell-edit-multi { min-width: 0; }
.mp-cell-edit-title { font-weight: 800; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--mp-muted); margin-bottom: 0.3rem; }
.mp-cell-edit-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin-bottom: 0.3rem; }
.mp-cell-edit-row:last-child { margin-bottom: 0; }
.mp-cell-edit-lbl { width: 1rem; flex: none; color: var(--mp-muted); font-size: 0.8rem; text-align: right; }
.mp-cell-btn { flex: 1; padding: 0.25rem 0; border: 1px solid var(--mp-border); border-radius: 6px;
    background: var(--mp-bg); color: var(--mp-text); cursor: pointer; font-size: 1rem; line-height: 1; }
.mp-cell-btn:hover { background: var(--mp-bg); filter: brightness(1.1); }
.mp-cell-btn.good { color: var(--mp-good); border-color: var(--mp-good); }
.mp-cell-btn.nolift { color: var(--mp-nolift); border-color: var(--mp-nolift); }
.mp-cell-btn.warn { color: #d97706; border-color: #d97706; }
.mp-cmd-error { outline: 2px solid var(--mp-nolift) !important; }
.mp-linkbtn { background: none; border: none; padding: 0; color: var(--mp-accent); cursor: pointer;
    font-size: inherit; text-decoration: underline; }

/* Compact "set current" affordance + flight grouping separators. */
.mp-setcur { padding: 0.05rem 0.4rem; font-size: 0.8rem; line-height: 1.2; border: 1px solid var(--mp-border);
    border-radius: 5px; background: var(--mp-bg); color: var(--mp-muted); cursor: pointer; }
.mp-setcur:hover { border-color: var(--mp-accent); color: var(--mp-accent); }
.mp-flight-sep td { background: var(--mp-surface); font-weight: 800; padding: 0.45rem 0.6rem;
    border-top: 2px solid var(--mp-border); border-bottom: 1px solid var(--mp-border); }
.mp-flight-sep.current td { color: var(--mp-accent); box-shadow: inset 4px 0 0 var(--mp-accent); }
/* Presentation mode: the board goes full-bleed and the top menu bar is hidden; a faint Exit button stays. */
.mp-btn.mp-runboard-exit { display: none; }
/* justify-content: safe center vertically centres the content, falling back to top-alignment instead of clipping
   when it overflows; the extra top padding reserves the fixed Exit button's zone so it can never overlap the
   Good Lift button even when the board is taller than the screen. */
.mp-runboard.present { position: fixed; inset: 0; z-index: 1000; overflow: auto; padding: 3.5rem 0.75rem 0.5rem; background: var(--mp-bg); display: flex; flex-direction: column; justify-content: safe center; }
.mp-runboard.present .mp-board-head { display: none; }
.mp-runboard.present .mp-runboard-exit { display: inline-flex; position: fixed; top: 0.5rem; right: 0.5rem; z-index: 1100;
    opacity: 0.25; transition: opacity 0.15s; }
.mp-runboard.present .mp-runboard-exit:hover { opacity: 1; }

/* ---- Run-board current-lifter header (bar weight + name/meta left; No lift / Good lift / ☰ right) ---- */
/* Head: current lifter (name/weight/age/equipment/division) on the left, action buttons on the right. */
.mp-run-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap;
    background: var(--mp-surface); border: 1px solid var(--mp-border); border-left: 4px solid var(--mp-accent);
    border-radius: 10px; padding: 0.6rem 0.9rem; margin: 0.5rem 0; }
/* flex-basis 0 (not auto) is load-bearing: the head wraps, and wrap decisions use an item's BASE size, so a
   basis of auto would let a long untruncated name push the buttons onto a second row before shrinking is ever
   considered. With basis 0 the left block can never force a wrap — it grows into whatever the right-hand
   controls leave, and min-width:0 lets the name inside it ellipsis instead of overflowing. */
.mp-run-head-left { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; flex: 1 1 0; }
/* Body: the loaded bar (fixed ~500px) on the left, the run-sheet grid filling the rest on the right. */
.mp-run-body { display: flex; gap: 1rem; align-items: flex-start; }
.mp-run-grid { flex: 1 1 auto; min-width: 0; }
/* Left column under the head: the loaded bar with the next-lifter strip beneath it. */
.mp-run-leftcol { flex: 0 0 500px; max-width: 500px; min-width: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.mp-run-bar { display: flex; flex-direction: column; width: 100%; background: var(--mp-surface);
    border: 1px solid var(--mp-border); border-radius: 10px; padding: 0.5rem 0.8rem; }
.mp-run-bar-top { text-align: center; font-size: 2.6rem; font-weight: 900; color: var(--mp-accent); line-height: 1.05; }
.mp-run-bar-track { display: flex; align-items: center; gap: 4px; flex-wrap: nowrap; overflow-x: auto; min-height: 310px; }
.mp-run-bar-foot { text-align: right; min-height: 1.4em; font-size: 1.4rem; font-weight: 800; color: var(--mp-text); }
/* The bar shaft (inner end), the collar, and the sleeve end poking out past the collar — all centred on the loading axis. */
.mp-run-barshaft { flex: 0 0 auto; width: 30px; height: 33px; border-radius: 3px;
    background: linear-gradient(180deg, #d3d8df, #8b929c 55%, #6b7280); border: 1px solid rgba(0,0,0,0.5); }
.mp-run-barend { width: 38px; }   /* the sleeve end pokes out past the collar on the right */
/* Collar ≈ 3/4 the height of the 1.25 kg plate (≈104px) so the thin bar end clearly shows above/below it. */
.mp-run-collar { position: relative; flex: 0 0 auto; width: 26px; height: 78px; border-radius: 5px; margin: 0 1px;
    background: linear-gradient(180deg, #d3d8df, #9aa0aa 50%, #5b616b); border: 1px solid rgba(0,0,0,0.6);
    box-shadow: inset 0 0 0 3px rgba(255,255,255,0.18), inset 0 0 6px rgba(0,0,0,0.45); }
/* The locking screw/knob on top of the collar, so it clearly reads as a collar. */
.mp-run-collar::after { content: ""; position: absolute; left: 50%; top: -13px; transform: translateX(-50%);
    width: 11px; height: 15px; border-radius: 3px 3px 2px 2px;
    background: linear-gradient(180deg, #e2e6ec, #7d848f); border: 1px solid rgba(0,0,0,0.6);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.5); }
/* Each plate: weight centred, optional count for the biggest plate printed lower down (under the weight). */
.mp-run-plate { position: relative; flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
    min-width: 40px; padding: 0 3px; border-radius: 4px; border: 1.5px solid rgba(230, 237, 243, 0.9); color: #fff;
    font-weight: 800; line-height: 1; text-shadow: 0 1px 2px rgba(0,0,0,0.75); }
.mp-run-plate-wt { font-size: 1.05rem; }
.mp-run-plate-count { position: absolute; left: 0; right: 0; bottom: 8px; text-align: center;
    font-size: 0.9rem; font-weight: 900; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.8); }
/* Name is the dominant element in the current-lifter header — larger than the bar weight (2.6rem) at a ~1.10 ratio.
   Truncates with an ellipsis instead of wrapping/overlapping the timer, attempt buttons, or status content on the
   right (mp-run-head-left already has min-width:0 so this flex child is free to shrink below its content width). */
.mp-run-name { font-size: 2.85rem; font-weight: 900; line-height: 1.1; max-width: 100%;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-run-sub { display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; }
.mp-run-kg { font-size: 1.4rem; font-weight: 900; color: var(--mp-accent); }
.mp-run-meta { font-size: 0.9rem; margin-top: 0.1rem; }
.mp-run-head-right { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.mp-btn.mp-run-good { background: var(--mp-good); color: #fff; font-size: 1.05rem; padding: 0.5rem 1.1rem; }
.mp-btn.mp-run-nolift { background: var(--mp-nolift); color: #fff; font-size: 1.05rem; padding: 0.5rem 1.1rem; }
/* Attempt countdown shown in line with the header; turns red and holds at 00 when time runs out. */
.mp-run-timer { font-variant-numeric: tabular-nums; font-weight: 800; font-size: 1.6rem; min-width: 2.4ch;
    text-align: center; color: var(--mp-accent); }
.mp-run-timer:empty { display: none; }
.mp-run-timer.expired { color: var(--mp-nolift); }
/* Next-two lifters under the bar, each a modestly larger card: identity on row 1, attempt weight on row 2, and a
   plate-loading column on the right spanning both rows. */
.mp-run-next { display: flex; flex-direction: column; gap: 0.5rem; background: var(--mp-surface);
    border: 1px solid var(--mp-border); border-radius: 10px; padding: 0.6rem 0.8rem; }
/* 2-row/2-col grid: left column (minmax(0,1fr)) holds identity (row 1) then weight (row 2); the right column is a
   reserved plate-loading lane sized for the widest realistic loadout (9×25  1×20  1×2.5  1×1.25 at 1280×720)
   without clipping, and spans both rows via the named "plates" area so the mini plate stack can be vertically
   centred across the card's full height. Empty plate data still renders inside this area (see markup), so the
   column's reserved width never collapses and the left text never jumps. */
.mp-run-next-item { display: grid; grid-template-columns: minmax(0, 1fr) minmax(10.5rem, 11rem);
    grid-template-areas: "identity plates" "weight plates"; column-gap: 0.75rem; row-gap: 0.2rem;
    align-items: center; min-height: 5.75rem; padding: 0.35rem 0.1rem; }
.mp-run-next-item + .mp-run-next-item { border-top: 1px solid var(--mp-border); }
.mp-run-next-line1 { grid-area: identity; display: flex; align-items: baseline; gap: 0.55rem; font-size: 1.25rem;
    min-width: 0; }
.mp-run-next-wt { grid-area: weight; justify-self: start; font-size: 1.7rem; font-weight: 900; color: var(--mp-accent); }
.mp-run-next-tag { font-size: 0.8rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--mp-muted); min-width: 3.2rem; }
.mp-run-next-name { font-weight: 800; color: var(--mp-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Plate-loading column: plates only — no shaft/collar/labels, just proportional, colour-matched blocks. The grid
   area already spans both rows (the card's full height); display:flex + align-items:center here vertically centres
   the plate row within that spanned height without stretching the individual plate graphics. justify-content:
   flex-start keeps the stack's left edge anchored at the start of its column (the column itself is the card's
   right-hand side) — the same right-of-card position and plate-colour semantics as before. Wraps at plate-pair
   boundaries only if a narrower supported viewport truly needs it — plate size itself never shrinks to fit. */
.mp-run-next-plates { grid-area: plates; align-self: stretch; display: flex; align-items: center;
    justify-content: flex-start; gap: 2px; flex-wrap: wrap; min-width: 0; }
.mp-run-next-plate { flex: 0 0 auto; border-radius: 2px; border: 1px solid rgba(230, 237, 243, 0.7); }
.mp-run-next-plates-empty { font-size: 1rem; }
.mp-flight-select {
    width: auto; padding: 0.45rem 0.6rem; font-size: 0.9rem; border-radius: 8px;
    background: var(--mp-bg); color: var(--mp-text); border: 1px solid var(--mp-border);
}
.mp-flight-select:hover { border-color: color-mix(in srgb, var(--mp-accent) 45%, var(--mp-border)); }
.mp-flight-select:focus { outline: none; border-color: var(--mp-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--mp-accent) 25%, transparent); }

/* ============================================================================================================
   RP WP5 §6: run-board PB/national-record attempt-indicator badges + tri-state Indicators popover.
   RunMeet.razor is static SSR (no InteractiveServer circuit), so — unlike Scoreboard.razor.css's WP4 rules, which
   filter badges SERVER-SIDE before they ever reach the DOM — every badge here always renders, and run-board.js
   toggles "hide-pb"/"hide-record" classes on the .mp-runboard root to apply the effective tri-state filter
   entirely client-side (instant, no page reload). Visual language (icon/short-text/status colour) intentionally
   mirrors Scoreboard.razor.css's .mp-sb-annot rules so the two boards read as one system.
   ============================================================================================================ */

/* §6.1 effective filtering: hides only the matching KIND — PB/record badges everywhere on the board, including the
   current-lifter prominent callout (mp-rb-pb/mp-rb-record double as both the styling AND the hide-toggle marker,
   same convention as the reference mock's .hide-pb .badge.pb rule). */
.mp-runboard.hide-pb .mp-rb-pb { display: none !important; }
.mp-runboard.hide-record .mp-rb-record { display: none !important; }
/* The multi-record secondary line ("N eligible records · …") is record-only supplementary text, not a badge —
   still respects the Records toggle so it never contradicts a hidden record badge. */
.mp-runboard.hide-record .mp-rb-record-fact { display: none !important; }

/* §6.3 compact per-cell/card badges — rendered on the value's OWN text line (never on a line beneath it) so a badged
   cell is never taller than its badge-less neighbours and grid rows keep their natural height. Mirrors
   Scoreboard.razor.css's .mp-sb-annot-stack rule, including the three things that rule depends on: display:inline
   (an atomic inline box establishes its own line box even when empty, which grew annotated rows by a full line),
   white-space:nowrap on the cells that carry a badge so a badge can never be pushed to a second line, and icon-only
   badges in the narrow grid cells (the type word stays in title/aria-label). */
.mp-rb-annot-stack {
    display: inline;
}
/* Next/Then card variant: the cards have room for the full "★PB"/"▲NR" wording, so only the cell badges go icon-only
   (see .mp-rb-annot-label below); this variant just needs a slightly wider gap from the lifter name. */
.mp-rb-annot-stack-inline { margin-left: 0.2rem; }

/* Only cells that really carry a badge opt out of wrapping — every other cell keeps its normal wrapping and height.
   The displayed value is a block by default (.mp-cell-val above, so the in-cell editor can replace it in place), and a
   block always ends its line — badges after it could never share it. In badge-bearing cells only, the value goes inline
   so the badges land beside it; .mp-cell-edit stays a block, so the editor still opens on its own line underneath.
   :not(.editing) matters: this selector outranks ".mp-edit-cell.editing .mp-cell-val { display: none }", so without it
   an open editor would show its old value alongside the input. */
.mp-runboard td:has(.mp-rb-annot) { white-space: nowrap; }
.mp-runboard td:has(.mp-rb-annot):not(.editing) .mp-cell-val { display: inline; }

.mp-rb-annot {
    display: inline-flex; align-items: center; gap: 0.15rem; margin-left: 0.2rem; padding: 0 0.3rem;
    border: 1px solid currentColor; border-radius: 999px; font-size: 0.6rem; font-weight: 900; letter-spacing: 0.04em;
    text-transform: uppercase; line-height: 1.55; white-space: nowrap; vertical-align: middle;
}

/* Icon-only inside the dense grid cells; the Next/Then cards and the prominent current-lifter callout keep the word. */
.mp-runboard td .mp-rb-annot-label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* Kind: PB (star) vs national record (triangle) — distinct hues/icons/text, never colour alone (§10). */
.mp-rb-annot.mp-rb-pb { color: var(--mp-accent, #eab308); }
.mp-rb-annot.mp-rb-record { color: #b57bff; }
/* Status shading layered on top of the kind colour. */
.mp-rb-annot.mp-rb-annot-ratified { background: color-mix(in srgb, var(--mp-good, #16a34a) 20%, transparent); }
.mp-rb-annot.mp-rb-annot-pending { background: color-mix(in srgb, currentColor 15%, transparent); }
.mp-rb-annot.mp-rb-annot-failed { color: var(--mp-muted, #9ca3af); opacity: 0.7; text-decoration: line-through; }
.mp-rb-annot.mp-rb-annot-superseded { color: var(--mp-muted, #9ca3af); opacity: 0.7; }

/* §6.2 current-lifter prominent callout: a larger variant of the same badge language, plus the threshold/secondary
   text lines beneath the name. */
.mp-run-name-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.mp-rb-annot-large { font-size: 0.78rem; padding: 0.2rem 0.55rem; border-radius: 7px; }
.mp-run-ind-secondary, .mp-run-ind-threshold { font-size: 0.85rem; margin-top: 0.1rem; }

/* §6.1 tri-state Indicators popover — plain JS/data-attribute toggling (run-board.js), CSS layout mirrors
   Scoreboard.razor.css's WP4 .mp-ind-popover positioning for visual consistency between the two toolbars. */
.mp-ind-wrap { position: relative; display: inline-flex; }
.mp-ind-popover {
    position: absolute; right: 0; top: calc(100% + 6px); z-index: 40; width: min(22rem, 90vw);
    margin-bottom: 0; box-shadow: 0 14px 38px rgba(0, 0, 0, 0.45);
}
.mp-ind-popover[hidden] { display: none; }
.mp-ind-row { display: grid; grid-template-columns: 7rem 1fr; align-items: center; gap: 0.5rem; margin-top: 0.6rem; }
.mp-ind-row > span { font-size: 0.8rem; font-weight: 700; }
.mp-ind-popover .mp-segmented { width: 100%; }
.mp-ind-popover .mp-segmented button { flex: 1; justify-content: center; }
@media (max-width: 650px) {
    .mp-ind-popover { position: fixed; left: 0.75rem; right: 0.75rem; top: 4.5rem; width: auto; }
}
/* §6.4: the Indicators control lives inside .mp-board-head, already hidden by the existing
   .mp-runboard.present .mp-board-head rule above — badges (outside mp-board-head) stay visible. */

/* Stacked per-division values (Division / Points / Place) — one line per division a lifter is entered in. */
.mp-stack { white-space: nowrap; vertical-align: top; }
.mp-stack div { line-height: 1.25; }
.mp-stack div + div { border-top: 1px dotted var(--mp-border); }

/* Platform / loading display (huge, chromeless). */
.mp-display { min-height: 100vh; display: flex; flex-direction: column; gap: 1.5rem; padding: 2rem 2.5rem; background: var(--mp-bg); color: var(--mp-text); }
.mp-display-top { display: flex; justify-content: space-between; align-items: baseline; }
.mp-display-name { font-size: 5rem; font-weight: 900; line-height: 1; letter-spacing: -0.02em; }
.mp-display-weight { font-size: 9rem; font-weight: 900; color: var(--mp-accent); line-height: 1; }
.mp-display-sub { font-size: 1.6rem; color: var(--mp-muted); }
.mp-display-next { font-size: 2rem; }
.mp-display-flash { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 10rem; font-weight: 900; z-index: 1100; }
.mp-display-flash.good { background: var(--mp-good); color: #fff; }
.mp-display-flash.nolift { background: var(--mp-nolift); color: #fff; }
.mp-plate-bar { display: flex; align-items: center; justify-content: center; gap: 3px; margin: 1rem 0; }
.mp-plate { display: inline-block; border-radius: 3px; border: 1px solid rgba(0,0,0,0.5); }
.mp-plate-axle { width: 120px; height: 12px; background: #9ca3af; border-radius: 6px; }

/* ---- Platform display (LiftingCast-style: one-side bar + flight mini-scoreboard) ---- */
.mp-pf-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 1.75rem; align-items: start; }
.mp-pf-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 1rem; }
.mp-pf-name { font-size: 3.6rem; font-weight: 900; line-height: 1; letter-spacing: -0.02em; }
.mp-pf-weight { font-size: 7rem; font-weight: 900; color: var(--mp-accent); line-height: 0.9; white-space: nowrap; }
.mp-pf-kg { font-size: 2.2rem; margin-left: 0.4rem; color: var(--mp-muted); }
.mp-onebar { display: flex; align-items: flex-end; gap: 4px; min-height: 150px; margin: 0.75rem 0 0.25rem; padding-left: 0.25rem; }
.mp-onebar-collar { width: 18px; height: 64px; background: #9ca3af; border-radius: 3px; align-self: center; }
.mp-plate-big { display: flex; align-items: center; justify-content: center; min-width: 46px; border-radius: 4px;
    border: 1px solid rgba(0,0,0,0.55); color: #fff; font-weight: 900; font-size: 1.5rem; text-shadow: 0 1px 2px rgba(0,0,0,0.6); }
.mp-minibar { display: inline-flex; align-items: center; gap: 2px; }
.mp-pf-next { width: 100%; margin-top: 1rem; font-size: 1.4rem; }
.mp-pf-next th { text-align: left; color: var(--mp-muted); font-size: 1rem; text-transform: uppercase; letter-spacing: 0.04em; }
.mp-pf-next td, .mp-pf-next th { padding: 0.45rem 0.6rem; border-bottom: 1px solid var(--mp-border); }
.mp-pf-board { width: 100%; font-size: 1.25rem; font-variant-numeric: tabular-nums; }
.mp-pf-board th { text-align: right; color: var(--mp-muted); font-size: 0.95rem; padding: 0.3rem 0.5rem; border-bottom: 2px solid var(--mp-border); }
.mp-pf-board th:first-child, .mp-pf-board td:first-child { text-align: left; }
.mp-pf-board td { text-align: right; padding: 0.32rem 0.5rem; border-bottom: 1px solid var(--mp-border); }
.mp-pf-lifter { font-weight: 700; }

/* ---- OBS overlay: detailed broadcast composition (WP6 §9.2/§9.3 — docs/specs/obs-overlay-mock.html is the
   authoritative visual reference: gold/dark panel system, top-left profile, top-centre decision lights, top-right
   up-next, 150px bottom banner). Panels stay permanently in the DOM (Overlay.razor never @if-removes one) and
   toggle a "collapsed"/"visible" class so the slide/collapse transitions below actually animate. ---- */
body:has(.mp-overlay-root) { background: transparent !important; overflow: hidden; }
.mp-overlay-root {
    position: fixed; inset: 0; overflow: hidden;
    color: var(--mp-text);
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    /* §9.2 resolution support (720p/1080p/4K without cropping or tiny text): every px dimension below is expressed
       as calc(N * var(--s)) where N is the 1920×1080 design value in px and --s is the "scaled pixel" LENGTH unit
       (100vh/1080 — exactly 1px at 1080p; note number×length is the only valid calc multiplication, so the design
       value is written unitless). 1080p renders pixel-identical to the design, 4K exactly 2×, 720p ~0.667×, all
       proportionally from the viewport HEIGHT (aspect-safe: an ultrawide keeps 1080p-size panels rather than
       blowing them up off the canvas). */
    --s: calc(100vh / 1080);
    /* Derived panel tokens, computed from the theme's --mp-* vars (set inline on this element by Overlay.razor) so
       a theme's colours are the source of truth and the mock's gold/dark reads as the DEFAULT palette (its --mp-accent
       default is already the barbell gold above). */
    --ovl-panel: linear-gradient(145deg, color-mix(in srgb, var(--mp-surface) 94%, white 4%), color-mix(in srgb, var(--mp-bg) 90%, black 12%));
    --ovl-good-dark: color-mix(in srgb, var(--mp-good) 60%, black);
    --ovl-nolift-dark: color-mix(in srgb, var(--mp-nolift) 60%, black);
    --ovl-line: color-mix(in srgb, white 15%, transparent);
    --ovl-ease: cubic-bezier(.22, .75, .18, 1);
}

/* Shared floating-panel look for all four panels. */
.mp-ovl-profile, .mp-ovl-decision, .mp-ovl-next, .mp-ovl-banner {
    border: 1px solid color-mix(in srgb, var(--mp-accent) 75%, transparent);
    background: var(--ovl-panel);
    box-shadow: 0 16px 50px rgba(0,0,0,0.48), inset 0 0 0 1px rgba(255,255,255,0.035);
    backdrop-filter: blur(13px);
}

/* ---- Top-left: lifter profile — image + identity + OPL stats + latest-three history ---- */
.mp-ovl-profile {
    position: absolute; top: 3.2vh; left: 1.3vw;
    display: grid; grid-template-rows: minmax(0,1fr) auto;
    width: min(31vw, calc(575 * var(--s))); height: min(64vh, calc(650 * var(--s))); min-height: calc(590 * var(--s));
    overflow: hidden; border-radius: calc(12 * var(--s)); transform-origin: left center;
    /* No `width` in the transition list (the mock had it): the collapse animates via transform/opacity, and a width
       transition also fires on viewport-driven min()/var(--s) changes, where it can freeze at currentTime 0 in
       non-compositing contexts (hidden tabs / OBS preview) leaving the panel stuck at the previous viewport's width. */
    transition: transform 680ms var(--ovl-ease), opacity 420ms ease;
}
.mp-ovl-profile.collapsed { transform: translateX(calc(-100% - 2vw)) scaleX(0.74); opacity: 0; pointer-events: none; }
.mp-ovl-profile-inner { display: grid; grid-template-columns: 42% minmax(0,58%); width: 100%; min-height: 0; overflow: hidden; }
.mp-ovl-profile-image {
    position: relative; width: 100%; height: 100%; min-height: 0; overflow: hidden; isolation: isolate;
    background: radial-gradient(circle at 50% 20%, rgba(255,255,255,0.12), transparent 28%),
        linear-gradient(180deg, color-mix(in srgb, var(--mp-surface) 80%, white 6%), color-mix(in srgb, var(--mp-bg) 85%, black 15%));
}
.mp-ovl-profile-image img, .mp-ovl-profile-image .mp-ovl-silhouette { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.mp-ovl-profile-copy { min-width: 0; min-height: 0; padding: calc(24 * var(--s)) calc(22 * var(--s)) calc(18 * var(--s)); overflow: hidden; }
.mp-ovl-name-row { display: flex; align-items: center; gap: calc(10 * var(--s)); min-width: 0; }
.mp-ovl-athlete-name { min-width: 0; margin: 0; overflow: hidden; font-size: calc(32 * var(--s)); line-height: 1; letter-spacing: 0.02em; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.mp-ovl-country { flex: 0 0 auto; color: var(--mp-muted); font-size: calc(16 * var(--s)); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }
.mp-ovl-team { margin: calc(9 * var(--s)) 0 calc(16 * var(--s)); color: var(--mp-accent); font-size: calc(15 * var(--s)); font-weight: 750; letter-spacing: 0.07em; text-transform: uppercase; }
.mp-ovl-bio { margin: 0 0 calc(16 * var(--s)); color: color-mix(in srgb, var(--mp-text) 88%, transparent); font-size: calc(15 * var(--s)); line-height: 1.48; }
.mp-ovl-section-heading { margin: calc(10 * var(--s)) 0 calc(8 * var(--s)); color: var(--mp-accent); font-size: calc(15 * var(--s)); font-weight: 850; letter-spacing: 0.08em; line-height: 1.2; text-transform: uppercase; }
.mp-ovl-stat-grid { display: grid; grid-template-columns: minmax(0,1fr) auto; gap: calc(7 * var(--s)) calc(14 * var(--s)); padding-top: calc(11 * var(--s)); border-top: 1px solid var(--ovl-line); color: var(--mp-muted); font-size: calc(13 * var(--s)); line-height: 1.15; text-transform: uppercase; }
.mp-ovl-stat-grid strong { color: var(--mp-text); text-align: right; white-space: nowrap; }
.mp-ovl-history { min-height: calc(150 * var(--s)); padding: calc(11 * var(--s)) calc(14 * var(--s)) calc(13 * var(--s)); overflow: hidden; border-top: 1px solid var(--ovl-line); background: rgba(0,0,0,0.25); }
.mp-ovl-history .mp-ovl-section-heading { margin-top: 0; }
.mp-ovl-history-table { display: grid; grid-template-columns: minmax(calc(90 * var(--s)),1.6fr) 0.6fr repeat(5, 0.62fr); gap: calc(6 * var(--s)); align-items: center; color: color-mix(in srgb, var(--mp-text) 90%, transparent); font-size: calc(12 * var(--s)); line-height: 1.2; margin-bottom: calc(6 * var(--s)); }
.mp-ovl-history-table span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-ovl-history-table.header { color: var(--mp-muted); text-transform: uppercase; }
.mp-ovl-history-empty { color: var(--mp-muted); font-size: calc(12.5 * var(--s)); padding-top: calc(5 * var(--s)); }

/* ---- Top-centre: temporary referee-decision panel — visible only during DecisionHold ---- */
.mp-ovl-decision {
    position: absolute; top: 3.5vh; left: 50%;
    width: min(32vw, calc(560 * var(--s))); padding: calc(22 * var(--s)) calc(28 * var(--s));
    border-radius: calc(11 * var(--s)); text-align: center; opacity: 0; pointer-events: none;
    transform: translateX(-50%) translateY(-14px) scale(0.96);
    transition: transform 430ms var(--ovl-ease), opacity 430ms ease;
}
.mp-ovl-decision.visible { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
.mp-ovl-decision-lift { margin-bottom: calc(10 * var(--s)); font-size: calc(28 * var(--s)); font-weight: 850; letter-spacing: 0.08em; text-transform: uppercase; }
.mp-ovl-lights { display: flex; justify-content: center; gap: calc(38 * var(--s)); margin: calc(6 * var(--s)) 0 calc(12 * var(--s)); }
.mp-ovl-light { width: calc(95 * var(--s)); aspect-ratio: 1; border-radius: 50%; background: #fff;
    box-shadow: 0 0 0 3px rgba(255,255,255,0.22), 0 0 26px rgba(255,255,255,0.75), inset 0 -8px 16px rgba(0,0,0,0.2); }
.mp-ovl-light.nolift {
    background: var(--mp-nolift);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-nolift) 25%, transparent), 0 0 29px color-mix(in srgb, var(--mp-nolift) 78%, transparent), inset 0 -8px 16px rgba(70,0,0,0.38);
}
.mp-ovl-light.empty { background: color-mix(in srgb, var(--mp-text) 12%, transparent); box-shadow: none; opacity: 0.4; }
.mp-ovl-decision-text {
    display: inline-flex; align-items: center; justify-content: center; min-width: calc(220 * var(--s)); padding: calc(7 * var(--s)) calc(18 * var(--s));
    border: 1px solid var(--mp-accent); border-radius: calc(7 * var(--s)); color: var(--mp-accent); background: rgba(0,0,0,0.78);
    font-size: calc(27 * var(--s)); font-weight: 900; letter-spacing: 0.06em; text-transform: uppercase;
}
.mp-ovl-decision-text.bad { color: #ff727b; border-color: #ff5561; }

/* ---- Top-right: up-next panel — default five from the authoritative run order ---- */
.mp-ovl-next {
    position: absolute; top: 3.4vh; right: 1.3vw;
    width: min(27vw, calc(480 * var(--s))); max-height: calc(540 * var(--s)); overflow: hidden; border-radius: calc(16 * var(--s));
    transform-origin: top right;
    /* No `max-height` in the transition list (the mock had it): the collapse reads as scaleY+opacity, and a
       max-height transition also fires on viewport-driven var(--s) changes, where it can freeze at currentTime 0
       in non-compositing contexts and clip the panel at the previous viewport's cap. */
    transition: transform 620ms var(--ovl-ease), opacity 350ms ease;
}
.mp-ovl-next.collapsed { max-height: calc(42 * var(--s)); opacity: 0; pointer-events: none; transform: translateY(-18px) scaleY(0.08); }
.mp-ovl-next-head { display: flex; align-items: center; justify-content: space-between; padding: calc(13 * var(--s)) calc(17 * var(--s)); border-bottom: 1px solid var(--ovl-line);
    font-size: calc(19 * var(--s)); font-weight: 850; letter-spacing: 0.04em; text-transform: uppercase; }
.mp-ovl-next-row { display: grid; grid-template-columns: calc(28 * var(--s)) 1fr auto; gap: calc(11 * var(--s)); align-items: center; min-height: calc(65 * var(--s)); padding: calc(8 * var(--s)) calc(14 * var(--s)); border-bottom: 1px solid rgba(255,255,255,0.1); }
.mp-ovl-next-row:last-child { border-bottom: 0; }
.mp-ovl-next-number { color: color-mix(in srgb, var(--mp-text) 90%, transparent); font-size: calc(15 * var(--s)); font-weight: 750; }
.mp-ovl-next-name { font-size: calc(17 * var(--s)); font-weight: 720; }
.mp-ovl-next-meta { margin-top: calc(2 * var(--s)); color: var(--mp-muted); font-size: calc(12 * var(--s)); text-transform: uppercase; }
.mp-ovl-next-attempt span { display: inline-block; min-width: calc(64 * var(--s)); padding: calc(6 * var(--s)) calc(9 * var(--s)); border-radius: calc(5 * var(--s)); background: color-mix(in srgb, var(--mp-surface) 70%, black 15%);
    font-size: calc(14 * var(--s)); font-weight: 760; text-align: center; }
.mp-ovl-next-attempt .entered { background: var(--ovl-good-dark); }
.mp-ovl-next-empty { padding: calc(14 * var(--s)); color: var(--mp-muted); font-size: calc(13 * var(--s)); text-align: center; text-transform: uppercase; }

/* ---- Bottom: information banner (150px at the 1080p design canvas, --s-scaled) — persistent except while every
   panel is mid-transition ---- */
.mp-ovl-banner {
    position: absolute; left: 1.25vw; right: 1.25vw; bottom: 3.25vh;
    display: grid; grid-template-columns: 1.15fr 0.75fr 0.83fr 1.65fr 1.05fr;
    height: calc(150 * var(--s)); overflow: hidden; border-radius: calc(14 * var(--s)); transform-origin: left center;
    clip-path: inset(0 0 0 0 round calc(14 * var(--s)));
    transition: transform 680ms var(--ovl-ease), opacity 360ms ease, clip-path 680ms var(--ovl-ease);
}
.mp-ovl-banner.collapsed-left { opacity: 0; pointer-events: none; transform: scaleX(0.02); clip-path: inset(0 98% 0 0 round calc(14 * var(--s))); }
.mp-ovl-banner-section { display: flex; flex-direction: column; justify-content: center; min-width: 0; min-height: 0; padding: calc(10 * var(--s)) calc(12 * var(--s)); overflow: hidden; border-right: 1px solid rgba(255,255,255,0.13); }
.mp-ovl-banner-section:last-child { border-right: 0; }
.mp-ovl-identity { display: grid; grid-template-columns: calc(62 * var(--s)) minmax(0,1fr); gap: calc(11 * var(--s)); align-items: center; min-height: 0; }
.mp-ovl-avatar {
    position: relative; width: calc(62 * var(--s)); height: calc(92 * var(--s)); overflow: hidden; border: 1px solid rgba(255,255,255,0.19); border-radius: calc(8 * var(--s));
    background: linear-gradient(color-mix(in srgb, var(--mp-surface) 80%, white 6%), color-mix(in srgb, var(--mp-bg) 85%, black 15%));
}
.mp-ovl-avatar img, .mp-ovl-avatar .mp-ovl-silhouette { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.mp-ovl-identity-name { overflow: hidden; font-size: calc(21 * var(--s)); font-weight: 880; line-height: 1; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.mp-ovl-identity-team { margin-top: calc(7 * var(--s)); color: var(--mp-accent); font-size: calc(11 * var(--s)); font-weight: 800; letter-spacing: 0.05em; line-height: 1.25; text-transform: uppercase; }
.mp-ovl-compact-stats { display: grid; grid-template-columns: 1fr auto; gap: calc(6 * var(--s)) calc(9 * var(--s)); color: var(--mp-muted); font-size: calc(11 * var(--s)); line-height: 1.1; text-transform: uppercase; }
.mp-ovl-compact-stats strong { color: var(--mp-text); text-align: right; white-space: nowrap; }
.mp-ovl-attempt-heading, .mp-ovl-placing-heading { flex: 0 0 auto; margin-bottom: calc(4 * var(--s)); color: var(--mp-accent); font-size: calc(11 * var(--s)); font-weight: 850; letter-spacing: 0.07em; line-height: 1.1; text-align: center; text-transform: uppercase; }
.mp-ovl-best-lifts { display: grid; grid-template-columns: repeat(4,1fr); overflow: hidden; border: 1px solid color-mix(in srgb, var(--mp-accent) 25%, transparent); border-radius: calc(8 * var(--s)); }
.mp-ovl-best-lifts div { padding: calc(8 * var(--s)) calc(4 * var(--s)); text-align: center; border-right: 1px solid rgba(255,255,255,0.12); }
.mp-ovl-best-lifts div:last-child { border-right: 0; }
.mp-ovl-best-lifts small { display: block; margin-bottom: calc(4 * var(--s)); color: var(--mp-accent); font-size: calc(9 * var(--s)); text-transform: uppercase; }
.mp-ovl-best-lifts strong { font-size: calc(14 * var(--s)); }
.mp-ovl-attempt-wrap { position: relative; justify-content: flex-start; gap: 0; }
/* RP WP6 §7.1/§7.2: the dedicated attempt callout. The kicker (lift/attempt/weight) always renders; the PB and
   record badge lines are ALWAYS in the DOM at a fixed reserved size (mp-ovl-callout-empty only flips visibility),
   so toggling the meet's indicator defaults or an annotation appearing/disappearing never changes this block's
   height and never moves the attempt cells below it or the banner sections beside it (§7.2 no-layout-jump). */
.mp-ovl-callout-kicker { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.mp-ovl-callout-badges { display: flex; flex-direction: column; align-items: flex-start; gap: calc(3 * var(--s)); margin: calc(4 * var(--s)) 0 calc(6 * var(--s)); }
.mp-ovl-callout-badge {
    display: flex; align-items: center; max-width: 100%; min-height: calc(19 * var(--s)); padding: 0 calc(8 * var(--s));
    overflow: hidden; border: 1px solid currentColor; border-radius: 999px; font-size: calc(10.5 * var(--s));
    font-weight: 900; letter-spacing: 0.04em; line-height: 1; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap;
}
/* Reserves the same box (visibility, not removal — §7.2) so a disabled/absent kind leaves no visible trace. */
.mp-ovl-callout-badge.mp-ovl-callout-empty { visibility: hidden; }
/* Kind colour (never colour alone — §10; both lines always carry full "PB"/"NATIONAL RECORD" text too) — same
   palette as Scoreboard.razor.css/RunMeet.razor's .mp-sb-annot/.mp-rb-annot rules, so every surface reads as one
   system. */
.mp-ovl-callout-badge.mp-ovl-callout-pb { color: var(--mp-accent); }
.mp-ovl-callout-badge.mp-ovl-callout-record { color: #b57bff; }
/* Status shading layered on top of the kind colour — order matters: these come AFTER the kind rules above so a
   failed/superseded annotation always mutes regardless of kind (mirrors the board CSS's cascade order). */
.mp-ovl-callout-badge.mp-ovl-callout-ratified { background: color-mix(in srgb, var(--mp-good) 22%, transparent); }
.mp-ovl-callout-badge.mp-ovl-callout-pending { background: color-mix(in srgb, currentColor 16%, transparent); }
.mp-ovl-callout-badge.mp-ovl-callout-failed { color: var(--mp-muted); opacity: 0.72; text-decoration: line-through; }
.mp-ovl-callout-badge.mp-ovl-callout-superseded { color: var(--mp-muted); opacity: 0.72; }
.mp-ovl-attempts { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); flex: 1 1 auto; gap: calc(7 * var(--s)); min-height: 0; overflow: hidden; }
.mp-ovl-attempt {
    position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; min-width: 0; min-height: 0; overflow: hidden;
    border: 1px solid rgba(255,255,255,0.14); border-radius: calc(7 * var(--s)); background: color-mix(in srgb, var(--mp-surface) 75%, black 15%);
}
.mp-ovl-attempt.good { background: linear-gradient(145deg, var(--mp-good), var(--ovl-good-dark)); }
.mp-ovl-attempt.bad { background: linear-gradient(145deg, var(--mp-nolift), var(--ovl-nolift-dark)); }
.mp-ovl-attempt.current { border-color: var(--mp-accent); background: rgba(17,20,23,0.96); box-shadow: inset 0 0 20px color-mix(in srgb, var(--mp-accent) 6%, transparent); }
.mp-ovl-attempt small { display: block; max-width: 95%; margin-bottom: calc(3 * var(--s)); overflow: hidden; color: color-mix(in srgb, var(--mp-text) 92%, transparent); font-size: calc(9 * var(--s)); font-weight: 850; line-height: 1.05; text-align: center; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.mp-ovl-attempt strong { font-size: calc(26 * var(--s)); line-height: 1; }
.mp-ovl-attempt.bad::after { content: ""; position: absolute; width: 135%; height: calc(3 * var(--s)); background: rgba(255,255,255,0.72); transform: rotate(-27deg); }
.mp-ovl-placing {
    display: grid; grid-template-columns: minmax(0,1fr) calc(22 * var(--s)) minmax(0,1fr); flex: 1 1 auto; align-items: center; min-height: 0; overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--mp-accent) 28%, transparent); border-radius: calc(8 * var(--s)); background: rgba(0,0,0,0.22);
}
.mp-ovl-place-card { min-width: 0; text-align: center; }
.mp-ovl-place-card small { display: block; margin-bottom: calc(3 * var(--s)); overflow: hidden; color: color-mix(in srgb, var(--mp-text) 88%, transparent); font-size: calc(9 * var(--s)); line-height: 1.05; text-overflow: ellipsis; text-transform: uppercase; white-space: nowrap; }
.mp-ovl-place-card strong { font-size: calc(30 * var(--s)); line-height: 1; white-space: nowrap; }
.mp-ovl-place-card.forecast strong { color: var(--mp-accent); }
.mp-ovl-arrow { color: var(--mp-accent); font-size: calc(21 * var(--s)); line-height: 1; text-align: center; }

@media (max-aspect-ratio: 16/10) {
    .mp-ovl-profile { width: 32vw; }
    .mp-ovl-next { width: 30vw; }
    .mp-ovl-banner { grid-template-columns: 1.05fr 0.72fr 0.82fr 1.62fr 1fr; }
}

/* Auto-save status indicator. */
.mp-autosave-status { font-size: 0.85rem; font-weight: 600; color: var(--mp-muted); }
.mp-autosave-status[data-state="saved"] { color: var(--mp-good); }
.mp-autosave-status[data-state="pending"] { color: var(--mp-accent); }

.mp-card {
    background: var(--mp-surface);
    border: 1px solid var(--mp-border);
    border-radius: 12px;
    padding: 1.25rem 1.4rem;
    margin-bottom: 1rem;
}
.mp-card h3 { margin-top: 0; }

.mp-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

/* ==== Setup tab professional redesign (WP2, docs/specs/setup-redesign/*) ====
   Everything below is scoped under .mp-setup-scope (the /manage?tab=setup root — see ManageMeet.razor) so the
   dark-control rewrite and the 12-col shell don't regress any other page. The three lower tools (EntryFormEditor /
   OplImportPanel / RecordBookPanel) render inside this scope too and already reuse .mp-card/.mp-setup-sec/
   .mp-setup-head/.mp-setup-grid/.mp-setup-check/.mp-setup-chips/.form-control — restyling those shared classes
   here restyles the tools consistently for free, without touching their internals (WP0 §2 rule 5). */

/* ---- Page header (SetupPageHeader.razor) — eyebrow + title + counts strip, replaces .mp-setup-overview ---- */
.mp-setup-pagehead {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1.5rem; align-items: center;
    margin: 0 0 1rem; padding: 1.1rem 1.2rem; border: 1px solid var(--mp-border); border-radius: 12px;
    background: linear-gradient(105deg, color-mix(in srgb, var(--mp-accent) 11%, transparent), transparent 42%), var(--mp-surface);
    box-shadow: 0 12px 28px rgba(0,0,0,0.17);
}
.mp-setup-pagehead-copy { min-width: 0; }
.mp-setup-eyebrow {
    display: block; margin-bottom: 0.25rem; color: var(--mp-accent); font-size: 0.68rem; font-weight: 800;
    letter-spacing: 0.09em; text-transform: uppercase;
}
.mp-setup-pagehead h2 { margin: 0; font-size: clamp(1.25rem, 1.8vw, 1.6rem); letter-spacing: -0.02em; }
.mp-setup-pagehead p { margin: 0.35rem 0 0; max-width: 48rem; color: var(--mp-muted); font-size: 0.85rem; }
.mp-setup-stats {
    display: grid; grid-template-columns: repeat(4, minmax(4.6rem, 1fr)); margin: 0; overflow: hidden;
    border: 1px solid var(--mp-border); border-radius: 9px; background: color-mix(in srgb, var(--mp-bg) 70%, transparent);
}
.mp-setup-stats div { min-width: 4.6rem; padding: 0.55rem 0.8rem; text-align: center; border-left: 1px solid var(--mp-border); }
.mp-setup-stats div:first-child { border-left: 0; }
.mp-setup-stats dt { color: var(--mp-muted); font-size: 0.62rem; font-weight: 750; letter-spacing: 0.05em; text-transform: uppercase; }
.mp-setup-stats dd { margin: 0.1rem 0 0; color: var(--mp-text); font-size: 1.05rem; font-weight: 850; font-variant-numeric: tabular-nums; }

/* ---- 12-column shell (replaces the .mp-setup-cols CSS-multicolumn masonry: predictable DOM/keyboard order,
   explicit spans instead of surprising column-fill reflow — WP0 §0.1/§2 rule 7). ---- */
.mp-setup-shell { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 1rem; align-items: start; }
.mp-setup-c12 { grid-column: span 12; }
.mp-setup-c8 { grid-column: span 8; }
.mp-setup-c6 { grid-column: span 6; }
.mp-setup-c4 { grid-column: span 4; }
.mp-setup-wide { grid-column: 1 / -1; }
/* RP WP3: stacks 2+ cards inside one grid column div (e.g. Scoring & running rules + Attempt indicators) so the
   second card renders directly beneath the first — a same-span sibling grid item would instead auto-place at
   column 1 of the next row, not underneath this column (see ManageMeet.razor Setup column 2). */
.mp-setup-c4-stack { display: flex; flex-direction: column; gap: 1rem; }

/* ---- Dark control base + full state coverage (fable-spec §6.2/§6.3) ----
   rest / hover / focus-visible / filled / placeholder / disabled / read-only / invalid, for text, number, select,
   password, search, colour inputs and the MultiSelectDropdown trigger. No input stays a harsh white box.
   Email notifications WP4 (WP0 §1.3: "new scope class .mp-comms-scope mirrors it") — every selector below also
   matches under .mp-comms-scope so Communications/Settings/Compose/Providers get the identical dark controls
   without a second, drifting copy of this block. */
.mp-setup-scope .form-control,
.mp-setup-scope .mp-multiselect > summary.msd-control,
.mp-comms-scope .form-control,
.mp-comms-scope .mp-multiselect > summary.msd-control {
    display: block; width: 100%; min-height: 2.35rem; padding: 0 0.65rem; color: var(--mp-text);
    background: var(--mp-control-bg); border: 1px solid var(--mp-control-border); border-radius: 7px;
    box-shadow: inset 0 1px 1px rgba(0,0,0,0.2); outline: none;
    transition: border-color .14s ease, background-color .14s ease, box-shadow .14s ease;
}
.mp-setup-scope input[type="color"].form-control, .mp-comms-scope input[type="color"].form-control { padding: 0.2rem; cursor: pointer; }
.mp-setup-scope .form-control::placeholder, .mp-comms-scope .form-control::placeholder { color: var(--mp-control-placeholder); opacity: 1; }
.mp-setup-scope .form-control:hover:not(:disabled):not([readonly]),
.mp-setup-scope .mp-multiselect > summary.msd-control:hover,
.mp-comms-scope .form-control:hover:not(:disabled):not([readonly]),
.mp-comms-scope .mp-multiselect > summary.msd-control:hover { background: var(--mp-control-bg-hover); border-color: #435164; }
.mp-setup-scope .form-control:focus-visible,
.mp-setup-scope .form-control:focus,
.mp-setup-scope .mp-multiselect[open] > summary.msd-control,
.mp-comms-scope .form-control:focus-visible,
.mp-comms-scope .form-control:focus,
.mp-comms-scope .mp-multiselect[open] > summary.msd-control {
    border-color: var(--mp-control-border-focus); background: #19212b;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-control-border-focus) 22%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-setup-scope .form-control:disabled, .mp-setup-scope .form-control[disabled],
.mp-comms-scope .form-control:disabled, .mp-comms-scope .form-control[disabled] {
    opacity: 0.55; cursor: not-allowed; background: color-mix(in srgb, var(--mp-control-bg) 65%, var(--mp-bg));
}
.mp-setup-scope .form-control[readonly], .mp-comms-scope .form-control[readonly] { background: transparent; border-style: dashed; color: var(--mp-muted); }
.mp-setup-scope .form-control.invalid, .mp-setup-scope .form-control[aria-invalid="true"],
.mp-comms-scope .form-control.invalid, .mp-comms-scope .form-control[aria-invalid="true"] {
    border-color: var(--mp-nolift);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-nolift) 18%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-setup-scope .validation-message, .mp-comms-scope .validation-message { display: block; margin-top: 0.3rem; color: var(--mp-nolift); font-size: 0.78rem; font-weight: 700; }
.mp-setup-scope select.form-control, .mp-comms-scope select.form-control {
    appearance: none; -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, #7d8999 50%), linear-gradient(135deg, #7d8999 50%, transparent 50%);
    background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%; background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
    padding-right: 1.7rem;
}
.mp-setup-scope input[type="search"].form-control, .mp-comms-scope input[type="search"].form-control { padding-left: 2.1rem; }
.mp-setup-scope input[type="checkbox"], .mp-comms-scope input[type="checkbox"] { accent-color: var(--mp-accent); width: 15px; height: 15px; }
/* File inputs (OplImportPanel/RecordBookPanel CSV uploads — fable-spec §6.3/§9.4 explicitly names "file" in the
   required dark-control coverage list): the <input> box itself already picks up .form-control above, but the
   "Choose File" affordance is a distinct native pseudo-element that ignores the input's own background/border, so
   without this rule it stays a plain white OS button against the dark card — confirmed via the WP4 evidence
   captures. Both the standard and the WebKit/Blink-prefixed selector are needed (Chromium, which Playwright and
   most directors' browsers use, still only recognises the prefixed one). */
.mp-setup-scope input[type="file"].form-control { padding: 0.3rem 0.65rem; cursor: pointer; }
/* Kept as two separate rules deliberately, NOT a comma-separated group: a plain (non-:is()) selector list is
   invalidated as a whole if any browser doesn't recognise one of its selectors, so grouping the standard and the
   -webkit- form together silently dropped BOTH in Chromium (confirmed — the button rendered as a stock white OS
   control until this was split; Playwright/most directors run Chromium, which needs the prefixed selector). */
.mp-setup-scope input[type="file"].form-control::-webkit-file-upload-button {
    margin-right: 0.65rem; padding: 0.35rem 0.7rem; color: var(--mp-text); font: inherit; font-weight: 700;
    background: var(--mp-nested-surface); border: 1px solid var(--mp-control-border); border-radius: 6px; cursor: pointer;
    transition: background-color .14s ease, border-color .14s ease;
}
.mp-setup-scope input[type="file"].form-control::file-selector-button {
    margin-right: 0.65rem; padding: 0.35rem 0.7rem; color: var(--mp-text); font: inherit; font-weight: 700;
    background: var(--mp-nested-surface); border: 1px solid var(--mp-control-border); border-radius: 6px; cursor: pointer;
    transition: background-color .14s ease, border-color .14s ease;
}
.mp-setup-scope input[type="file"].form-control:hover::-webkit-file-upload-button { background: var(--mp-control-bg-hover); border-color: #435164; }
.mp-setup-scope input[type="file"].form-control:hover::file-selector-button { background: var(--mp-control-bg-hover); border-color: #435164; }

/* ---- Card shell + header (shared by the 8 new sections AND the 3 lower tools) ----
   WP4 (Overalls divisions-menu clipping fix): overflow:hidden used to live on the WHOLE card purely so its own
   top corners stayed rounded under the header's flush top edge — but that ALSO clipped any descendant that needs
   to paint outside the card's own box, like an open MultiSelectDropdown menu (.msd-menu, position:absolute inside
   .mp-multiselect — see ScoringRunningSection.razor's overalls divisions field). The corner clip now lives on
   .mp-setup-head alone (matching top border-radius + its own overflow:hidden) — the card's own background already
   follows its border-radius natively with no overflow rule needed, and every OTHER direct child is already inset
   by the .mp-setup-sec > * margin rule below, so nothing else ever touched the rounded corners in the first place
   (confirmed against every current .mp-setup-sec usage, including the header-less lower tools and Results.razor's
   plain h3+table cards). position:relative is the positioning context the .mp-setup-sec:has(.mp-multiselect[open])
   rule further down promotes with z-index while a menu is open. */
.mp-setup-sec {
    padding: 0; border-radius: 12px; position: relative;
    box-shadow: 0 12px 28px rgba(0,0,0,0.17);
}
.mp-setup-head {
    display: flex; align-items: flex-start; gap: 0.7rem; flex-wrap: wrap; margin: 0 0 0.9rem;
    padding: 1rem 1.1rem 0.75rem; border-bottom: 1px solid color-mix(in srgb, var(--mp-border) 85%, transparent);
    border-radius: 12px 12px 0 0; overflow: hidden;
}
.mp-setup-head::before {
    content: ""; align-self: stretch; width: 3px; min-height: 1.25rem; border-radius: 999px; background: var(--mp-accent);
}
.mp-setup-head h3 { margin: 0; font-size: 1rem; letter-spacing: -0.01em; }
.mp-setup-head .mp-muted { flex: 1 1 14rem; font-size: 0.78rem; line-height: 1.4; }
.mp-setup-card-icon {
    flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center; margin-top: -0.05rem;
    border: 1px solid #344150; border-radius: 8px; background: var(--mp-nested-surface); color: var(--mp-accent);
    font-size: 0.7rem; font-weight: 800;
}
.mp-setup-card-titles { min-width: 0; }
.mp-setup-card-titles h3 { margin: 0; font-size: 1rem; letter-spacing: -0.01em; }
.mp-setup-card-titles .mp-muted { display: block; margin-top: 0.15rem; font-size: 0.78rem; line-height: 1.4; }
/* Section bodies (everything after the header) get consistent side/bottom padding; the header owns its own
   top/side padding when present (my 8 new sections + EntryFormEditor). OplImportPanel/RecordBookPanel don't use
   .mp-setup-head at all (their own .mp-compact-row IS the first child) so the first-child rule gives them the
   top inset the old uniform `.mp-setup-sec { padding: 1rem 1.1rem }` used to provide. */
.mp-setup-sec > *:not(.mp-setup-head) { margin-left: 1.1rem; margin-right: 1.1rem; }
.mp-setup-sec > *:not(.mp-setup-head):first-child { margin-top: 1.1rem; }
.mp-setup-sec > *:last-child { margin-bottom: 1.1rem; }
.mp-setup-sec > .mp-setup-head + * { margin-top: 0; }

.mp-setup-grid {
    display: grid; gap: 0.7rem 0.8rem;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 175px), 1fr)); align-items: end;
}
.mp-setup-grid label.mp-muted { display: block; margin-bottom: 0.22rem; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.015em; }
.mp-setup-sec h4 {
    margin: 0.9rem 0 0.4rem !important; color: var(--mp-muted); font-size: 0.7rem;
    font-weight: 800; letter-spacing: 0.055em; text-transform: uppercase;
}
.mp-setup-check {
    display: flex; align-items: center; gap: 0.5rem; min-height: 2.35rem; padding: 0.45rem 0.6rem;
    border: 1px solid var(--mp-control-border); border-radius: 8px; background: var(--mp-nested-surface); white-space: normal;
}
.mp-setup-check input { flex: 0 0 auto; }
.mp-setup-sec .mp-btn.danger[title^="Remove"] {
    display: inline-grid; place-items: center; flex: 0 0 2.35rem; width: 2.35rem; min-width: 2.35rem;
    height: 2.35rem; padding: 0; line-height: 1;
}
.mp-setup-divider { height: 1px; background: var(--mp-border); margin: 0.85rem 0; }
.mp-setup-subhead { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin-top: 0.4rem; color: var(--mp-muted); }
.mp-setup-addrow { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; }
.mp-setup-addrow .form-control { flex: 1 1 6rem; min-width: 5rem; }

/* ---- Toggle-switch rows (Public meet / self-registration / live+final results / attempt options) ----
   Still a real, keyboard-operable, labelled <input type=checkbox> — only its appearance changes to a pill switch. */
.mp-setup-toggle-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.55rem; }
.mp-setup-toggle {
    display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; min-height: 2.65rem;
    padding: 0.5rem 0.65rem; border: 1px solid var(--mp-control-border); border-radius: 8px;
    background: var(--mp-nested-surface); cursor: pointer; font-size: 0.82rem; font-weight: 650;
}
.mp-setup-toggle input[type="checkbox"] {
    appearance: none; -webkit-appearance: none; flex: 0 0 auto; width: 34px; height: 20px; margin: 0;
    border-radius: 999px; background: #293443; border: 1px solid #3b4859; position: relative; cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
.mp-setup-toggle input[type="checkbox"]::after {
    content: ""; position: absolute; width: 14px; height: 14px; border-radius: 50%; background: #7c8999;
    left: 2px; top: 2px; transition: left .15s ease, background-color .15s ease;
}
.mp-setup-toggle input[type="checkbox"]:checked { background: rgba(240,185,77,.25); border-color: #a87a28; }
.mp-setup-toggle input[type="checkbox"]:checked::after { left: 16px; background: var(--mp-accent); }
.mp-setup-toggle input[type="checkbox"]:focus-visible { outline: 2px solid var(--mp-control-border-focus); outline-offset: 2px; }
.mp-setup-toggle input[type="checkbox"]:disabled { opacity: 0.5; cursor: not-allowed; }

/* ---- Attempt indicators (AttemptIndicatorsSection.razor — PB/record spec §4) ----
   .mp-ai-rule reuses .mp-setup-toggle's switch look (same selector above styles its checkbox) but stacks the two
   rows in one column and allows a wrapping help line under each label, which the 2-up .mp-setup-toggle-grid has no
   room for. The summary pills' live text (§4.1 "updates immediately") is pure CSS: each .mp-ai-eff holds four
   spans, and exactly one is shown depending on the two switches' :checked state — no JS, no interactive render
   mode, matching this static-SSR page (same ":has()"-driven-visibility technique as .mp-cf-panel above). */
.mp-ai-rules { display: flex; flex-direction: column; gap: 0.5rem; }
.mp-ai-rule { align-items: flex-start; }
.mp-ai-rule-text { display: flex; flex-direction: column; gap: 0.2rem; padding-right: 0.5rem; }
.mp-ai-rule-text strong { font-size: 0.85rem; font-weight: 650; }
.mp-ai-rule-text small { font-size: 0.74rem; font-weight: 400; line-height: 1.35; color: var(--mp-muted); }
.mp-ai-rule input[type="checkbox"] { margin-top: 0.2rem; }

.mp-ai-summary-row { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.85rem; }
.mp-ai-pill {
    display: inline-flex; align-items: center; gap: 0.25rem; width: max-content; max-width: 100%;
    padding: 0.2rem 0.6rem; border-radius: 999px; font-size: 0.76rem; font-weight: 500;
    background: var(--mp-nested-surface); border: 1px solid var(--mp-border); color: var(--mp-muted);
}
.mp-ai-pill .mp-ai-eff { color: var(--mp-text); font-weight: 700; }
.mp-ai-eff span { display: none; }
.mp-ai-card:has(#ai-pb-switch:checked):has(#ai-record-switch:checked) .mp-ai-eff .mp-ai-both { display: inline; }
.mp-ai-card:has(#ai-pb-switch:checked):has(#ai-record-switch:not(:checked)) .mp-ai-eff .mp-ai-pbonly { display: inline; }
.mp-ai-card:has(#ai-pb-switch:not(:checked)):has(#ai-record-switch:checked) .mp-ai-eff .mp-ai-nronly { display: inline; }
.mp-ai-card:has(#ai-pb-switch:not(:checked)):has(#ai-record-switch:not(:checked)) .mp-ai-eff .mp-ai-none { display: inline; }

.mp-ai-notice {
    background: color-mix(in srgb, var(--mp-info) 14%, var(--mp-surface)); border: 1px solid var(--mp-info);
    border-radius: 8px; padding: 0.6rem 0.9rem; font-size: 0.85rem; margin-top: 0.6rem;
}

/* ---- Schedule & structure (ScheduleStructureSection.razor) ---- */
.mp-setup-structure { display: grid; grid-template-columns: 15.5rem minmax(0, 1fr); gap: 0.8rem; align-items: start; }
.mp-setup-mini-col { display: grid; gap: 0.7rem; }
.mp-setup-mini-panel { border: 1px solid var(--mp-border); border-radius: 9px; background: var(--mp-nested-surface); overflow: hidden; }
.mp-setup-mini-head { margin: 0; padding: 0.55rem 0.65rem; color: var(--mp-muted); border-bottom: 1px solid var(--mp-border); font-size: 0.68rem; font-weight: 760; text-transform: uppercase; letter-spacing: 0.05em; }
.mp-setup-mini-list { list-style: none; margin: 0; padding: 0.35rem; }
.mp-setup-mini-list li { display: flex; gap: 0.4rem; align-items: center; padding: 0.2rem 0.2rem; }
.mp-setup-mini-addrow { display: flex; gap: 0.4rem; padding: 0.5rem; border-top: 1px solid var(--mp-border); }
.mp-setup-schedule-panel { padding: 0.7rem 0.8rem; }
.mp-setup-schedule-day { margin-bottom: 0.75rem; }
.mp-setup-schedule-day:last-of-type { margin-bottom: 0; }
.mp-setup-flight-pill { display: inline-flex; gap: 0.2rem; align-items: center; }
@media (max-width: 900px) { .mp-setup-structure { grid-template-columns: 1fr; } }

/* ---- Competition catalogues (CompetitionCataloguesSection.razor) — 4-cell grid per the mock ---- */
/* align-items:start (grid default is stretch): with real content, "Weight classes" is reliably taller than the
   other three catalogues (sex-segmented lists + a 3-field add-row vs. their single-field add-rows) — stretching
   every card to match turned Age divisions/Equipment/Events into mostly-empty boxes (confirmed in the 1440x1000
   evidence capture). Letting each catalogue size to its own content removes that dead space. */
.mp-setup-catalog-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.65rem; align-items: start; }
.mp-setup-catalog {
    min-height: 7rem; padding: 0.7rem 0.75rem; border: 1px solid var(--mp-border); border-radius: 9px;
    background: linear-gradient(160deg, rgba(255,255,255,0.018), transparent 44%), var(--mp-nested-surface);
}
.mp-setup-catalog-top { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.5rem; }
.mp-setup-catalog-top b { font-size: 0.82rem; }
.mp-setup-catalog-top .mp-muted { font-size: 0.72rem; }
.mp-setup-catalog .mp-setup-subhead:first-of-type { margin-top: 0; }
@media (max-width: 1099px) { .mp-setup-catalog-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .mp-setup-catalog-grid { grid-template-columns: 1fr; } }

/* ---- Overall add-form: name and divisions each take a fixed half — the divisions box grows in height (chips
   wrap) as more are chosen, without either box changing width. ---- */
.mp-setup-overalls { display: flex; flex-direction: column; gap: 0.7rem; margin-top: 0.5rem; }
.mp-setup-overall-row { display: flex; flex-direction: column; gap: 0.35rem; }
.mp-ov-namerow { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; align-items: start; }
.mp-ov-namerow > .form-control { width: 100%; min-width: 0; }
.mp-ov-namerow > .mp-multiselect { width: 100%; min-width: 0; }

/* WP4: Formula / Age coefficient / Grouping (Split by sex) / Remove / Add share one >=38px control baseline.
   Root cause was two-fold: (1) .mp-setup-addrow's shared align-items:center vertically CENTRES children instead
   of bottom-aligning them, so a short bare control floats mid-row against a taller labelled <div><label/><select/>
   </div> sibling instead of sharing its bottom edge; (2) the checkbox had no label-above at all, unlike Formula/
   Age coefficient. .mp-setup-addrow itself is untouched (the catalogue add-rows and schedule add-forms that also
   use it are already uniform-height, bare-control rows and already look correct centred) — .mp-ov-addrow is a
   scoped modifier applied ONLY to the overalls row, so this fix can't regress those. flex-end bottom-aligns every
   child regardless of its own height; wrapping "Split by sex" in the same label-above-control shape as Formula/
   Age coefficient (see ScoringRunningSection.razor) makes the three fields structurally identical, and Remove/Add
   get an explicit 38px floor so a short bare button can't float above the shared baseline either. row-gap covers
   the 2-columns-then-1 reflow as flex-wrap drops items to new lines at narrow widths. */
.mp-ov-addrow { align-items: flex-end; row-gap: 0.5rem; }
.mp-ov-addrow > div { flex: 1 1 6.5rem; min-width: 5.75rem; }
.mp-ov-addrow .form-control, .mp-ov-addrow .mp-setup-check { min-height: 38px; }
.mp-ov-addrow > .mp-btn { min-height: 38px; flex: 0 0 auto; }
.mp-ov-addrow > .mp-btn.danger[title^="Remove"] { width: 38px; height: 38px; flex: 0 0 38px; }

/* ---- FU-D: per-row Eligibility disclosure (results handoff §5.3) — collapsed by default, native <details>, no
   JS required to open/close. Its own Events/Equipment MultiSelectDropdowns are each a SEPARATE <details
   class="mp-multiselect"> nested one level inside this one; that nesting needed no changes to the existing
   card-elevation z-index chain (.mp-setup-scope .mp-setup-sec:has(.mp-multiselect[open]) → .mp-multiselect[open]
   → .msd-menu, above) because :has() matches a descendant .mp-multiselect[open] at any depth, and .msd-menu
   positions itself relative to its own immediate .mp-multiselect ancestor, not this one. */
.mp-ov-eligibility { margin-top: 0.15rem; border: 1px solid var(--mp-control-border); border-radius: 8px; background: var(--mp-nested-surface); }
.mp-ov-eligibility > summary {
    list-style: none; cursor: pointer; display: flex; align-items: center; gap: 0.5rem;
    min-height: 38px; padding: 0 0.7rem; font-size: 0.78rem; font-weight: 700;
}
.mp-ov-eligibility > summary::-webkit-details-marker { display: none; }
.mp-ov-eligibility > summary::before { content: "▸"; font-size: 0.65rem; color: var(--mp-muted); transition: transform .15s ease; }
.mp-ov-eligibility[open] > summary::before { transform: rotate(90deg); }
.mp-ov-eligibility-hint { font-weight: 600; }
.mp-ov-eligibility-body { align-items: flex-end; row-gap: 0.5rem; padding: 0 0.7rem 0.7rem; }
.mp-ov-eligibility-body > div { flex: 1 1 9rem; min-width: 8.5rem; }
.mp-ov-eligibility-body .form-control, .mp-ov-eligibility-body .mp-multiselect { min-height: 38px; }
.mp-ov-eligibility-help { margin: 0 0.7rem 0.7rem; font-size: 0.72rem; }

/* ---- Setup-tab multiselect menu: paints above its own card, the next card, and the sticky save bar ----
   .mp-setup-sec no longer clips its children (see the card-shell rule above) — this elevates ONLY the card that
   currently owns an open menu (:has()), so the normal/closed stacking order is untouched. manage-structure.js
   additionally promotes the open menu to position:fixed with viewport-clamped coordinates (flips upward near the
   bottom of a short viewport, clamps max-height so a long option list always scrolls internally instead of
   overflowing the screen) — these z-index rules are both the non-JS fallback AND what actually governs paint
   order either way, since the JS only ever changes position/top/left/width/max-height, never z-index. Reference
   stacking (fable mock): card-with-open-menu 160 -> open .mp-multiselect 180 -> .msd-menu 200, above the sticky
   save bar (.mp-savebar, z-index 60 in this codebase — either order of magnitude, 200 clears it). */
.mp-setup-scope .mp-setup-sec:has(.mp-multiselect[open]) { z-index: 160; }
.mp-setup-scope .mp-multiselect[open] { z-index: 180; }
.mp-setup-scope .msd-menu { z-index: 200; }

/* ---- Bars &amp; collars: one row per lift — bar name (wide) + empty-bar weight (narrow). ---- */
.mp-setup-bar-rows { display: flex; flex-direction: column; gap: 0.5rem; }
.mp-setup-bar-row { display: grid; grid-template-columns: 1fr 5.5rem; gap: 0.75rem; align-items: end; }
.mp-setup-bar-row label.mp-muted { display: block; font-size: 0.8rem; margin-bottom: 0.15rem; }
.mp-setup-bar-row-collar > div:first-child { min-height: 2.35rem; display: flex; align-items: end; }

/* ---- Plate inventory: dense 4-column grid, full 14-denomination catalogue (fable-spec §4.2 — no chips). ---- */
.mp-setup-plates { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.4rem; }
.mp-setup-plate-row {
    display: flex; align-items: center; gap: 0.45rem; padding: 0.4rem 0.5rem; cursor: pointer;
    border: 1px solid var(--mp-border); border-radius: 7px; background: var(--mp-nested-surface);
}
.mp-setup-plate-kg { flex: 1; font-variant-numeric: tabular-nums; font-size: 0.82rem; }
.mp-setup-plate-row input[type="checkbox"] { width: 15px; height: 15px; }
.mp-setup-plate-row input[type="color"] { width: 2rem; height: 1.45rem; padding: 0; border: 1px solid var(--mp-control-border); border-radius: 4px; background: none; }
@media (max-width: 1099px) { .mp-setup-plates { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px) { .mp-setup-plates { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ---- Address lookup: suggestion dropdown anchored under the search input. ---- */
.mp-addr-wrap { position: relative; }
.mp-addr-wrap label.mp-muted { display: flex; justify-content: space-between; gap: 0.5rem; }
.mp-addr-results { position: absolute; left: 0; right: 0; top: 100%; z-index: 60; background: var(--mp-surface);
    border: 1px solid var(--mp-border); border-radius: 8px; margin-top: 2px; overflow: hidden;
    box-shadow: 0 8px 24px rgba(0,0,0,0.45); }
.mp-addr-item { display: block; width: 100%; text-align: left; background: none; border: 0; color: var(--mp-text);
    padding: 0.45rem 0.7rem; font-size: 0.85rem; cursor: pointer; border-bottom: 1px solid var(--mp-border); }
.mp-addr-item:last-child { border-bottom: 0; }
.mp-addr-item:hover { background: color-mix(in srgb, var(--mp-accent) 14%, var(--mp-surface)); }

.mp-setup-h2 { margin: 1.25rem 0 0.25rem; }
.mp-setup-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.3rem 0; }
.mp-setup-chip { display: inline-flex; align-items: center; gap: 0.3rem; background: var(--mp-bg);
    border: 1px solid var(--mp-border); border-radius: 999px; padding: 0.15rem 0.35rem 0.15rem 0.6rem; font-size: 0.85rem; }
/* The chip's remove button — quiet until hovered, then reads as destructive. */
.mp-chip-x { background: none; border: 0; color: var(--mp-muted); font-size: 1rem; line-height: 1;
    padding: 0 0.15rem; cursor: pointer; border-radius: 999px; }
.mp-chip-x:hover { color: #fff; background: var(--mp-nolift); }

/* ---- Sticky save bar (SetupSaveBar.razor visuals; EditForm shell stays on ManageMeet.razor) ----
   Fixed to the viewport bottom per the mock; .mp-setup-scope reserves bottom padding (see responsive tiers below)
   so it never covers the last section's controls. */
.mp-savebar {
    position: fixed; z-index: 60; left: 50%; bottom: 1.1rem; transform: translateX(-50%);
    width: min(1768px, calc(100% - 3.5rem)); display: flex; align-items: center; justify-content: space-between;
    gap: 0.75rem; padding: 0.65rem 0.75rem 0.65rem 1rem;
    background: color-mix(in srgb, var(--mp-surface) 94%, transparent); backdrop-filter: blur(14px);
    border: 1px solid var(--mp-control-border); border-radius: 11px;
    box-shadow: 0 20px 50px rgba(0,0,0,0.45);
}
.mp-savebar-note { visibility: hidden; display: flex; align-items: center; gap: 0.5rem; margin-right: auto; font-size: 0.8rem; font-weight: 650; }
.mp-savebar-note.show { visibility: visible; color: #d3b673; }
.mp-savebar-note.show::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--mp-accent); flex: 0 0 auto; }
/* Custom unsaved-changes dialog. */
.mp-dirty-dialog { background: var(--mp-surface); color: var(--mp-text); border: 1px solid var(--mp-border);
    border-radius: 12px; padding: 1.25rem 1.4rem; max-width: 26rem; }
.mp-dirty-dialog::backdrop { background: rgba(0, 0, 0, 0.55); }

/* ---- Responsive tiers (fable-spec §6.5) ----
   >=2400: the shell/page already stretch (no max-width cap on .mp-container) — no extra rule needed.
   1600-2399: the 12-col shell as authored above.
   1100-1599: two major columns — the 8-spans go full width, the 4-spans pair up into two per row; the 6-spans
     (bars&collars / racks&plates) are already two-up and need no change.
   768-1099: one column for every major card; sub-grids (catalogue, toggle-grid, plates) stay multi-up.
   <768: one column, 44px touch targets, no page-level horizontal scroll. */
.mp-setup-scope { padding-bottom: 5.5rem; }
/* >=2400px (fable-spec §6.5) used to cap this column at 2100px so single-line text fields wouldn't stretch to a
   fraction of a 3840px viewport. meets-ui fable-spec §6.1 supersedes that: no page-level surface cap is allowed
   anywhere, including here, so the setup column now stretches full-width with .mp-container (which itself has
   no max-width) at every viewport, including 4K. */
.mp-setup-scope { width: 100%; max-width: none; }
@media (min-width: 1100px) and (max-width: 1599px) {
    .mp-setup-c8 { grid-column: span 12; }
    /* Setup WP4: c4 cards (Registration & visibility, Scoring & running rules) never land adjacent to each other
       in DOM order — each is preceded by a span-12 card (Meet details / Schedule & structure), so a bare
       `span 6` here never actually "pairs up" as the original comment intended; it just leaves the other 6
       columns of that row blank (confirmed via the 1440x1000 evidence capture — a full row-height gap next to
       Registration & visibility, and again next to Scoring & running rules). Matching the <1100px tier (span 12)
       removes the dead space; the c6 cards (Bars & collars / Racks & plates) are genuinely adjacent siblings and
       keep their correct 6+6 pairing untouched below. */
    .mp-setup-c4 { grid-column: span 12; }
}
@media (max-width: 1099px) {
    .mp-setup-pagehead { grid-template-columns: 1fr; gap: 0.9rem; }
    .mp-setup-stats { width: 100%; }
    .mp-setup-shell { grid-template-columns: 1fr; }
    .mp-setup-c12, .mp-setup-c8, .mp-setup-c6, .mp-setup-c4 { grid-column: 1 / -1; }
}
@media (max-width: 767px) {
    .mp-setup-pagehead { padding: 1rem; }
    .mp-setup-stats { grid-template-columns: repeat(2, 1fr); }
    .mp-setup-stats div:nth-child(odd) { border-left: 0; }
    .mp-setup-stats div:nth-child(n+3) { border-top: 1px solid var(--mp-border); }
    .mp-setup-toggle-grid { grid-template-columns: 1fr; }
    .mp-setup-plates { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mp-setup-scope .form-control,
    .mp-setup-scope .mp-btn,
    .mp-setup-scope input[type="checkbox"]:not(.mp-setup-toggle input),
    .mp-setup-scope .mp-setup-plate-row { min-height: 44px; }
    .mp-savebar { width: calc(100% - 1.5rem); flex-wrap: wrap; }
}

.mp-muted { color: var(--mp-muted); }
.mp-hero { padding: 3rem 0 2rem; }
.mp-hero h1 { font-size: 2.5rem; font-weight: 800; letter-spacing: -0.03em; }
.mp-hero p { color: var(--mp-muted); font-size: 1.15rem; max-width: 640px; }

/* display:inline-flex + width:max-content (rather than plain inline-block) plus an explicit white-space:nowrap
   (meets-ui fable-spec §5.6) guarantees .mp-badge.live can never break into two lines inside a narrow composite
   header track, without resorting to an oversized fixed width. */
.mp-badge {
    display: inline-flex; align-items: center; width: max-content; max-width: 100%; white-space: nowrap;
    padding: 0.15rem 0.6rem; border-radius: 999px;
    font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    background: var(--mp-surface-2); color: var(--mp-muted); border: 1px solid var(--mp-border);
}
.mp-badge.good { color: var(--mp-good); border-color: var(--mp-good); }
.mp-badge.nolift { color: var(--mp-nolift); border-color: var(--mp-nolift); }
.mp-badge.live { color: var(--mp-accent); border-color: var(--mp-accent); }

.mp-btn {
    display: inline-block; padding: 0.55rem 1.1rem; border-radius: 8px; font-weight: 700;
    background: var(--mp-accent); color: #1a1300; text-decoration: none; border: none; cursor: pointer;
}
.mp-btn.secondary { background: var(--mp-surface-2); color: var(--mp-text); border: 1px solid var(--mp-border); }
.mp-btn.danger { background: var(--mp-surface-2); color: var(--mp-nolift); border: 1px solid var(--mp-border); font-weight: 800; }
.mp-btn.danger:hover { background: var(--mp-nolift); color: #fff; border-color: var(--mp-nolift); }
.mp-btn.ghost { background: transparent; color: var(--mp-text); border: 1px solid transparent; font-weight: 600; }
.mp-btn.ghost:hover { border-color: var(--mp-border); }
.mp-btn:disabled { opacity: 0.45; cursor: default; }

table.mp-table { width: 100%; border-collapse: collapse; }
.mp-table th, .mp-table td { padding: 0.6rem 0.8rem; text-align: left; border-bottom: 1px solid var(--mp-border); }
.mp-table th { color: var(--mp-muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; }

/* Referee light pips */
.mp-lights { display: inline-flex; gap: 0.4rem; }
.mp-light { width: 22px; height: 22px; border-radius: 50%; border: 2px solid #000; }
.mp-light.white { background: #f5f5f5; }
.mp-light.red { background: var(--mp-nolift); }
.mp-light.yellow { background: #f5c518; }
.mp-light.blue { background: #2563eb; }
.mp-light.off { background: #2a2a2a; }

/* Referee-light picker buttons (colour the button when its light is selected). */
.mp-light-btn {
    border: 1px solid var(--mp-border); border-radius: 6px; padding: 0.3rem 0.55rem; cursor: pointer;
    font-weight: 700; font-size: 0.8rem; background: var(--mp-surface-2); color: var(--mp-text);
}
.mp-light-btn.selected[data-light="White"] { background: #f5f5f5; color: #111; border-color: #f5f5f5; }
.mp-light-btn.selected[data-light="Red"] { background: var(--mp-nolift); color: #fff; border-color: var(--mp-nolift); }
.mp-light-btn.selected[data-light="Yellow"] { background: #f5c518; color: #111; border-color: #f5c518; }
.mp-light-btn.selected[data-light="Blue"] { background: #2563eb; color: #fff; border-color: #2563eb; }

/* Theme tab — live board previews (scoreboard / run board / overlay) rendered in scaled-down iframes. */
.mp-theme-previews {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1rem; margin-top: 0.5rem;
}
.mp-theme-preview-label { color: var(--mp-muted); font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 0.35rem; }
.mp-theme-preview {
    position: relative; border: 1px solid var(--mp-border); border-radius: 10px; overflow: hidden;
    aspect-ratio: 16 / 9; background: #000;
}
.mp-theme-preview iframe {
    position: absolute; top: 0; left: 0; width: 400%; height: 400%; border: 0;
    transform: scale(0.25); transform-origin: 0 0; pointer-events: none;
}

/* Column-resize grips on grid headers. */
.mp-table thead th { position: relative; }
/* Border-box so a pinned column width is exact (no padding/border drift → no jump on first resize). */
.mp-table th, .mp-table td { box-sizing: border-box; }
.mp-col-grip { position: absolute; top: 0; right: 0; width: 7px; height: 100%; cursor: col-resize; user-select: none; touch-action: none; }
.mp-col-grip:hover { background: var(--mp-accent); opacity: 0.6; }
body.mp-col-resizing { cursor: col-resize; user-select: none; }

/* Big display screens */
.mp-screen { background: #000; color: #fff; min-height: 100vh; padding: 2rem; }
.mp-screen .current-lifter { font-size: 4rem; font-weight: 800; }
.mp-screen .attempt-weight { font-size: 6rem; font-weight: 900; color: var(--mp-accent); }

/* Livestream overlay: transparent background for OBS browser source */
.mp-overlay { background: transparent; color: #fff; padding: 1rem 1.5rem; }
.mp-overlay .lower-third {
    display: inline-block; background: rgba(0,0,0,0.75); border-left: 5px solid var(--mp-accent);
    padding: 0.75rem 1.25rem; border-radius: 6px;
}

/* ==== Director UI redesign (docs/specs/director-ui-spec.md) ====
   Shared primitives (visually-hidden text, an overflow disclosure, a status-dot) used by both the dashboard and
   the manage-console Overview, plus the two screens' own layout classes. Reuses --mp-* tokens and the existing
   .mp-card/.mp-btn/.mp-badge/.mp-linkbtn system throughout — no second styling framework (§4). */
.mp-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
/* Alias used by the profile/equipment components (WP6 BLOCK-2: the name previously existed only as scoped CSS
   inside ProfileImageUpload, so legends/live-regions elsewhere rendered visibly). Keep both names global. */
.mp-visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

.mp-eyebrow { color: var(--mp-accent); text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.72rem; font-weight: 800; }

/* Generic <details>/<summary> disclosure for "quiet" secondary actions (Export, More actions, card overflow) —
   keyboard-operable natively, no JS required to open/close (§4.3). */
.mp-overflow { position: relative; display: inline-block; }
.mp-overflow summary { list-style: none; cursor: pointer; }
.mp-overflow summary::-webkit-details-marker { display: none; }
.mp-overflow-menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 30; min-width: 12rem;
    display: flex; flex-direction: column; background: var(--mp-surface); border: 1px solid var(--mp-border-strong, var(--mp-border));
    border-radius: 8px; padding: 0.35rem; box-shadow: 0 10px 28px rgba(0,0,0,0.4); }
.mp-overflow-menu a, .mp-overflow-menu .mp-linkbtn { display: block; width: 100%; text-align: left; padding: 0.4rem 0.55rem;
    border-radius: 6px; color: var(--mp-text); text-decoration: none; font-size: 0.85rem; font-weight: 600; }
.mp-overflow-menu a:hover, .mp-overflow-menu .mp-linkbtn:hover { background: var(--mp-surface-2); }
.mp-overflow-menu form, .mp-overflow-menu .mp-linkbtn { margin: 0; }
.mp-danger-text.mp-linkbtn { color: var(--mp-nolift); }
.mp-icon-btn { width: 2.3rem; padding: 0 !important; }

/* ---- Meet Director dashboard (§5) ----
   meets-ui fable-spec §6.1: .mp-page-header/.mp-dash-toolbar/.mp-dash-empty/.mp-dash-noresults/.mp-dash-grid no
   longer carry a max-width:1760px page-level cap — they stretch to .mp-container's own edges (width:100%) at
   every viewport, including 4K, leaving no dead gutter. Intentional readability caps (page-header p's 46rem
   measure, the search control's own max-width) are unaffected. */
.mp-page-header { display: flex; align-items: flex-end; justify-content: space-between; gap: 1.25rem;
    flex-wrap: wrap; width: 100%; max-width: none; margin: 0 0 1.25rem; }
.mp-page-header h1 { margin: 0.2rem 0 0.35rem; font-size: clamp(1.7rem, 2.6vw, 2.4rem); letter-spacing: -0.02em; }
.mp-page-header p { max-width: 46rem; }
.mp-dash-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }

.mp-dash-toolbar { width: 100%; max-width: none; margin: 0 0 1rem; display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.mp-dash-search { flex: 1 1 240px; max-width: 30rem; }
.mp-dash-search input { width: 100%; height: 2.4rem; border-radius: 8px; border: 1px solid var(--mp-border);
    background: var(--mp-bg); color: var(--mp-text); padding: 0 0.75rem; }
/* Segmented control: supports plain <button> (dashboard, JS-toggled) and plain <a> (public meets, real
   navigation — meets-ui fable-spec §4.3, no JS owned by this work package) with identical visuals. */
.mp-segmented { display: flex; align-items: center; padding: 3px; background: var(--mp-bg); border: 1px solid var(--mp-border); border-radius: 9px; }
.mp-segmented button, .mp-segmented a { display: inline-flex; align-items: center; height: 1.9rem; padding: 0 0.7rem;
    color: var(--mp-muted); background: transparent; border: 0; text-decoration: none;
    border-radius: 6px; font-size: 0.78rem; font-weight: 750; cursor: pointer; white-space: nowrap; }
.mp-segmented button.active, .mp-segmented a.active { background: var(--mp-surface-2); color: var(--mp-text); }
.mp-dash-sort { width: 11rem; height: 2.4rem; border-radius: 8px; border: 1px solid var(--mp-border); background: var(--mp-bg); color: var(--mp-text); padding: 0 0.6rem; }

.mp-dash-empty, .mp-dash-noresults { width: 100%; max-width: none; margin: 0 0 1rem; text-align: center; padding: 2.5rem 1.5rem; }
.mp-dash-empty-icon { width: 3rem; height: 3rem; margin: 0 auto 0.75rem; border: 1px solid var(--mp-border); border-radius: 12px;
    display: grid; place-items: center; background: var(--mp-surface-2); font-size: 1.4rem; font-weight: 800; color: var(--mp-accent); }

/* auto-fill + minmax(min(100%,360px),1fr) + grid-auto-rows:1fr (meets-ui fable-spec §5.7) makes every card/tile
   in a row share the same computed row height, so Create-another-meet stretches to match its row siblings
   without a fixed min-height. */
.mp-dash-grid { width: 100%; max-width: none; margin: 0; display: grid; gap: 1rem;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr)); grid-auto-rows: 1fr; align-items: stretch; }
.mp-dash-card, .mp-dash-create-tile { background: var(--mp-surface); border: 1px solid var(--mp-border); border-radius: 13px; overflow: hidden; }
/* Six explicit row tracks (meets-ui fable-spec §5.7): top, meta, kpis, progress, a flexible spacer (.mp-dash-spacer,
   an explicit empty row so it — not the footer — absorbs the leftover height), then the footer pinned to the
   card's bottom edge regardless of how much content the other rows carry. */
.mp-dash-card { display: grid; grid-template-rows: auto auto auto auto 1fr auto; height: 100%; min-height: 374px; }

/* Composite header (meets-ui fable-spec §5.4): the title link reserves an explicit fixed-height 25px badge track
   + 10px gap + 2.56em two-line title track — regardless of whether the name naturally wraps to one or two lines —
   so `.mp-dash-card-meta` (now this row's sibling, not its child; see §5.2) always begins at the same
   parent-relative offset. The 40px second column reserves the overflow control's slot even when a given card
   renders no overflow menu, so every card's title column starts/ends at the same x-offset too. */
.mp-dash-card-top { display: grid; grid-template-columns: minmax(0, 1fr) 40px; align-items: start; column-gap: 12px;
    padding: 1.1rem 1.1rem 0; }
.mp-dash-card-link { display: grid; grid-template-rows: 25px 2.56em; row-gap: 10px; min-width: 0;
    text-decoration: none; color: inherit; border-radius: 6px; }
.mp-dash-card-link:focus-visible { outline: 2px solid var(--mp-accent); outline-offset: 3px; }
.mp-dash-card-title {
    display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    line-height: 1.28;
    /* 2 × 1.28 line-height: explicit block-size (not just min/max-block-size) forces the track to reserve two
       lines even when the rendered title only occupies one — a browser may otherwise size the row from the
       single rendered line despite a min-block-size alone. */
    block-size: 2.56em; min-block-size: 2.56em; max-block-size: 2.56em;
    margin: 0; font-size: 1.12rem; font-weight: 800; letter-spacing: -0.015em; color: var(--mp-text);
}
/* Sibling of .mp-dash-card-top (§5.2), not nested inside it — metadata no longer competes with the title/overflow
   row for horizontal space, and its top offset is now purely a function of the title-link's fixed track sizes
   above, identical for a one-line and a naturally two-line title. */
.mp-dash-card-meta { display: flex; flex-wrap: wrap; gap: 0.25rem 0.85rem; font-size: 0.75rem; padding: 0.55rem 1.1rem 0; }
.mp-dash-kpis { display: grid; grid-template-columns: repeat(3, 1fr); margin: 0.6rem 1.1rem 0.9rem; border: 1px solid var(--mp-border); border-radius: 10px; overflow: hidden; }
.mp-dash-kpis > div { padding: 0.6rem 0.65rem; background: rgba(0,0,0,0.12); border-right: 1px solid var(--mp-border); }
.mp-dash-kpis > div:last-child { border-right: 0; }
.mp-dash-kpis strong { display: block; overflow: hidden; font-size: 0.95rem; letter-spacing: -0.01em; text-overflow: ellipsis; white-space: nowrap; }
.mp-dash-kpis span { display: block; color: var(--mp-muted); font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 750; }
.mp-dash-progress { margin: 0 1.1rem 0.9rem; }
.mp-dash-progress-label { display: flex; justify-content: space-between; color: var(--mp-muted); font-size: 0.7rem; margin-bottom: 0.4rem; }
.mp-dash-progress-bar { height: 6px; border-radius: 999px; background: var(--mp-bg); overflow: hidden; }
.mp-dash-progress-bar i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--mp-accent), #ffd76a); }
/* Explicit empty grid row (the 5th `1fr` track above) — grows/shrinks so .mp-dash-foot always lands on the
   card's last (auto) row instead of being stretched itself. */
.mp-dash-spacer { min-height: 0; }
.mp-dash-foot { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; padding: 0.75rem 1.1rem; border-top: 1px solid var(--mp-border); background: rgba(0,0,0,0.12); flex-wrap: wrap; }
.mp-dash-quick { display: flex; gap: 0.85rem; flex-wrap: wrap; }
.mp-dash-quick a { color: var(--mp-muted); text-decoration: none; font-size: 0.75rem; font-weight: 700; }
.mp-dash-quick a:hover { color: var(--mp-text); }
/* Create-another-meet tile (§5.8): one anchor, same border-radius/surface/min-height/height:100% contract as
   .mp-dash-card, so it stretches to the same computed row height under .mp-dash-grid's grid-auto-rows:1fr — the
   old fixed min-height:14rem sizing mechanism is gone. Centered via its own 5-row grid (spacer/icon/title/copy/
   spacer), matching the reference mock's .create-card. */
.mp-dash-create-tile { display: grid; grid-template-rows: 1fr auto auto auto 1fr; align-items: center; justify-items: center;
    height: 100%; min-height: 374px; text-align: center; padding: 1.5rem; text-decoration: none; color: var(--mp-text); border-style: dashed; }
.mp-dash-create-tile:hover { border-color: var(--mp-accent); }
.mp-dash-create-tile .mp-dash-empty-icon { grid-row: 2; margin: 0 0 0.4rem; }
.mp-dash-create-tile h3 { grid-row: 3; margin: 0; font-size: 1.05rem; letter-spacing: -0.01em; }
.mp-dash-create-tile .mp-muted { grid-row: 4; max-width: 15rem; margin: 0.4rem 0 0; }
[data-dashboard-card][hidden] { display: none; }

@media (max-width: 899px) {
    /* flex-wrap:nowrap must ride along with the column switch (here and on .mp-public-toolbar below): in a
       column container that still allows WRAPPING, each flex line is as wide as its widest item's intrinsic
       width — and .mp-segmented is a scroll strip whose intrinsic width ignores its own overflow-x, so once
       its status counts reach three digits ("All · 300") it is intrinsically wider than a phone viewport and
       align-items:stretch widens every sibling past the page edge with it. A single-line column instead
       clamps stretched children to the container and lets the strip scroll within itself. */
    .mp-page-header, .mp-dash-toolbar { flex-direction: column; align-items: stretch; flex-wrap: nowrap; }
    .mp-dash-actions .mp-btn { flex: 1; }
    .mp-dash-search { max-width: none; flex: 0 0 auto; }
    .mp-dash-grid { grid-template-columns: 1fr; }
}

/* ---- Public meets (meets-ui fable-spec §4) ----
   Dedicated .mp-public-* selectors (spec §7) instead of overloading the generic .mp-grid/.mp-card classes other
   unrelated pages still use. Reuses --mp-* tokens and the existing .mp-btn/.mp-badge/.mp-segmented/.mp-overflow
   system throughout — no second styling framework. .mp-public-meet-grid deliberately mirrors .mp-dash-grid's
   auto-fill/minmax(min(100%,360px),1fr)/grid-auto-rows:1fr recipe (§5.7) for the same equal-row-height guarantee. */
.mp-public-page { width: 100%; }

.mp-public-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; width: 100%; margin: 0 0 1rem; }
/* position:relative lives on the FORM (not the inner .mp-public-search span) because the submit button is the
   form's last child, a sibling of the span — not nested inside it. */
.mp-public-search-form { position: relative; flex: 1 1 240px; max-width: 30rem; min-width: 0; }
.mp-public-search { display: block; }
.mp-public-search input[type="search"] { width: 100%; height: 2.6rem; border-radius: 9px; border: 1px solid var(--mp-border);
    background: var(--mp-bg); color: var(--mp-text); padding: 0 2.5rem 0 0.85rem; }
.mp-public-search-submit { position: absolute; right: 0.3rem; top: 50%; transform: translateY(-50%);
    width: 2rem; height: 2rem; display: grid; place-items: center; background: transparent; border: 0;
    border-radius: 6px; color: var(--mp-muted); cursor: pointer; }
.mp-public-search-submit:hover { color: var(--mp-text); background: var(--mp-surface-2); }
.mp-public-search-submit svg { width: 16px; height: 16px; }
.mp-public-sort-form { flex: 0 0 auto; }

.mp-public-result-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem;
    margin: 0.25rem 0.15rem 0.85rem; color: var(--mp-muted); font-size: 0.78rem; }
.mp-public-result-row strong { color: var(--mp-text); }

.mp-public-meet-grid { width: 100%; display: grid; gap: clamp(14px, 1vw, 20px);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr)); grid-auto-rows: 1fr; align-items: stretch; }

.mp-public-meet-card { display: grid; grid-template-rows: auto minmax(92px, 1fr) auto; height: 100%; min-height: 340px;
    min-width: 0; padding: 1.15rem; border: 1px solid var(--mp-border); border-radius: 13px; background: var(--mp-surface); }

/* Composite header (meets-ui fable-spec §5.4, the same fixed-track contract applied to director cards): a fixed
   25px status track + a fixed 15px gap + a fixed 2.56em two-line title track, so `.mp-public-meet-meta` always
   begins at the same offset from the top of its own parent card, whether the meet name naturally occupies one
   line ("Canterbury Raw Open") or wraps to two. */
.mp-public-meet-head { display: grid; grid-template-rows: 25px 2.56em; row-gap: 15px; min-width: 0; }
.mp-public-meet-status { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; min-width: 0; }
.mp-public-meet-time { overflow: hidden; color: var(--mp-muted); font-size: 0.72rem; font-weight: 750; text-overflow: ellipsis; white-space: nowrap; }
.mp-public-meet-title {
    display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    line-height: 1.28;
    block-size: 2.56em; min-block-size: 2.56em; max-block-size: 2.56em;
    margin: 0; font-size: 1.15rem; font-weight: 850; letter-spacing: -0.02em; color: var(--mp-text); text-decoration: none;
}
.mp-public-meet-title:hover { text-decoration: underline; }
.mp-public-meet-title:focus-visible { outline: 2px solid var(--mp-accent); outline-offset: 3px; border-radius: 4px; }

/* The flexible `minmax(92px,1fr)` row on .mp-public-meet-card lives HERE (not as a separate spacer element) —
   align-content:start pins the detail rows to the top of that row while its own leftover height absorbs the
   difference between cards, pushing every card's footer to the same bottom edge (§4.4). */
.mp-public-meet-meta { display: grid; align-content: start; gap: 0.55rem; min-width: 0; padding-block: 0.95rem 0; }
.mp-public-meet-detail { display: grid; grid-template-columns: 18px minmax(0, 1fr); align-items: center; gap: 0.5rem;
    min-width: 0; color: var(--mp-muted); font-size: 0.78rem; line-height: 1.35; }
.mp-public-meet-detail svg { width: 15px; height: 15px; color: var(--mp-muted); flex: 0 0 auto; }
.mp-public-meet-detail span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Action footer (§4.5): equal-width two-column grid; a lone action or the 3rd action (when Livestream + Live
   scoreboard are both present) spans both columns. Every rendered control shares the same min-height. */
.mp-public-meet-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem;
    min-width: 0; padding-block-start: 0.95rem; border-top: 1px solid var(--mp-border); }
.mp-public-meet-actions .mp-btn { width: 100%; min-width: 0; min-height: 44px; padding-inline: 0.65rem; }
.mp-public-meet-actions .mp-overflow { display: block; width: 100%; min-width: 0; }
.mp-public-meet-actions > *:first-child:last-child { grid-column: 1 / -1; }
.mp-public-meet-actions > *:nth-child(3) { grid-column: 1 / -1; }

.mp-btn.stream { display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
    background: color-mix(in srgb, var(--mp-nolift) 16%, var(--mp-surface-2));
    border: 1px solid color-mix(in srgb, var(--mp-nolift) 45%, var(--mp-border)); color: #ffb5b9; }
.mp-btn.stream:hover { border-color: var(--mp-nolift); background: color-mix(in srgb, var(--mp-nolift) 24%, var(--mp-surface-2)); }
.mp-btn.stream svg { width: 14px; height: 14px; flex: 0 0 auto; }

/* Dedicated action grid for the public meet detail page's Watch card (§4.6) — replaces inline margin-left
   spacing between Scoreboard/Warm-up room/Results/Livestream. */
.mp-watch-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 0.75rem; }
.mp-watch-actions .mp-overflow { display: inline-block; }
/* PublicMeet.razor's own named selectors, replacing the page's former inline `style="margin:..."` attributes. */
.mp-meet-detail-title { margin: 0.4rem 0; }
.mp-meet-detail-grid { margin-top: 1rem; }

@media (max-width: 899px) {
    /* flex-wrap:nowrap for the same reason as .mp-dash-toolbar's column switch above: without it, the
       wrapped-column line takes .mp-segmented's intrinsic (unscrolled) width once its counts reach three
       digits, and every stretched sibling overflows the page with it. */
    .mp-public-toolbar { flex-direction: column; align-items: stretch; flex-wrap: nowrap; }
    .mp-public-search-form, .mp-public-sort-form { max-width: none; }
    .mp-public-sort-form select { width: 100%; }
    .mp-segmented { overflow-x: auto; }
}

@media (max-width: 480px) {
    .mp-public-meet-actions { grid-template-columns: 1fr; }
    .mp-public-meet-actions > *:nth-child(3) { grid-column: auto; }
    .mp-watch-actions .mp-btn { width: 100%; }
}

/* ---- Manage console: shared context header + tab strip (§6.1) ---- */
.mp-crumbs { color: var(--mp-muted); font-size: 0.78rem; }
.mp-crumbs span { margin: 0 0.4rem; }
.mp-meet-hero { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; flex-wrap: wrap; }
.mp-meet-hero h1 { margin: 0.2rem 0 0.3rem; font-size: clamp(1.5rem, 2.2vw, 1.9rem); letter-spacing: -0.02em; }
.mp-meet-hero-actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.mp-meet-tabs { display: flex; align-items: center; gap: 2px; padding: 5px;
    background: var(--mp-surface); border: 1px solid var(--mp-border); border-radius: 10px; overflow-x: auto; }
.mp-meet-tabs a { flex: none; padding: 0.55rem 0.8rem; border-radius: 8px; font-size: 0.78rem; font-weight: 750;
    color: var(--mp-muted); text-decoration: none; white-space: nowrap; }
.mp-meet-tabs a.active { color: var(--mp-text); background: var(--mp-surface-3, var(--mp-surface-2)); }
@media (max-width: 899px) {
    .mp-meet-hero { flex-direction: column; align-items: flex-start; }
    .mp-meet-hero-actions { width: 100%; }
    .mp-meet-hero-actions .mp-btn { flex: 1; }
}

/* ---- Manage Overview (§6.2–§6.7) ---- */
.mp-overview-toolbar { display: flex; justify-content: flex-end; }
.mp-overview-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 1rem; align-items: stretch; }
.mp-overview-grid .mp-card { margin-bottom: 0; }
.mp-readiness-card { grid-column: span 8; padding: 1.4rem; display: grid; grid-template-columns: auto 1fr; gap: 1.4rem; align-items: center; }
.mp-ring { --p: 0%; width: 5.5rem; aspect-ratio: 1; border-radius: 50%; display: grid; place-items: center;
    background: conic-gradient(var(--mp-accent) var(--p), var(--mp-surface-2) 0); position: relative; }
.mp-ring::before { content: ""; width: 4.2rem; aspect-ratio: 1; border-radius: 50%; background: var(--mp-surface); position: absolute; }
.mp-ring strong { position: relative; font-size: 1.2rem; }
.mp-readiness-copy h2 { margin: 0 0 0.4rem; font-size: 1.25rem; }
.mp-readiness-copy p { max-width: 40rem; }
.mp-readiness-copy .mp-btn { margin-top: 0.75rem; }
.mp-lifecycle-card { grid-column: span 4; padding: 1.1rem 1.25rem; display: flex; flex-direction: column; justify-content: space-between; gap: 0.75rem; }
.mp-lifecycle-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; }
.mp-lifecycle-stage { margin-top: 0.4rem; }
.mp-timeline { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; margin-top: 0.5rem; }
.mp-timeline span { display: block; height: 4px; border-radius: 99px; background: var(--mp-surface-2); }
.mp-timeline span.done { background: var(--mp-good); }
.mp-timeline span.current { background: var(--mp-accent); }
.mp-timeline-labels { display: flex; justify-content: space-between; font-size: 0.68rem; margin-top: 0.4rem; }
.mp-lifecycle-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.mp-stat-strip { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(6, 1fr); overflow: hidden; padding: 0; }
.mp-stat-box { min-height: 5.6rem; padding: 0.95rem 1rem; border-right: 1px solid var(--mp-border); }
.mp-stat-box:last-child { border-right: 0; }
.mp-stat-box strong { display: block; font-size: 1.3rem; letter-spacing: -0.02em; }
.mp-stat-box span { color: var(--mp-muted); font-size: 0.68rem; }
.mp-stat-box.alert strong { color: var(--mp-nolift); }
.mp-tasks { grid-column: span 7; }
.mp-board { grid-column: span 5; }
.mp-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; padding-bottom: 0.6rem; border-bottom: 1px solid var(--mp-border); margin-bottom: 0.35rem; }
.mp-card-head h2 { margin: 0; font-size: 1.05rem; }
.mp-card-head p { margin-top: 0.25rem; font-size: 0.8rem; }

/* Readiness checklist rows. */
.mp-checklist-item { display: grid; grid-template-columns: 1.6rem minmax(0,1fr) auto; gap: 0.75rem; align-items: center; padding: 0.7rem 0; border-bottom: 1px solid var(--mp-border); }
.mp-checklist-item:last-child { border-bottom: 0; }
.mp-checklist-mark { width: 1.6rem; height: 1.6rem; border-radius: 7px; display: grid; place-items: center;
    background: var(--mp-surface-2); border: 1px solid var(--mp-border); color: var(--mp-muted); font-size: 0.72rem; font-weight: 800; }
.mp-checklist-mark.done { color: #08261a; background: var(--mp-good); border-color: var(--mp-good); }
.mp-checklist-mark.blocking { color: var(--mp-nolift); border-color: var(--mp-nolift); }
.mp-checklist-mark.recommended { color: var(--mp-accent); border-color: var(--mp-accent); }
.mp-checklist-body strong { display: block; font-size: 0.85rem; }
.mp-checklist-body p { color: var(--mp-muted); font-size: 0.72rem; margin-top: 0.15rem; }
.mp-checklist-item.done { opacity: 0.75; }
.mp-checklist-item a { color: var(--mp-accent-2, var(--mp-accent)); text-decoration: none; font-size: 0.78rem; font-weight: 800; white-space: nowrap; }
.mp-checklist-state { font-size: 0.75rem; white-space: nowrap; }

/* Boards & displays launcher. */
.mp-board-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.mp-board-row { display: grid; grid-template-columns: 2.2rem minmax(0,1fr) auto auto; gap: 0.6rem; align-items: center; padding: 0.4rem 0.35rem; border-radius: 9px; }
.mp-board-row:hover { background: var(--mp-surface-2); }
.mp-board-icon { width: 2.2rem; height: 2.2rem; border-radius: 8px; display: grid; place-items: center; background: var(--mp-surface-2); color: var(--mp-accent); }
.mp-board-link { min-width: 0; text-decoration: none; color: var(--mp-text); }
.mp-board-link:focus-visible { outline: 2px solid var(--mp-accent); outline-offset: 2px; }
.mp-board-link strong { display: block; font-size: 0.85rem; }
.mp-board-link span { display: block; color: var(--mp-muted); font-size: 0.72rem; margin-top: 0.1rem; }
.mp-board-copy-status { font-size: 0.68rem; color: var(--mp-good); min-width: 0; }
.mp-board-copy { border: 0; background: transparent; color: var(--mp-muted); cursor: pointer; padding: 0.4rem; border-radius: 7px; }
.mp-board-copy:hover { background: var(--mp-surface-3, var(--mp-surface-2)); color: var(--mp-text); }
.mp-board-copy.mp-copied { color: var(--mp-good); }

@media (max-width: 1439px) {
    .mp-readiness-card, .mp-tasks { grid-column: span 7; }
    .mp-lifecycle-card, .mp-board { grid-column: span 5; }
}
@media (max-width: 899px) {
    .mp-overview-grid { grid-template-columns: 1fr; }
    .mp-overview-grid > * { grid-column: 1 / -1; }
    .mp-readiness-card { grid-template-columns: auto 1fr; }
    .mp-stat-strip { grid-template-columns: repeat(2, 1fr); }
    .mp-stat-box { border-right: 0; border-bottom: 1px solid var(--mp-border); }
}

/* ---- Phone-first pass: /my/meets/{id} (docs/ARCHITECTURE-GAP-PLAN.md §12 Phase 7) ---- */
/* Scoped to .mp-mymeet (the lifter's own meet-day page) rather than globally — the meet-day boards (run board,
   scoreboard) reuse the same .mp-btn/.form-control/.mp-grid classes at operator-console density and must not
   grow bigger tap targets on a scoring-table screen. */
.mp-mymeet { min-width: 0; }
.mp-mymeet .mp-card { min-width: 0; overflow-wrap: anywhere; }
/* Tables can be wider than a phone screen (4 attempt columns) — scroll INSIDE the card, never the page. */
.mp-mymeet table.mp-table { min-width: 22rem; }
.mp-mymeet div:has(> table.mp-table) { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Attempt/rack-height inputs and every button get a real thumb-sized tap target (>=44px, per WCAG 2.5.5). */
.mp-mymeet input.form-control, .mp-mymeet select.form-control { min-height: 44px; font-size: 1rem; box-sizing: border-box; }
.mp-mymeet .mp-btn { min-height: 44px; padding: 0.65rem 1.2rem; font-size: 1rem; box-sizing: border-box; }
.mp-mymeet .mp-withdraw-card { padding: 0.75rem 1.4rem; }
.mp-mymeet .mp-withdraw-card .mp-btn { width: 100%; }
.mp-target-row { margin: 0.3rem 0; line-height: 1.5; }
.mp-target-row:first-child { margin-top: 0; }
.mp-target-row:last-child { margin-bottom: 0; }
@media (max-width: 480px) {
    /* Single column: the two-up "Declare attempt / Rack heights" grid stacks, and every full-bleed action button
       spans the full width so it's an easy thumb target instead of a half-width phone-unfriendly strip. */
    .mp-mymeet .mp-grid { grid-template-columns: 1fr; }
    .mp-mymeet .mp-btn { width: 100%; }
    .mp-mymeet h1 { font-size: 1.5rem; }
}

/* ---- Async page-state (PageLoadState.razor): spinner + shimmer skeleton ---- */
.mp-load { display: flex; align-items: center; gap: 0.5rem; margin: 0.75rem 0; }
.mp-load-spinner {
    width: 18px; height: 18px; border: 2px solid var(--mp-border); border-top-color: var(--mp-accent);
    border-radius: 50%; animation: mp-spin 0.8s linear infinite;
}
@keyframes mp-spin { to { transform: rotate(360deg); } }
.mp-skel { display: flex; flex-direction: column; gap: 0.55rem; margin-top: 0.75rem; }
.mp-skel-bar {
    height: 1.1rem; border-radius: 6px; width: 100%;
    background: linear-gradient(90deg, var(--mp-surface) 25%, color-mix(in srgb, var(--mp-text) 8%, var(--mp-surface)) 37%, var(--mp-surface) 63%);
    background-size: 400% 100%; animation: mp-shimmer 1.4s ease infinite;
}
@keyframes mp-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
.mp-skel-title { height: 1.6rem; width: 40%; }
.mp-load-error strong { color: var(--mp-nolift); display: block; margin-bottom: 0.25rem; }
.mp-load-error a { margin-top: 0.5rem; display: inline-flex; }

/* ---- Configurable entry form (WP3 §6.1): the Setup-tab editor and the public /enter form share these classes
   so the live preview and the real entrant-facing form read identically. ---- */
.mp-entry-editor .mp-setup-head { align-items: center; }
.mp-entry-warning {
    background: color-mix(in srgb, var(--mp-accent) 12%, var(--mp-surface)); border: 1px solid var(--mp-accent);
    border-radius: 8px; padding: 0.6rem 0.9rem; font-size: 0.85rem; margin: 0.5rem 0 0.75rem;
}
.mp-entry-table { margin-top: 0.5rem; }
.mp-entry-table td, .mp-entry-table th { vertical-align: top; }
.mp-entry-field { margin: 0 0 0.85rem; }
.mp-entry-field label { display: block; font-size: 0.8rem; margin-bottom: 0.2rem; }
.mp-entry-help { color: var(--mp-muted); font-size: 0.78rem; margin: -0.05rem 0 0.3rem; }
.mp-entry-checks { display: flex; flex-direction: column; gap: 0.25rem; margin: 0.2rem 0; }
.mp-entry-check { display: flex; align-items: center; gap: 0.4rem; font-size: 0.9rem; font-weight: 400; }
.mp-entry-none { margin-top: 0.35rem; color: var(--mp-muted); }
.mp-entry-error { color: var(--mp-nolift); font-size: 0.8rem; margin-top: 0.25rem; }
.mp-entry-preview {
    border: 1px dashed var(--mp-border); border-radius: 10px; padding: 0.85rem 1rem; margin-top: 0.4rem;
    background: color-mix(in srgb, var(--mp-bg) 60%, transparent);
}
.mp-entry-preview .mp-entry-field:last-child { margin-bottom: 0; }

/* ---- OpenPowerlifting import (WP4 §7.3): Setup-tab "Import livestream data" panel. ---- */
.mp-opl-preflight { display: flex; gap: 1.25rem; flex-wrap: wrap; margin: 0.5rem 0; }
.mp-opl-stat { display: flex; flex-direction: column; align-items: flex-start; min-width: 5.5rem; }
.mp-opl-stat-n { font-size: 1.4rem; font-weight: 800; line-height: 1.1; }
.mp-opl-source-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin-top: 0.5rem; }
@media (max-width: 720px) { .mp-opl-source-grid { grid-template-columns: 1fr; } }
.mp-opl-jobhead { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin: 0.6rem 0; }
.mp-opl-processing { color: var(--mp-muted); }
.mp-opl-table td, .mp-opl-table th { vertical-align: top; }
.mp-opl-table select.form-control { min-width: 14rem; }
.mp-opl-attrib { margin-top: 1rem; font-size: 0.72rem; }

/* ==== WP4 (§7): Setup lower half — section index + entry-form builder + compact tool panels ==== */
.mp-badge.warn { color: var(--mp-accent); border-color: var(--mp-accent); }
.mp-form-ok { color: var(--mp-good); font-weight: 600; }
.mp-form-err { color: var(--mp-nolift); font-weight: 600; }

/* ---- §7.1 Section index: sticky rail on desktop, horizontal strip on mobile ---- */
.mp-setup-lower { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 1rem; align-items: start; margin-top: 1rem; }
.mp-setup-tools { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.mp-setup-tools .mp-card { margin-bottom: 0; }
/* min-width: 0 — without it this grid item's automatic minimum size is its min-content width, which on the mobile
   tier below is the whole un-collapsed row of index links (~617px) and floors the column, and so the page, wider
   than the viewport. The nav's own overflow-x makes it a scroll container, which zeroes the automatic minimum of a
   flex/grid ITEM — but the nav is a normal-flow block here, so it still reports that width as its min-content
   contribution up to this aside. Fixing it has to happen on the grid item (here) or the track (below). */
.mp-setup-index { position: sticky; top: 0.75rem; padding: 0.75rem; min-width: 0; }
.mp-setup-index-nav { display: flex; flex-direction: column; gap: 0.25rem; }
.mp-setup-index-nav a { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
    padding: 0.5rem 0.6rem; border-radius: 8px; color: var(--mp-text); text-decoration: none; border: 1px solid transparent; }
.mp-setup-index-nav a:hover { background: color-mix(in srgb, var(--mp-accent) 12%, var(--mp-surface)); border-color: var(--mp-border); }
.mp-setup-index-label { font-weight: 600; font-size: 0.9rem; }
.mp-setup-index-help { font-size: 0.75rem; margin: 0.6rem 0 0; }
@media (max-width: 900px) {
    /* minmax(0, 1fr), not 1fr: the single mobile column must never be floored by its items' min-content. */
    .mp-setup-lower { grid-template-columns: minmax(0, 1fr); }
    .mp-setup-index { position: static; }
    .mp-setup-index-nav { flex-direction: row; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .mp-setup-index-nav a { flex: 0 0 auto; flex-direction: column; align-items: flex-start; }
    .mp-setup-index-help { display: none; }
}

/* ---- §7.2 Builder header ---- */
.mp-builder-head { align-items: flex-start; }
.mp-builder-title { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.mp-builder-title h3 { margin: 0; }
.mp-builder-sub { flex: 1 1 100%; font-size: 0.82rem; margin: 0.15rem 0 0; }
.mp-builder-actions { margin-left: auto; display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

/* ---- §7.2/§7.5 Two-pane body: ordered field list + live preview ---- */
.mp-builder-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 400px); gap: 1.25rem; align-items: start; }
@media (max-width: 1080px) { .mp-builder-body { grid-template-columns: 1fr; } }
.mp-fields { min-width: 0; }
/* A flex-wrap row (not a rigid grid) so the field name never collapses to zero width when the pane is narrow —
   the source/requirement/entries/menu controls wrap under the name instead. */
.mp-field-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.7rem;
    padding: 0.6rem 0.2rem; border-bottom: 1px solid var(--mp-border); }
.mp-field-reorder { flex: 0 0 auto; display: flex; flex-direction: column; gap: 0.15rem; }
.mp-field-reorder form { line-height: 0; }
.mp-icon-btn { background: var(--mp-surface-2); color: var(--mp-text); border: 1px solid var(--mp-border);
    border-radius: 6px; width: 1.7rem; height: 1.35rem; font-size: 0.7rem; cursor: pointer; padding: 0;
    display: inline-flex; align-items: center; justify-content: center; }
.mp-icon-btn:hover { border-color: var(--mp-accent); color: var(--mp-accent); }
.mp-field-name { flex: 1 1 12rem; min-width: 9rem; }
.mp-field-name strong { display: flex; align-items: center; gap: 0.4rem; font-size: 0.92rem; }
.mp-field-name .mp-badge { font-size: 0.6rem; padding: 0.05rem 0.35rem; }
.mp-field-meta { display: block; font-size: 0.75rem; }
.mp-field-source { flex: 0 0 auto; font-size: 0.8rem; min-width: 4.5rem; }
.mp-req-seg, .mp-field-entries { flex: 0 0 auto; }

/* Three-state requirement control (Hidden / Optional / Required) as an accessible segmented radio group. */
.mp-req-seg { display: inline-flex; border: 1px solid var(--mp-border); border-radius: 8px; overflow: hidden; }
.mp-req-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.mp-req-label { padding: 0.28rem 0.55rem; font-size: 0.78rem; cursor: pointer; color: var(--mp-muted);
    border-left: 1px solid var(--mp-border); user-select: none; }
.mp-req-label:first-of-type { border-left: 0; }
.mp-req-input:checked + .mp-req-label { background: var(--mp-accent); color: #1a1300; font-weight: 700; }
.mp-req-input:focus-visible + .mp-req-label { outline: 2px solid var(--mp-accent); outline-offset: -2px; }
.mp-req-locked { padding: 0.28rem 0.55rem; font-size: 0.78rem; color: var(--mp-muted); }

/* "Show on Entries page" toggle line. */
.mp-toggle-line { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; cursor: pointer;
    color: var(--mp-muted); }
.mp-toggle-line input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.mp-toggle { width: 1.8rem; height: 1rem; border-radius: 999px; background: var(--mp-surface-2);
    border: 1px solid var(--mp-border); position: relative; flex: 0 0 auto; transition: background 0.12s; }
.mp-toggle::after { content: ""; position: absolute; top: 1px; left: 1px; width: 0.8rem; height: 0.8rem;
    border-radius: 50%; background: var(--mp-muted); transition: transform 0.12s, background 0.12s; }
.mp-toggle-line.on { color: var(--mp-text); }
.mp-toggle-line.on .mp-toggle { background: color-mix(in srgb, var(--mp-accent) 55%, var(--mp-surface)); border-color: var(--mp-accent); }
.mp-toggle-line.on .mp-toggle::after { transform: translateX(0.8rem); background: var(--mp-accent); }
.mp-field-entries input:focus-visible + .mp-toggle { outline: 2px solid var(--mp-accent); outline-offset: 1px; }

/* Advanced per-field settings (public label, help text, options, explicit None, remove). */
.mp-field-adv { flex: 0 0 auto; margin-left: auto; }
.mp-field-adv[open] { flex: 1 1 100%; margin-left: 0; }
.mp-field-adv > summary { list-style: none; }
.mp-field-adv > summary::-webkit-details-marker { display: none; }
.mp-field-adv-body { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 0.35rem;
    margin: 0.5rem 0 0.2rem; padding: 0.7rem 0.85rem; background: var(--mp-bg); border: 1px solid var(--mp-border);
    border-radius: 8px; }
.mp-field-adv-body label.mp-muted { font-size: 0.75rem; }
.mp-field-adv-body .form-control { max-width: 26rem; }
.mp-field-adv-body form { margin-top: 0.2rem; }

/* Builder footer: add-field / form-options panels + save-draft. */
.mp-builder-foot { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-start; margin-top: 0.85rem; }
.mp-tool-panel { border: 1px solid var(--mp-border); border-radius: 8px; }
.mp-tool-panel[open] { flex: 1 1 100%; padding: 0.2rem 0.85rem 0.85rem; }
.mp-tool-panel > summary { display: inline-block; list-style: none; margin: 0; }
.mp-tool-panel > summary::-webkit-details-marker { display: none; }
.mp-tool-panel:not([open]) { border: 0; }
.mp-builder-save { margin-left: auto; display: flex; align-items: center; gap: 0.6rem; }
.mp-builder-savenote { font-size: 0.78rem; }
.mp-form-options { display: flex; flex-direction: column; gap: 0.6rem; max-width: 32rem; }
.mp-form-dep { background: color-mix(in srgb, var(--mp-accent) 8%, var(--mp-surface));
    border: 1px solid var(--mp-border); border-radius: 8px; padding: 0.5rem 0.7rem; }
.mp-form-dep-note { font-size: 0.82rem; }
/* Custom-field options input appears only for select types (pure-CSS :has, no interactivity). */
.mp-cf-options { display: none; }
.mp-cf-panel:has(.mp-cf-type option[value="SingleSelect"]:checked) .mp-cf-options,
.mp-cf-panel:has(.mp-cf-type option[value="MultiSelect"]:checked) .mp-cf-options { display: block; }

/* ---- §7.5 Live preview pane ---- */
.mp-preview { position: sticky; top: 0.75rem; border: 1px solid var(--mp-border); border-radius: 12px; padding: 0.85rem; background: var(--mp-surface); }
@media (max-width: 1080px) { .mp-preview { position: static; } }
.mp-vis-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.mp-preview-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.6rem; }
.mp-preview-head h4 { margin: 0; }
.mp-preview-mode { font-size: 0.75rem; }
.mp-seg { display: inline-flex; border: 1px solid var(--mp-border); border-radius: 8px; overflow: hidden; }
.mp-seg label { padding: 0.28rem 0.6rem; font-size: 0.78rem; cursor: pointer; color: var(--mp-muted); border-left: 1px solid var(--mp-border); }
.mp-seg label:first-of-type { border-left: 0; }
#mp-pw-desktop:checked ~ .mp-preview-head .mp-seg label[for="mp-pw-desktop"],
#mp-pw-mobile:checked ~ .mp-preview-head .mp-seg label[for="mp-pw-mobile"] { background: var(--mp-accent); color: #1a1300; font-weight: 700; }
#mp-pw-desktop:focus-visible ~ .mp-preview-head .mp-seg label[for="mp-pw-desktop"],
#mp-pw-mobile:focus-visible ~ .mp-preview-head .mp-seg label[for="mp-pw-mobile"] { outline: 2px solid var(--mp-accent); outline-offset: -2px; }
.mp-preview-window { transition: max-width 0.15s ease; }
#mp-pw-mobile:checked ~ .mp-preview-window { max-width: 390px; margin-inline: auto; }
.mp-preview-mode::after { content: " · desktop width"; }
#mp-pw-mobile:checked ~ .mp-preview-head .mp-preview-mode::after { content: " · mobile width"; }
.mp-preview-title { display: flex; flex-direction: column; margin-bottom: 0.6rem; }
.mp-preview-title span { font-size: 0.75rem; }

/* ---- §7.6 Compact "at rest" tool panels (livestream import, record book) ---- */
.mp-tool-disclosure > summary { list-style: none; cursor: pointer; }
.mp-tool-disclosure > summary::-webkit-details-marker { display: none; }
.mp-compact-row { display: flex; align-items: flex-start; gap: 0.85rem; padding: 0.15rem 0; }
.mp-compact-icon { flex: 0 0 auto; width: 2.2rem; height: 2.2rem; border-radius: 8px; display: flex; align-items: center;
    justify-content: center; background: var(--mp-surface-2); border: 1px solid var(--mp-border); font-size: 1.1rem; }
.mp-compact-main { flex: 1 1 auto; min-width: 0; }
.mp-compact-main h3 { margin: 0; }
.mp-compact-main p { margin: 0.15rem 0 0.4rem; font-size: 0.82rem; }
.mp-compact-meta { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; font-size: 0.8rem; }
.mp-compact-cue { flex: 0 0 auto; align-self: center; }
.mp-tool-disclosure[open] .mp-compact-cue { display: none; }
.mp-tool-disclosure[open] .mp-compact-row { border-bottom: 1px solid var(--mp-border); padding-bottom: 0.7rem; margin-bottom: 0.2rem; }
.mp-tool-detail { padding-top: 0.4rem; }

/* ---- Entries tab (director-ui-spec §8) — reuses the shared .mp-* tokens and the WP2 .mp-data-grid/.mp-dg-*
   foundation as-is; only Entries-specific chrome (counts, payment banner, chips, column chooser, row menu, edit
   drawer) is defined here. Rows hidden by the global search / status chips use !important so they win over the
   inline display data-grid.js sets for its own per-column filters (the two compose). */
.mp-e-filtered-out { display: none !important; }

.mp-e-flash { padding: 0.5rem 0.8rem; }
.mp-e-header { display: flex; justify-content: flex-end; margin-bottom: 0.75rem; }
.mp-e-header-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

/* Payment banner (§8.2) — a compact <details> whose summary is the status line. */
.mp-e-pay-banner { padding: 0; margin-bottom: 0.9rem; overflow: hidden; }
.mp-e-pay-banner > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 0.7rem; padding: 0.7rem 0.9rem; }
.mp-e-pay-banner > summary::-webkit-details-marker { display: none; }
.mp-e-pay-banner.is-ok { border-color: color-mix(in srgb, var(--mp-good) 45%, var(--mp-border)); }
.mp-e-pay-banner.is-warn { border-color: color-mix(in srgb, var(--mp-accent) 55%, var(--mp-border)); }
.mp-e-pay-icon { flex: 0 0 auto; width: 1.5rem; height: 1.5rem; border-radius: 50%; display: grid; place-items: center;
    font-weight: 900; color: #08261a; background: var(--mp-good); }
.mp-e-pay-banner.is-warn .mp-e-pay-icon { background: var(--mp-accent); color: #241a00; }
.mp-e-pay-text { display: flex; flex-direction: column; }
.mp-e-pay-text .mp-muted { font-size: 0.8rem; }
.mp-e-pay-manage { margin-left: auto; white-space: nowrap; }
.mp-e-pay-body { padding: 0 0.9rem 0.9rem; border-top: 1px solid var(--mp-border); }

/* Counts strip (§8.1). */
.mp-e-counts { display: flex; align-items: stretch; padding: 0; overflow-x: auto; margin-bottom: 0.9rem; }
.mp-e-count { min-width: 118px; flex: 1; padding: 0.7rem 0.9rem; border-right: 1px solid var(--mp-border); white-space: nowrap; }
.mp-e-count:last-child { border-right: 0; }
.mp-e-count strong { font-size: 1.2rem; margin-right: 0.35rem; }
.mp-e-count span { color: var(--mp-muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; }

/* Toolbar: search + status chips + column chooser (§8.3/§8.8). */
.mp-e-toolbar { display: flex; align-items: center; gap: 0.55rem; margin-bottom: 0.6rem; flex-wrap: wrap; }
.mp-e-search { flex: 1 1 220px; max-width: 22rem; }
.mp-e-search input { width: 100%; height: 2.3rem; border-radius: 8px; border: 1px solid var(--mp-border);
    background: var(--mp-bg); color: var(--mp-text); padding: 0 0.7rem; }
.mp-e-search input:focus { outline: none; border-color: var(--mp-accent); }
.mp-e-chips { display: flex; align-items: center; gap: 0.3rem; flex-wrap: wrap; }
.mp-e-chip { height: 2.1rem; padding: 0 0.7rem; background: transparent; border: 1px solid var(--mp-border);
    border-radius: 8px; color: var(--mp-muted); cursor: pointer; font-size: 0.75rem; font-weight: 700; }
.mp-e-chip:hover { color: var(--mp-text); }
.mp-e-chip.is-active { color: var(--mp-text); background: var(--mp-surface-2); border-color: var(--mp-accent); }
.mp-e-toolbar-spacer { flex: 1 1 auto; }

/* Column chooser popover (§8.6) — reuses .mp-overflow/.mp-overflow-menu; widened for the grouped list. */
.mp-e-columns .mp-overflow-menu { min-width: 19rem; padding: 0; }
.mp-e-columns-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem;
    padding: 0.7rem 0.8rem; border-bottom: 1px solid var(--mp-border); }
.mp-e-columns-body { max-height: 22rem; overflow: auto; padding: 0.35rem; }
.mp-e-columns-section { padding: 0.5rem 0.5rem 0.25rem; color: var(--mp-muted); text-transform: uppercase;
    letter-spacing: 0.07em; font-size: 0.62rem; font-weight: 800; }
.mp-e-column-option { display: flex; align-items: center; gap: 0.6rem; min-height: 2.2rem; padding: 0.3rem 0.5rem; border-radius: 6px; }
.mp-e-column-option:hover { background: var(--mp-surface-2); }
.mp-e-column-option.is-locked { opacity: 0.75; }
.mp-e-column-label { flex: 1; font-size: 0.82rem; }
.mp-e-column-option small { color: var(--mp-muted); font-size: 0.68rem; white-space: nowrap; }
.mp-e-lock { color: var(--mp-accent); font-size: 0.7rem; }
/* Toggle switch (a submit button that immediately persists the choice). */
.mp-e-switch { flex: 0 0 auto; width: 2rem; height: 1.15rem; border-radius: 999px; border: 1px solid var(--mp-border);
    background: var(--mp-bg); cursor: pointer; position: relative; padding: 0; }
.mp-e-switch::after { content: ""; position: absolute; top: 1px; left: 1px; width: 0.9rem; height: 0.9rem;
    border-radius: 50%; background: var(--mp-muted); transition: transform 0.12s ease, background 0.12s ease; }
.mp-e-switch.on { background: color-mix(in srgb, var(--mp-accent) 35%, var(--mp-bg)); border-color: var(--mp-accent); }
.mp-e-switch.on::after { transform: translateX(0.85rem); background: var(--mp-accent); }
.mp-e-switch:focus-visible { outline: 2px solid var(--mp-accent); outline-offset: 2px; }

/* Grid cell rendering. */
.mp-entries-grid .mp-e-col-lifter { min-width: 15rem; }
.mp-entries-grid .mp-e-muted { color: var(--mp-muted); }
.mp-e-person { display: flex; align-items: center; gap: 0.55rem; }
.mp-e-avatar { flex: 0 0 auto; width: 1.7rem; height: 1.7rem; border-radius: 50%; display: grid; place-items: center;
    font-size: 0.62rem; font-weight: 800; color: #fff; background: linear-gradient(135deg, #4e5d73, #232b39); }
.mp-e-person-name { font-weight: 700; }
.mp-e-sub { color: var(--mp-muted); font-size: 0.7rem; margin-top: 0.15rem; }
.mp-e-status { display: inline-flex; align-items: center; gap: 0.4rem; font-weight: 700; white-space: nowrap; }
.mp-e-status i { flex: 0 0 auto; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--mp-muted); }
.mp-e-status.confirmed i, .mp-e-status.paid i { background: var(--mp-good); }
.mp-e-status.pending i { background: var(--mp-accent); }
.mp-e-status.wait i { background: var(--mp-info); }

/* Row actions + overflow menu. */
.mp-e-actions-cell { white-space: nowrap; }
.mp-e-row-actions { display: flex; align-items: center; gap: 0.3rem; }
.mp-e-mini { height: 1.9rem; padding: 0 0.55rem; font-size: 0.72rem; }
.mp-e-mini.primary { background: var(--mp-accent); color: #1a1300; border-color: var(--mp-accent); font-weight: 800; }
.mp-e-more { font-weight: 800; letter-spacing: 0.05em; }
.mp-e-row-menu .mp-overflow-menu { min-width: 9rem; }

/* Grid footer. */
.mp-e-gridfoot { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
    font-size: 0.72rem; padding: 0.5rem 0.2rem 0; }

/* Edit drawer (§8.9). */
.mp-e-drawer-scrim { position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,0.5); display: flex; justify-content: flex-end; }
.mp-e-drawer { width: min(40rem, 100%); height: 100%; overflow-y: auto; background: var(--mp-surface);
    border-left: 1px solid var(--mp-border); padding: 1.1rem 1.2rem; box-shadow: -14px 0 40px rgba(0,0,0,0.45); }
.mp-e-drawer-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; }
.mp-e-drawer-head h3 { margin: 0.15rem 0 0; }
.mp-e-drawer-body { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; margin-top: 0.6rem; }
.mp-e-original, .mp-e-correction { min-width: 0; }
.mp-e-original h4, .mp-e-correction h4 { margin: 0 0 0.5rem; }
.mp-e-original { background: var(--mp-bg); border: 1px solid var(--mp-border); border-radius: 10px; padding: 0.75rem 0.85rem; }
.mp-e-fieldlist { display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 0.7rem; margin: 0; font-size: 0.82rem; }
.mp-e-fieldlist dt { color: var(--mp-muted); }
.mp-e-fieldlist dd { margin: 0; word-break: break-word; }
/* Email notifications WP4 (spec §4.6) — last-notification pill inside the edit drawer's "Original at entry" panel. */
.mp-e-notify-pill { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; font-size: 0.8rem; }

@media (max-width: 720px) {
    .mp-e-drawer-body { grid-template-columns: 1fr; }
    .mp-e-drawer { width: 100%; }
    .mp-e-toolbar { align-items: stretch; }
    .mp-e-search { max-width: none; }
}

/* ==== Scoreboard/Livestream WP4: Setup-tab "Livestreams" panel (spec §5.2) ====
   Session-grouped card list; one row per active platform. Renders inside .mp-setup-scope, so the dark
   .form-control/select/input tokens defined near the top of this file already apply — only this panel's own
   layout (grid rows, compact fields, advanced disclosure) is defined here. */
.mp-ls-session {
    border: 1px solid var(--mp-border); border-radius: 12px; background: var(--mp-nested-surface, var(--mp-surface-2));
    margin-bottom: 0.85rem; overflow: hidden;
}
.mp-ls-session:last-child { margin-bottom: 0; }
.mp-ls-session-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 0.6rem;
    padding: 0.7rem 0.85rem; border-bottom: 1px solid var(--mp-border);
}
.mp-ls-session-head h4 { margin: 0; font-size: 0.92rem; }
.mp-ls-session-head p { margin: 0.2rem 0 0; font-size: 0.75rem; }
.mp-ls-row {
    display: grid; grid-template-columns: 7rem minmax(0,1.6fr) minmax(200px,1.3fr) 7.5rem 10rem auto;
    gap: 0.6rem; align-items: end; padding: 0.75rem 0.85rem;
    border-bottom: 1px solid color-mix(in srgb, var(--mp-border) 70%, transparent);
}
.mp-ls-row:last-of-type { border-bottom: 0; }
.mp-ls-field label { display: block; font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 0.25rem; }
.mp-ls-static { min-height: 2.2rem; display: flex; align-items: center; font-weight: 650; font-size: 0.85rem; }
.mp-ls-actions { display: flex; gap: 0.35rem; flex-wrap: wrap; align-items: center; grid-column: 1 / -1; margin-top: 0.15rem; }
.mp-ls-actions .mp-btn, .mp-ls-actions a.mp-btn, .mp-ls-actions span.mp-btn { white-space: nowrap; }
.mp-ls-advanced { grid-column: 1 / -1; margin-top: 0.35rem; }
.mp-ls-advanced > summary { cursor: pointer; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; list-style: none; color: var(--mp-muted); }
.mp-ls-advanced > summary::-webkit-details-marker { display: none; }
.mp-ls-advanced label { display: inline-block; margin: 0.4rem 0.5rem 0.4rem 0; font-size: 0.78rem; }
@media (max-width: 1099px) { .mp-ls-row { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .mp-ls-row { grid-template-columns: 1fr; } }

/* ==== Scoreboard/Livestream WP4: web lift player (spec §3.3/§4.3) — /meets/{id}/lifts/{attemptId} ==== */
.mp-lift-player { max-width: 40rem; margin: 0 auto; padding: 1rem 0 3rem; }
.mp-lp-back { display: inline-block; margin-bottom: 0.75rem; }
.mp-lp-frame {
    position: relative; aspect-ratio: 16 / 9; border-radius: 14px; overflow: hidden;
    background: linear-gradient(155deg, #151a25, #030405); border: 1px solid var(--mp-border);
    display: grid; place-items: center;
}
.mp-lp-iframe { width: 100%; height: 100%; border: 0; }
.mp-lp-play {
    width: 4.5rem; height: 4.5rem; min-width: 44px; min-height: 44px; border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.33); background: rgba(9,11,13,0.85); color: #fff; font-size: 1.6rem;
    padding-left: 0.3rem; cursor: pointer; box-shadow: 0 10px 30px rgba(0,0,0,0.6);
}
.mp-lp-cliptag { position: absolute; bottom: 0.7rem; left: 0.7rem; border-radius: 7px; background: rgba(0,0,0,0.7); padding: 0.3rem 0.5rem; font-size: 0.72rem; color: #fff; }
.mp-lp-frame-empty { padding: 1.5rem; text-align: center; }
.mp-lp-fallback { display: inline-block; margin-top: 0.5rem; font-size: 0.78rem; }
.mp-lp-title { display: flex; justify-content: space-between; align-items: flex-start; gap: 0.75rem; margin-top: 1rem; }
.mp-lp-title h2 { margin: 0 0 0.2rem; }
.mp-lp-result { font-weight: 800; font-size: 0.85rem; white-space: nowrap; }
.mp-lp-result.good { color: var(--mp-good); }
.mp-lp-result.bad { color: var(--mp-nolift); }
.mp-lp-metarow { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; margin-top: 0.85rem; }
.mp-lp-metarow div { background: var(--mp-surface-2); border: 1px solid var(--mp-border); border-radius: 10px; padding: 0.55rem 0.7rem; }
.mp-lp-metarow small { display: block; color: var(--mp-muted); font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; }
.mp-lp-metarow b { font-size: 0.92rem; }
.mp-lp-nav { display: flex; justify-content: space-between; gap: 0.6rem; margin-top: 1rem; }
.mp-lp-nav .mp-btn { min-height: 44px; display: inline-flex; align-items: center; }
.mp-lp-others { margin-top: 1.25rem; }
.mp-lp-others h3 { margin: 0 0 0.5rem; font-size: 0.85rem; }
.mp-lp-others-strip { display: flex; gap: 0.6rem; overflow-x: auto; padding-bottom: 0.3rem; }
.mp-lp-mini {
    min-width: 8.5rem; border: 1px solid var(--mp-border); border-radius: 10px; background: var(--mp-surface-2);
    padding: 0.6rem 0.7rem; text-decoration: none; color: var(--mp-text); flex: 0 0 auto; display: block;
}
.mp-lp-mini.active { border-color: var(--mp-accent); background: color-mix(in srgb, var(--mp-accent) 12%, var(--mp-surface-2)); }
.mp-lp-mini b { display: block; font-size: 0.78rem; font-weight: 700; }
.mp-lp-mini small { display: block; color: var(--mp-muted); font-size: 0.68rem; margin-top: 0.25rem; }
@media (max-width: 500px) {
    .mp-lift-player { padding: 0.5rem 0.75rem 3rem; }
    .mp-lp-metarow { grid-template-columns: 1fr 1fr; }
}

/* ==== Completion WP1b+WP2: home, auth, onboarding, account & security (docs/specs/completion) ====
   New surfaces only — reuses --mp-* tokens and the existing .mp-card/.mp-btn/.mp-badge/.mp-muted system
   throughout (WP0 §2 rule 5). Dark form-control treatment mirrors the Setup redesign's .mp-setup-scope rules
   (same --mp-control-* tokens, same states) but scoped under .mp-auth-scope so Login/Register/Onboarding/
   Devices get properly themed inputs without touching any other page. Also reused as-is (WP8 completion fix,
   spec §5.1) on the director's manual-entry form (ManualEntryPage.razor) and the public results filter bar
   (Results.razor) — same harsh-white-input problem, same fix, no new CSS needed. */

.mp-auth-scope .form-control,
.mp-auth-scope .mp-multiselect > summary.msd-control {
    display: block; width: 100%; min-height: 2.6rem; padding: 0 0.75rem; color: var(--mp-text);
    background: var(--mp-control-bg); border: 1px solid var(--mp-control-border); border-radius: 8px;
    box-shadow: inset 0 1px 1px rgba(0,0,0,0.2); outline: none;
    transition: border-color .14s ease, background-color .14s ease, box-shadow .14s ease;
}
.mp-auth-scope .form-control::placeholder { color: var(--mp-control-placeholder); opacity: 1; }
.mp-auth-scope .form-control:hover:not(:disabled):not([readonly]) { background: var(--mp-control-bg-hover); border-color: #435164; }
.mp-auth-scope .form-control:focus-visible, .mp-auth-scope .form-control:focus {
    border-color: var(--mp-control-border-focus); background: #19212b;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-control-border-focus) 22%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-auth-scope .form-control:disabled { opacity: 0.55; cursor: not-allowed; }
.mp-auth-scope .form-control.invalid, .mp-auth-scope .form-control[aria-invalid="true"] {
    border-color: var(--mp-nolift);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-nolift) 18%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-auth-scope select.form-control {
    appearance: none; -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, #7d8999 50%), linear-gradient(135deg, #7d8999 50%, transparent 50%);
    background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%; background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
    padding-right: 1.7rem;
}
.mp-auth-scope .validation-message, .mp-auth-scope .mp-field-error {
    display: block; margin-top: 0.3rem; color: var(--mp-nolift); font-size: 0.78rem; font-weight: 700;
}
.mp-auth-scope label.mp-muted { display: block; margin: 0.75rem 0 0.3rem; font-size: 0.78rem; font-weight: 650; }
.mp-auth-scope label.mp-muted:first-child { margin-top: 0; }

.mp-badge.blue { color: var(--mp-info); border-color: var(--mp-info); }

/* ---- Shared inline status panels (errors/notices) — aria-live region content, no card-jump (spec §5.4/§10) ---- */
.mp-auth-error {
    border: 1px solid var(--mp-nolift); background: color-mix(in srgb, var(--mp-nolift) 12%, var(--mp-surface));
    border-radius: 10px; padding: 0.75rem 0.9rem; margin-bottom: 1rem;
}
.mp-auth-error strong { color: var(--mp-nolift); display: block; font-size: 0.85rem; }
.mp-auth-error p { margin: 0.25rem 0 0; color: var(--mp-muted); font-size: 0.8rem; }
.mp-auth-notice {
    border: 1px solid var(--mp-good); background: color-mix(in srgb, var(--mp-good) 12%, var(--mp-surface));
    border-radius: 10px; padding: 0.75rem 0.9rem; margin-bottom: 1rem;
}
.mp-auth-notice strong { color: var(--mp-good); display: block; font-size: 0.85rem; }
.mp-auth-notice p { margin: 0.25rem 0 0; color: var(--mp-muted); font-size: 0.8rem; }

/* ---- §5.4 Sign-in / create account ---- */
.mp-auth-wrap { max-width: 1180px; margin: 0 auto; }
.mp-auth-layout { display: grid; grid-template-columns: minmax(0, 1.1fr) 460px; gap: 1.75rem; align-items: stretch; margin-top: 1.25rem; }
.mp-auth-story {
    padding: 2.25rem; border-radius: 14px; border: 1px solid var(--mp-border);
    background: linear-gradient(140deg, color-mix(in srgb, var(--mp-accent) 11%, transparent), transparent 45%), var(--mp-surface);
    display: flex; flex-direction: column; justify-content: space-between; gap: 1.5rem;
}
.mp-auth-story h1 { font-size: clamp(1.7rem, 3vw, 2.6rem); line-height: 1.05; letter-spacing: -0.02em; margin: 0.5rem 0 0.75rem; }
.mp-auth-story-top > p { color: #b8c0ca; font-size: 0.98rem; line-height: 1.6; max-width: 34rem; }
.mp-session-preview { display: grid; gap: 0.6rem; margin-top: 0.5rem; }
.mp-session-row {
    display: grid; grid-template-columns: 42px minmax(0, 1fr) auto; gap: 0.75rem; align-items: center;
    padding: 0.7rem; border-radius: 10px; background: rgba(11,14,19,0.45); border: 1px solid var(--mp-border);
}
.mp-device-icon { width: 42px; height: 42px; border-radius: 9px; background: var(--mp-surface-2); display: grid; place-items: center; color: var(--mp-accent-2, var(--mp-accent)); font-size: 1.1rem; }
.mp-session-row strong { display: block; font-size: 0.8rem; }
.mp-session-row span { display: block; color: var(--mp-muted); font-size: 0.7rem; margin-top: 2px; }

.mp-auth-card { padding: 1.6rem; border-radius: 14px; background: var(--mp-surface); border: 1px solid var(--mp-border); align-self: center; }
.mp-auth-card h2 { font-size: 1.5rem; margin: 0 0 0.4rem; }
.mp-auth-card > p.mp-muted { font-size: 0.82rem; margin-bottom: 0; }

.mp-provider-list { display: grid; gap: 0.6rem; margin: 1.2rem 0; }
.mp-provider-btn {
    min-height: 48px; display: grid; grid-template-columns: 28px 1fr 20px; align-items: center; gap: 0.6rem;
    border: 1px solid var(--mp-border); border-radius: 9px; background: var(--mp-surface-2); color: var(--mp-text);
    font-weight: 700; text-decoration: none; padding: 0 0.9rem;
}
.mp-provider-btn:hover, .mp-provider-btn:focus-visible { border-color: var(--mp-accent); }
.mp-provider-icon { width: 24px; height: 24px; border-radius: 6px; background: #fff; color: #151515; display: grid; place-items: center; font-weight: 900; font-size: 0.75rem; justify-self: start; }
.mp-provider-btn.instagram .mp-provider-icon { background: linear-gradient(135deg,#7c3aed,#f43f5e,#f59e0b); color: #fff; }
.mp-provider-arrow { justify-self: end; color: var(--mp-muted); }

.mp-divider { display: flex; align-items: center; gap: 0.6rem; color: var(--mp-muted); font-size: 0.72rem; margin: 0.9rem 0; }
.mp-divider::before, .mp-divider::after { content: ""; height: 1px; flex: 1; background: var(--mp-border); }

.mp-remember-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; margin-top: 0.7rem; font-size: 0.8rem; color: var(--mp-muted); flex-wrap: wrap; }
.mp-remember-row label { display: flex; align-items: center; gap: 0.5rem; }
.mp-remember-row input[type="checkbox"] { accent-color: var(--mp-accent); width: 15px; height: 15px; }

.mp-auth-foot { margin-top: 1.1rem; color: var(--mp-muted); font-size: 0.78rem; text-align: center; line-height: 1.6; }

@media (max-width: 900px) {
    .mp-auth-layout { grid-template-columns: 1fr; }
    .mp-auth-story { display: none; }
    .mp-auth-card { max-width: 520px; margin: 0 auto; width: 100%; }
}

/* ---- §5.5 First-run onboarding ---- */
.mp-onboard-layout { display: grid; grid-template-columns: 250px minmax(0, 1fr) 330px; gap: 1rem; align-items: start; margin-top: 1rem; }
.mp-onboard-steps { padding: 0.8rem; position: sticky; top: 0.75rem; }
.mp-ostep { display: grid; grid-template-columns: 27px 1fr; gap: 0.6rem; align-items: center; min-height: 50px; padding: 0.45rem 0.5rem; border-radius: 9px; color: var(--mp-muted); font-size: 0.82rem; font-weight: 700; }
.mp-ostep.active { color: var(--mp-text); background: var(--mp-surface-2); }
.mp-ostep-n { width: 27px; height: 27px; border-radius: 50%; border: 1px solid var(--mp-border); display: grid; place-items: center; font-size: 0.68rem; font-weight: 900; }
.mp-ostep.done .mp-ostep-n { background: var(--mp-good); border-color: var(--mp-good); color: #08261a; }
.mp-ostep.active .mp-ostep-n { border-color: var(--mp-accent); color: var(--mp-accent); }

.mp-choice-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; margin: 1.1rem 0; }
.mp-choice {
    position: relative; min-height: 160px; padding: 1.1rem; border: 1px solid var(--mp-border); border-radius: 11px;
    background: var(--mp-surface-2); cursor: pointer; display: block;
}
.mp-choice input { position: absolute; width: 1px; height: 1px; opacity: 0; top: 0.9rem; left: 0.9rem; }
.mp-choice:has(input:focus-visible) { outline: 2px solid var(--mp-accent); outline-offset: 2px; }
.mp-choice.selected {
    border-color: var(--mp-accent); box-shadow: inset 0 0 0 1px var(--mp-accent);
    background: linear-gradient(135deg, color-mix(in srgb, var(--mp-accent) 14%, transparent), transparent 55%), var(--mp-surface-2);
}
.mp-choice-icon { width: 40px; height: 40px; border-radius: 10px; background: var(--mp-surface-3, var(--mp-surface)); display: grid; place-items: center; color: var(--mp-accent-2, var(--mp-accent)); margin-bottom: 0.9rem; font-weight: 900; }
.mp-choice p { color: var(--mp-muted); font-size: 0.78rem; line-height: 1.5; margin-top: 0.4rem; }
.mp-choice-check { position: absolute; top: 0.9rem; right: 0.9rem; width: 22px; height: 22px; border-radius: 6px; border: 1px solid var(--mp-border-strong, var(--mp-border)); display: grid; place-items: center; font-size: 0.7rem; font-weight: 900; color: transparent; }
.mp-choice.selected .mp-choice-check { background: var(--mp-good); border-color: var(--mp-good); color: #08261a; }

.mp-onboard-summary { padding: 1.1rem; position: sticky; top: 0.75rem; }
.mp-summary-line { display: flex; justify-content: space-between; gap: 0.75rem; padding-bottom: 0.6rem; margin-bottom: 0.6rem; border-bottom: 1px solid var(--mp-border); font-size: 0.78rem; }
.mp-summary-line span { color: var(--mp-muted); }
.mp-summary-line:last-of-type { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }

.mp-onboard-actions { display: flex; justify-content: space-between; gap: 0.6rem; margin-top: 1.4rem; flex-wrap: wrap; }

@media (max-width: 1180px) {
    .mp-onboard-layout { grid-template-columns: 210px minmax(0, 1fr); }
    .mp-onboard-summary { grid-column: 1 / -1; position: static; }
}
@media (max-width: 860px) {
    .mp-onboard-layout { grid-template-columns: 1fr; }
    .mp-onboard-steps { position: static; display: flex; gap: 0.4rem; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .mp-ostep { flex: 0 0 auto; min-width: 9rem; }
}
@media (max-width: 560px) {
    .mp-choice-grid { grid-template-columns: 1fr; }
}

/* ---- §5.3 Public home ---- */
.mp-home-hero { display: grid; grid-template-columns: minmax(0, 7fr) minmax(340px, 5fr); gap: 2.5rem; align-items: center; min-height: 560px; padding: 2rem 0 2.5rem; }
.mp-home-hero h1 { font-size: clamp(2.2rem, 5vw, 4.2rem); line-height: 0.98; letter-spacing: -0.03em; margin: 0.5rem 0 0.9rem; }
.mp-home-hero h1 span { color: var(--mp-accent); }
.mp-home-copy p { max-width: 38rem; color: #b5bfcc; font-size: 1.05rem; line-height: 1.6; }
.mp-home-actions { display: flex; gap: 0.75rem; margin-top: 1.4rem; flex-wrap: wrap; }
.mp-proof-row { display: flex; flex-wrap: wrap; gap: 1.1rem; margin-top: 1.5rem; color: var(--mp-muted); font-size: 0.72rem; font-weight: 700; }
.mp-proof-row span::before { content: "\2713"; color: var(--mp-good); margin-right: 0.35rem; }

.mp-preview-card { padding: 1rem; border-radius: 14px; background: linear-gradient(150deg, color-mix(in srgb, var(--mp-accent) 9%, transparent), transparent 42%), var(--mp-surface); border: 1px solid var(--mp-border); box-shadow: 0 18px 44px rgba(0,0,0,0.35); }
/* flex-wrap matters: .mp-badge is white-space:nowrap, so without it the badge fixes this row's min-content
   at title+badge width (~281px), which propagates up through .mp-preview-card into the hero's 1fr track and
   forces page-level horizontal overflow at viewports ≤ ~347px. */
.mp-preview-top { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; margin-bottom: 0.8rem; gap: 0.5rem; }
.mp-preview-current { padding: 0.9rem; border-radius: 10px; background: var(--mp-bg); border-left: 4px solid var(--mp-accent); }
.mp-preview-name { display: flex; justify-content: space-between; gap: 0.75rem; align-items: flex-start; }
.mp-preview-name strong { font-size: 1.35rem; letter-spacing: -0.02em; }
.mp-preview-kg { color: var(--mp-accent); font-size: 1.35rem; font-weight: 900; }
.mp-preview-meta { display: flex; gap: 0.4rem; flex-wrap: wrap; color: var(--mp-muted); font-size: 0.72rem; margin-top: 0.4rem; }
.mp-preview-table { margin-top: 0.8rem; border: 1px solid var(--mp-border); border-radius: 10px; overflow: hidden; }
.mp-preview-row { display: grid; grid-template-columns: 28px minmax(0,1fr) repeat(3, 3.4rem); min-height: 42px; align-items: center; padding: 0 0.65rem; border-bottom: 1px solid var(--mp-border); font-size: 0.72rem; gap: 0.3rem; }
.mp-preview-row:last-child { border-bottom: 0; }
.mp-preview-row.head { color: var(--mp-muted); background: var(--mp-surface-2); font-size: 0.6rem; text-transform: uppercase; font-weight: 800; }
.mp-preview-row.current { background: color-mix(in srgb, var(--mp-accent) 12%, transparent); }
.mp-preview-good { color: var(--mp-good); font-weight: 800; }

.mp-feature-band { border-top: 1px solid var(--mp-border); border-bottom: 1px solid var(--mp-border); margin-top: 1rem; background: rgba(22,27,34,0.5); }
.mp-feature-grid { max-width: 1560px; margin: 0 auto; padding: 2.5rem 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.mp-feature-icon { width: 40px; height: 40px; border-radius: 10px; background: var(--mp-surface-2); color: var(--mp-accent); display: grid; place-items: center; margin-bottom: 1rem; font-weight: 900; }
.mp-feature-grid .mp-card p { color: var(--mp-muted); font-size: 0.8rem; line-height: 1.55; margin-top: 0.45rem; }

@media (max-width: 1100px) {
    /* minmax(0, 1fr), not bare 1fr: 1fr means minmax(auto, 1fr), so any grid item's min-content (e.g. a
       nowrap badge inside the preview card) could widen the track past the container and overflow the page. */
    .mp-home-hero { grid-template-columns: minmax(0, 1fr); min-height: auto; }
    .mp-home-hero .mp-preview-wrap { order: 2; }
    .mp-home-hero .mp-home-copy { order: 1; }
    .mp-feature-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .mp-feature-grid { grid-template-columns: 1fr; }
    .mp-preview-row > :nth-child(n+5) { display: none; }
    .mp-preview-row { grid-template-columns: 24px minmax(0,1fr) 3.4rem; }
}
@media (max-width: 480px) {
    .mp-home-actions { flex-direction: column; }
    .mp-home-actions .mp-btn { width: 100%; text-align: center; }
}

/* ---- §3.4 Account & security / trusted devices ---- */
.mp-device-list { display: grid; gap: 0.75rem; }
.mp-device-card { display: flex; align-items: center; gap: 1rem; padding: 0.9rem 1rem; border: 1px solid var(--mp-border); border-radius: 11px; background: var(--mp-surface-2); flex-wrap: wrap; }
.mp-device-card.current { border-color: var(--mp-accent); }
.mp-device-card-info { flex: 1 1 14rem; min-width: 0; }
.mp-device-card-info strong { display: block; font-size: 0.92rem; }
.mp-device-meta { display: flex; flex-wrap: wrap; gap: 0.5rem 0.9rem; margin-top: 0.35rem; color: var(--mp-muted); font-size: 0.75rem; }
.mp-device-card-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

.mp-conn-list { display: grid; }
.mp-conn-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.75rem 0; border-bottom: 1px solid var(--mp-border); flex-wrap: wrap; }
.mp-conn-row:last-child { border-bottom: 0; }
.mp-conn-name { display: flex; align-items: center; gap: 0.6rem; font-weight: 700; }

@media (max-width: 560px) {
    .mp-device-card { flex-direction: column; align-items: flex-start; }
    .mp-device-card-actions { width: 100%; }
}

/* ==== Profile/equipment WP3: /profile professional layout ====
   docs/specs/profile-equipment/{WP0-architecture-and-parity.md, fable-profile-equipment-architecture-spec.md,
   profile-redesign-ui-mockup.html}. ADDITIVE ONLY — nothing above this comment is touched. `.mp-profile-scope`
   clones the Setup redesign's `.mp-setup-scope` control treatment (rest/hover/focus-visible ring/readonly dashed/
   disabled/invalid/placeholder/select-arrow/color-scheme, WP0 finding 15) rather than duplicating hard-coded
   colours, plus this page's own layout/media-rail/set-card/rack-card/autocomplete chrome. Only --mp-* tokens are
   used, matching every value already used elsewhere in this file (WP0 §2 rule 5/finding 15). */

.mp-profile-scope { width: 100%; max-width: none; padding-bottom: 6.5rem; }

/* ---- Dark control base (identical states to .mp-setup-scope; see that block's own comments for the Chromium
   file-input caveat, which this page doesn't use, so it isn't repeated here). ---- */
.mp-profile-scope .form-control {
    display: block; width: 100%; min-height: 2.35rem; padding: 0 0.65rem; color: var(--mp-text);
    background: var(--mp-control-bg); border: 1px solid var(--mp-control-border); border-radius: 7px;
    box-shadow: inset 0 1px 1px rgba(0,0,0,0.2); outline: none;
    transition: border-color .14s ease, background-color .14s ease, box-shadow .14s ease;
}
.mp-profile-scope textarea.form-control { min-height: 6.5rem; resize: vertical; padding: 0.55rem 0.65rem; }
.mp-profile-scope .form-control::placeholder { color: var(--mp-control-placeholder); opacity: 1; }
.mp-profile-scope .form-control:hover:not(:disabled):not([readonly]) { background: var(--mp-control-bg-hover); border-color: #435164; }
.mp-profile-scope .form-control:focus-visible, .mp-profile-scope .form-control:focus {
    border-color: var(--mp-control-border-focus); background: #19212b;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-control-border-focus) 22%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-profile-scope .form-control:disabled, .mp-profile-scope .form-control[disabled] {
    opacity: 0.55; cursor: not-allowed; background: color-mix(in srgb, var(--mp-control-bg) 65%, var(--mp-bg));
}
.mp-profile-scope .form-control[readonly] { background: transparent; border-style: dashed; color: var(--mp-muted); }
.mp-profile-scope .form-control.invalid, .mp-profile-scope .form-control[aria-invalid="true"],
.mp-profile-scope .validation-message {
    border-color: var(--mp-nolift);
}
.mp-profile-scope .form-control.invalid, .mp-profile-scope .form-control[aria-invalid="true"] {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-nolift) 18%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-profile-scope .validation-message { display: block; margin-top: 0.3rem; color: var(--mp-nolift); font-size: 0.78rem; font-weight: 700; border: 0; }
.mp-profile-scope select.form-control {
    appearance: none; -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, #7d8999 50%), linear-gradient(135deg, #7d8999 50%, transparent 50%);
    background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%; background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
    padding-right: 1.7rem;
}
.mp-profile-scope label { display: block; margin-bottom: 0.35rem; color: var(--mp-muted); font-size: 0.78rem; font-weight: 700; }
.mp-profile-scope label .optional { color: var(--mp-faint, var(--mp-muted)); font-weight: 550; }

/* ---- WP5 polish: card elevation + icon chips (mock ".card"/".card-icon") ----
   The shared global `.mp-card` (platform.css line ~776) is deliberately left untouched — it is reused by Setup and
   other pages that were never designed with a drop shadow. Scoping the mock's `--shadow`/13px radius under
   `.mp-profile-scope` only brings this page to visual parity with the mock without touching any other surface. */
.mp-profile-scope .mp-card { border-radius: 13px; box-shadow: 0 14px 35px rgba(0, 0, 0, 0.22); }
.mp-profile-card-title { display: flex; align-items: flex-start; gap: 0.7rem; min-width: 0; }
.mp-profile-card-icon {
    flex: 0 0 auto; width: 2.15rem; height: 2.15rem; display: grid; place-items: center;
    border: 1px solid color-mix(in srgb, var(--mp-accent) 28%, transparent); border-radius: 9px;
    background: color-mix(in srgb, var(--mp-accent) 12%, transparent); color: var(--mp-accent);
}
.mp-profile-card-icon svg { width: 17px; height: 17px; }

/* ---- Header (ProfileHeader.razor, mock ".page-header") ---- */
.mp-profile-header {
    display: flex; align-items: flex-end; justify-content: space-between; gap: 1.25rem; flex-wrap: wrap;
    margin: 0 0 1.1rem; padding: 0.25rem 0.1rem;
}
.mp-profile-eyebrow {
    margin: 0 0 0.35rem; color: var(--mp-accent); font-size: 0.68rem; font-weight: 850;
    text-transform: uppercase; letter-spacing: 0.1em;
}
.mp-profile-header h1 { margin: 0; font-size: clamp(1.7rem, 2.4vw, 2.4rem); line-height: 1.05; letter-spacing: -0.03em; }
.mp-profile-subtitle { margin: 0.5rem 0 0; color: var(--mp-muted); }
.mp-profile-role-badges { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.mp-profile-role-badge {
    display: inline-flex; align-items: center; gap: 6px; min-height: 26px; width: max-content; white-space: nowrap;
    padding: 4px 10px; border: 1px solid #425064; border-radius: 999px; background: #1a222c; color: #dce4ee;
    font-size: 0.75rem; font-weight: 750;
}
.mp-profile-role-badge::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--mp-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-accent) 20%, transparent); }

/* ---- Alerts / notices (error summary + success/review banner — spec §12.4 focus management) ---- */
.mp-profile-alert {
    border: 1px solid var(--mp-nolift); background: color-mix(in srgb, var(--mp-nolift) 12%, var(--mp-surface));
    border-radius: 10px; padding: 0.8rem 0.95rem; margin-bottom: 1rem;
}
.mp-profile-alert:focus-visible, .mp-profile-alert:focus { outline: 2px solid var(--mp-nolift); outline-offset: 2px; }
.mp-profile-alert strong { color: var(--mp-nolift); display: block; font-size: 0.85rem; margin-bottom: 0.2rem; }
.mp-profile-notice {
    border: 1px solid var(--mp-good); background: color-mix(in srgb, var(--mp-good) 12%, var(--mp-surface));
    border-radius: 10px; padding: 0.8rem 0.95rem; margin-bottom: 1rem;
}
.mp-profile-notice strong { color: var(--mp-good); display: block; font-size: 0.85rem; }
.mp-profile-notice p { margin: 0.35rem 0 0; color: var(--mp-muted); font-size: 0.8rem; }

/* ---- Two-column workspace (fable-spec §4.1/§4.2, mock ".profile-layout") ---- */
.mp-profile-layout { display: grid; grid-template-columns: minmax(290px, 350px) minmax(0, 1fr); gap: 1.1rem; align-items: start; }
.mp-profile-side { position: sticky; top: 1.1rem; }
.mp-profile-main { display: flex; flex-direction: column; gap: 1.1rem; min-width: 0; }

.mp-profile-card { padding: 0; }
.mp-profile-card-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
    padding: 1.1rem 1.25rem 0.85rem; border-bottom: 1px solid var(--mp-border);
}
.mp-profile-card-head h2 { margin: 0; font-size: 1rem; letter-spacing: -0.015em; }
.mp-profile-card-desc { margin: 0.2rem 0 0; color: var(--mp-muted); font-size: 0.78rem; }
.mp-profile-card-body { padding: 1.1rem 1.25rem 1.25rem; }
.mp-profile-section-label {
    margin: 0 0 0.75rem; color: #cfd7e2; font-size: 0.72rem; font-weight: 850;
    text-transform: uppercase; letter-spacing: 0.07em;
}
.mp-profile-divider { height: 1px; background: var(--mp-border); margin: 1.1rem 0; }
.mp-profile-help { margin: 0.4rem 0 0; color: var(--mp-muted); font-size: 0.72rem; }
.mp-profile-help a { color: var(--mp-accent); }
.mp-profile-fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }

/* ---- Personal-details/public-profile field grid (mock ".field-grid") ---- */
.mp-profile-field-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0.85rem; }
.mp-profile-field { grid-column: span 4; min-width: 0; }
.mp-profile-field.span-6 { grid-column: span 6; }
.mp-profile-field.span-8 { grid-column: span 8; }
.mp-profile-field.span-12 { grid-column: 1 / -1; }

/* ---- Best-lift set cards (BestLiftsEditor.razor, mock ".equipment-set") ---- */
.mp-profile-equipment-defaults { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; }
.mp-profile-set { position: relative; padding: 0.9rem; border: 1px solid var(--mp-border); border-radius: 10px; background: var(--mp-nested-surface); }
.mp-profile-set.is-default { border-color: color-mix(in srgb, var(--mp-accent) 48%, var(--mp-border)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mp-accent) 9%, transparent); }
.mp-profile-set-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.75rem; }
.mp-profile-set-name { display: flex; align-items: center; gap: 0.5rem; font-weight: 850; }
.mp-profile-default-badge { font-size: 0.6rem; padding: 0.1rem 0.45rem; }
.mp-profile-default-choice {
    display: inline-flex; align-items: center; gap: 0.4rem; min-height: 1.6rem; padding: 0.1rem 0.2rem;
    color: var(--mp-muted); cursor: pointer; font-size: 0.68rem; font-weight: 750;
}
.mp-profile-default-choice input[type="radio"] { accent-color: var(--mp-accent); width: 15px; height: 15px; margin: 0; }
.mp-profile-default-choice:focus-within { outline: 2px solid var(--mp-control-border-focus); outline-offset: 2px; border-radius: 4px; }
.mp-profile-set.is-default .mp-profile-default-choice { color: var(--mp-accent); }
.mp-profile-lift-fields { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.6rem; }
.mp-profile-lift-field label { margin-bottom: 0.3rem; font-size: 0.68rem; }
.mp-profile-input-wrap { position: relative; }
.mp-profile-input-wrap .form-control { padding-right: 2.2rem; }
.mp-profile-input-suffix {
    position: absolute; right: 0.65rem; top: 50%; transform: translateY(-50%);
    color: var(--mp-muted); font-size: 0.7rem; font-weight: 750; pointer-events: none;
}
.mp-profile-set-note { margin: 0.6rem 0 0; color: var(--mp-muted); font-size: 0.66rem; line-height: 1.4; }

/* ---- Rack defaults island (RackDefaultsEditor.razor, mock ".rack-default") ---- */
.mp-profile-immediate-note { margin: 0 0 0.9rem; color: var(--mp-muted); font-size: 0.76rem; font-style: italic; }
.mp-profile-rack-search-row { display: grid; grid-template-columns: minmax(240px, 32rem) auto; align-items: end; gap: 0.65rem; margin-bottom: 0.5rem; }
.mp-profile-rack-search-row .mp-btn { min-height: 2.35rem; }
.mp-profile-rack-fields-pad { margin: 0 1.1rem 0.6rem; }
.mp-profile-rack-list { display: flex; flex-direction: column; gap: 0.7rem; margin-top: 0.9rem; }
.mp-profile-rack-card { border: 1px solid var(--mp-border); border-radius: 10px; background: var(--mp-nested-surface); overflow: hidden; }
.mp-profile-rack-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 0.85rem; border-bottom: 1px solid var(--mp-border); }
.mp-profile-rack-name { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.mp-profile-rack-glyph {
    flex: 0 0 auto; width: 1.9rem; height: 1.9rem; display: grid; place-items: center; border-radius: 8px;
    background: #202a36; color: var(--mp-accent); font-weight: 900; text-transform: uppercase;
}
.mp-profile-rack-name strong { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-profile-rack-meta { display: flex; align-items: center; gap: 0.4rem; color: var(--mp-muted); font-size: 0.66rem; }
.mp-profile-unavailable-badge { color: var(--mp-nolift); border-color: color-mix(in srgb, var(--mp-nolift) 45%, var(--mp-border)); }
.mp-profile-confirm-remove { display: flex; align-items: center; gap: 0.5rem; font-size: 0.72rem; color: var(--mp-muted); flex-wrap: wrap; }
.mp-profile-rack-fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.7rem; padding: 0.85rem 0.85rem 0.9rem; }
.mp-profile-segmented {
    display: grid; grid-template-columns: 1fr 1fr; gap: 4px; min-height: 2.35rem; padding: 4px;
    border: 1px solid var(--mp-control-border); border-radius: 8px; background: var(--mp-control-bg);
}
.mp-profile-segmented label {
    display: flex; align-items: center; justify-content: center; margin: 0; border-radius: 5px;
    color: var(--mp-muted); cursor: pointer; font-size: 0.7rem; font-weight: 750;
}
.mp-profile-segmented label.active { background: #2a3542; color: var(--mp-text); box-shadow: inset 0 0 0 1px #48576a; }
.mp-profile-segmented input[type="radio"] {
    position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%);
}
.mp-profile-segmented label:focus-within { outline: 2px solid var(--mp-control-border-focus); outline-offset: 2px; }
.mp-profile-rack-save-row { display: flex; align-items: center; gap: 0.75rem; padding: 0 0.85rem 0.85rem; flex-wrap: wrap; }
.mp-profile-save-state { color: var(--mp-muted); font-size: 0.75rem; }
.mp-profile-rack-error { color: var(--mp-nolift); font-weight: 700; }

/* ---- Shared rack-equipment autocomplete (RackEquipmentAutocomplete.razor, mock ".search-box"/".suggestions").
   Not nested under .mp-profile-scope: WP4 reuses this same component under .mp-setup-scope, so its chrome is
   scoped to its own class names instead of duplicated per host page. z-index follows the documented chain — the
   savebar is z-60 (below), so the open dropdown clears it at 190 (WP0 finding 15/§ "z-chain"). ---- */
.mp-rea { position: relative; min-width: 0; }
.mp-rea-box { position: relative; }
.mp-rea-input { padding-right: 0.65rem; }
.suggestions {
    position: absolute; left: 0; right: 0; top: calc(100% + 5px); z-index: 190; overflow: hidden;
    border: 1px solid #445165; border-radius: 9px; background: #141b24; box-shadow: 0 18px 40px rgba(0,0,0,.42);
    max-height: 18rem; overflow-y: auto;
}
.suggestion {
    width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
    padding: 0.6rem 0.75rem; border: 0; border-bottom: 1px solid #29323e; background: transparent;
    color: var(--mp-text); text-align: left; cursor: pointer; font: inherit;
}
.suggestion:last-child { border-bottom: 0; }
.suggestion:hover, .suggestion.active { background: #1d2631; }
.suggestion:focus-visible { outline: 2px solid var(--mp-control-border-focus); outline-offset: -2px; }
.suggestion[aria-disabled="true"] { cursor: default; color: var(--mp-muted); }
.suggestion strong { display: block; font-size: 0.75rem; }
.suggestion span span { display: block; color: var(--mp-muted); font-size: 0.62rem; }
.suggestion .type { flex: 0 0 auto; color: var(--mp-accent); font-size: 0.68rem; }
.suggestion.create { color: var(--mp-accent); font-weight: 800; }

/* ---- Sticky savebar clearance (reuses the existing global .mp-savebar; see the shared rule far above) ---- */
.mp-profile-scope .mp-save-state { display: flex; align-items: center; gap: 0.55rem; color: var(--mp-muted); font-size: 0.8rem; }
.mp-profile-scope .mp-save-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--mp-good); box-shadow: 0 0 0 4px color-mix(in srgb, var(--mp-good) 12%, transparent); flex: 0 0 auto; }
.mp-profile-scope .mp-save-actions { display: flex; align-items: center; gap: 0.6rem; }

/* ---- Responsive tiers (fable-spec §4.1/§4.2/§10, mock breakpoints) ----
   >=1180: two-column workspace as authored above.
   860-1179: media rail narrows slightly, fields still 12-col but span-8 collapses to full width.
   <860: media rail stacks above the form; media uploaders sit two-up (own ProfileImageUpload.razor.css handles
     stacking one-up under 720px, matched here for consistency at the same page-level tier).
   <640: single column throughout, 44px touch targets, no page-level horizontal scroll (spec §4.2). ---- */
@media (max-width: 1180px) {
    .mp-profile-layout { grid-template-columns: minmax(260px, 310px) minmax(0, 1fr); }
    .mp-profile-field { grid-column: span 6; }
    .mp-profile-field.span-8 { grid-column: span 12; }
    .mp-profile-rack-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
    .mp-profile-layout { grid-template-columns: minmax(0, 1fr); }
    .mp-profile-side { position: static; }
    .mp-profile-media-card .mp-profile-card-body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
    .mp-profile-media-card .mp-media-block + .mp-media-block { margin: 0; padding: 0; border: 0; }
    .mp-profile-equipment-defaults { grid-template-columns: minmax(0, 1fr); }
    .mp-profile-rack-search-row { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
    .mp-profile-header { align-items: flex-start; flex-direction: column; gap: 0.6rem; }
    .mp-profile-card-head, .mp-profile-card-body { padding-left: 1rem; padding-right: 1rem; }
    .mp-profile-field, .mp-profile-field.span-6, .mp-profile-field.span-8 { grid-column: 1 / -1; }
    .mp-profile-media-card .mp-profile-card-body { grid-template-columns: minmax(0, 1fr); }
    .mp-profile-lift-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mp-profile-rack-fields { grid-template-columns: minmax(0, 1fr); }
    .mp-profile-rack-search-row .mp-btn { width: 100%; }
    .mp-profile-scope .form-control, .mp-profile-scope .mp-btn, .mp-profile-scope .mp-media-icon-btn,
    .mp-profile-segmented label, .mp-profile-scope input[type="checkbox"] { min-height: 44px; }
    .mp-savebar { width: calc(100% - 1.5rem); flex-wrap: wrap; }
}
@media (max-width: 390px) {
    .mp-profile-scope { padding-left: 0; padding-right: 0; }
}

/* ==== Federation defaults WP2: /admin/users "Users and roles" (docs/specs/federation-defaults §7.5 +
   strength-meet-federation-create-mockup.html #page-roles) ====
   ADDITIVE ONLY — nothing above this comment is touched. Reuses --mp-* tokens and the existing
   .mp-card/.mp-btn/.mp-badge/.mp-table/.mp-auth-notice system; the dark control treatment is the same
   --mp-control-* recipe already used by .mp-setup-scope/.mp-auth-scope/.mp-profile-scope, scoped here so the
   admin filters get muted dark fields instead of harsh white ones without touching any other surface. */

.mp-adminroles-scope { width: 100%; }

.mp-adminroles-scope .form-control {
    display: block; width: 100%; min-height: 2.5rem; padding: 0 0.7rem; color: var(--mp-text);
    background: var(--mp-control-bg); border: 1px solid var(--mp-control-border); border-radius: 8px;
    box-shadow: inset 0 1px 1px rgba(0,0,0,0.2); outline: none;
    transition: border-color .14s ease, background-color .14s ease, box-shadow .14s ease;
}
.mp-adminroles-scope .form-control::placeholder { color: var(--mp-control-placeholder); opacity: 1; }
.mp-adminroles-scope .form-control:hover:not(:disabled) { background: var(--mp-control-bg-hover); border-color: #435164; }
.mp-adminroles-scope .form-control:focus-visible, .mp-adminroles-scope .form-control:focus {
    border-color: var(--mp-control-border-focus); background: #19212b;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-control-border-focus) 22%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-adminroles-scope select.form-control {
    appearance: none; -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, #7d8999 50%), linear-gradient(135deg, #7d8999 50%, transparent 50%);
    background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%; background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
    padding-right: 1.7rem;
}

.mp-adminroles-head { margin-bottom: 1rem; }
.mp-adminroles-head h1 { margin: 0 0 0.4rem; }
.mp-adminroles-eyebrow {
    margin: 0 0 0.35rem; color: var(--mp-accent); font-size: 0.68rem; font-weight: 850;
    text-transform: uppercase; letter-spacing: 0.1em;
}

.mp-adminroles-notice {
    border: 1px solid var(--mp-accent); border-radius: 10px; margin-bottom: 1rem; padding: 0.75rem 0.9rem;
    background: color-mix(in srgb, var(--mp-accent) 10%, var(--mp-surface));
}
.mp-adminroles-notice strong { display: block; font-size: 0.85rem; }
.mp-adminroles-notice p { margin: 0.25rem 0 0; color: var(--mp-muted); font-size: 0.8rem; }

/* Filters: a wrapping flex row so 320px stacks instead of forcing document-level horizontal overflow. */
.mp-adminroles-filters { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: flex-end; margin-bottom: 0.85rem; }
.mp-adminroles-field { flex: 1 1 11rem; min-width: 0; }
.mp-adminroles-field.search { flex: 2 1 16rem; }
.mp-adminroles-field label { display: block; margin-bottom: 0.3rem; color: var(--mp-muted); font-size: 0.78rem; font-weight: 700; }
.mp-adminroles-filters .mp-btn { flex: 0 0 auto; min-height: 2.5rem; }

/* The table is wide by nature (five columns incl. two action stacks); it scrolls inside its own card so the
   page body never does — same containment rule as .mp-mymeet's table wrapper. */
.mp-adminroles-tablewrap { padding: 0; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
.mp-adminroles-table { min-width: 46rem; }
.mp-adminroles-table td { vertical-align: top; }
.mp-adminroles-name { font-weight: 750; }
.mp-adminroles-sub { color: var(--mp-muted); font-size: 0.75rem; margin-top: 2px; word-break: break-word; }
.mp-adminroles-badges { display: flex; flex-wrap: wrap; gap: 0.35rem; }

/* Federation access state: the mock-up's switch pip, rendered decoratively (aria-hidden) next to real text so
   the state is never colour-only. */
.mp-adminroles-state { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.82rem; }
.mp-adminroles-switch {
    flex: 0 0 auto; width: 30px; height: 17px; border-radius: 999px; position: relative;
    background: var(--mp-surface-2); border: 1px solid var(--mp-border);
}
.mp-adminroles-switch::after {
    content: ""; position: absolute; top: 2px; left: 2px; width: 11px; height: 11px; border-radius: 50%;
    background: var(--mp-muted); transition: left .14s ease, background-color .14s ease;
}
.mp-adminroles-switch.on { background: color-mix(in srgb, var(--mp-good) 30%, transparent); border-color: var(--mp-good); }
.mp-adminroles-switch.on::after { left: 15px; background: var(--mp-good); }
.mp-adminroles-switch.locked { opacity: 0.75; }

.mp-adminroles-rolebtn { display: inline-block; margin-top: 0.5rem; font-size: 0.8rem; padding: 0.4rem 0.75rem; }
.mp-adminroles-confirm {
    margin-top: 0.5rem; padding: 0.6rem 0.7rem; border-radius: 9px;
    border: 1px solid var(--mp-accent); background: color-mix(in srgb, var(--mp-accent) 9%, var(--mp-surface-2));
    max-width: 22rem;
}
.mp-adminroles-confirm p { margin: 0 0 0.5rem; color: var(--mp-muted); font-size: 0.78rem; line-height: 1.5; }
.mp-adminroles-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.mp-adminroles-actions .mp-btn { font-size: 0.8rem; padding: 0.4rem 0.75rem; }

.mp-adminroles-cellstack { display: flex; flex-direction: column; gap: 0.35rem; min-width: 13.5rem; }
.mp-adminroles-hint { color: var(--mp-muted); font-size: 0.7rem; }
.mp-adminroles-lockrow { display: flex; gap: 0.35rem; }
.mp-adminroles-lockrow .form-control { min-width: 0; }

.mp-adminroles-foot { margin-top: 0.85rem; font-size: 0.78rem; }

@media (max-width: 640px) {
    .mp-adminroles-filters .mp-btn { width: 100%; }
    /* 44px touch targets on the role controls, matching the Setup/profile rules above. */
    .mp-adminroles-scope .form-control, .mp-adminroles-scope .mp-btn { min-height: 44px; }
}

/* ===== federation management (.mp-fed-*) =====
   Federation defaults WP3 (docs/specs/federation-defaults §7.1/§7.3/§7.4 + strength-meet-federation-create-
   mockup.html #page-federations / #page-editor). ADDITIVE ONLY — nothing above this comment is touched.
   Reuses --mp-* tokens and the existing .mp-card/.mp-btn/.mp-badge/.mp-table/.mp-notice/.mp-auth-notice/.mp-muted
   primitives; the muted dark field recipe is the SAME --mp-control-* tokens already used by .mp-setup-scope/
   .mp-adminroles-scope, scoped here under .mp-fed-scope so no other page is affected. 12px card radius comes
   from the shared .mp-card rule; every control below is 38px (2.375rem) minimum height on desktop and steps up
   to 44px under the touch media query, matching the Setup/admin-roles precedent. Usable at 320px: every wide
   table sits in its own horizontally-scrolling .mp-fed-tablewrap so the document itself never overflows. */

.mp-fed-scope { width: 100%; }

.mp-fed-scope .form-control {
    display: block; width: 100%; min-height: 2.375rem; padding: 0 0.7rem; color: var(--mp-text);
    background: var(--mp-control-bg); border: 1px solid var(--mp-control-border); border-radius: 7px;
    box-shadow: inset 0 1px 1px rgba(0,0,0,0.2); outline: none;
    transition: border-color .14s ease, background-color .14s ease, box-shadow .14s ease;
}
.mp-fed-scope textarea.form-control { min-height: 4.5rem; padding-top: 0.5rem; resize: vertical; }
.mp-fed-scope .form-control::placeholder { color: var(--mp-control-placeholder); opacity: 1; }
.mp-fed-scope .form-control:hover:not(:disabled) { background: var(--mp-control-bg-hover); border-color: #435164; }
.mp-fed-scope .form-control:focus-visible, .mp-fed-scope .form-control:focus {
    border-color: var(--mp-control-border-focus); background: #19212b;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-control-border-focus) 22%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-fed-scope .form-control:disabled { opacity: 0.6; cursor: not-allowed; }
.mp-fed-scope select.form-control {
    appearance: none; -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, #7d8999 50%), linear-gradient(135deg, #7d8999 50%, transparent 50%);
    background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%; background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
    padding-right: 1.7rem;
}

/* ---- page heading / metrics / filters (list + editor share these) ---- */
.mp-fed-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap; }
.mp-fed-head h1 { margin: 0 0 0.3rem; }
.mp-fed-head p { max-width: 48rem; }
.mp-fed-eyebrow { margin: 0 0 0.25rem; color: var(--mp-accent); font-size: 0.68rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.09em; }
.mp-fed-heading-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

.mp-fed-metric-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.6rem; margin-bottom: 0.9rem; }
.mp-fed-metric { padding: 0.7rem 0.75rem; border: 1px solid var(--mp-border); border-radius: 9px; background: var(--mp-surface); }
.mp-fed-metric strong { display: block; margin-bottom: 0.1rem; font-size: 1.25rem; line-height: 1; }
.mp-fed-metric span { color: var(--mp-muted); font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; }

.mp-fed-filters { display: grid; grid-template-columns: minmax(220px, 1.4fr) minmax(140px, 1fr) minmax(140px, 1fr) auto; gap: 0.6rem; align-items: end; margin-bottom: 0.85rem; }
.mp-fed-field { min-width: 0; }
.mp-fed-field label { display: block; margin-bottom: 0.3rem; color: var(--mp-muted); font-size: 0.78rem; font-weight: 700; }
.mp-fed-filters .mp-btn { min-height: 2.375rem; }

/* ---- list table ---- */
.mp-fed-tablewrap { padding: 0; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
.mp-fed-table { min-width: 52rem; }
.mp-fed-table td { vertical-align: top; }
.mp-fed-identity { display: flex; align-items: center; gap: 0.6rem; }
.mp-fed-logo-tile {
    width: 2.2rem; height: 2.2rem; flex: 0 0 auto; display: grid; place-items: center;
    border: 1px solid var(--mp-border); border-radius: 8px; color: var(--mp-accent); background: var(--mp-control-bg);
    font-weight: 800; font-size: 0.72rem;
}
.mp-fed-row-title { font-weight: 750; color: var(--mp-text); }
.mp-fed-row-sub { margin-top: 2px; color: var(--mp-muted); font-size: 0.72rem; }
.mp-fed-attention { color: var(--mp-accent); }
.mp-fed-badges { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.mp-fed-scope .mp-badge.draft { color: var(--mp-info); border-color: var(--mp-info); }
.mp-fed-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--mp-good); margin-right: 2px; }

.mp-fed-row-actions { display: flex; align-items: center; justify-content: flex-end; gap: 0.35rem; flex-wrap: wrap; }
.mp-fed-scope .mp-fed-btn-sm { min-height: 1.9rem; padding: 0 0.65rem; font-size: 0.78rem; }

.mp-fed-confirm {
    margin-top: 0.4rem; padding: 0.6rem 0.7rem; border: 1px solid var(--mp-border); border-radius: 8px;
    background: var(--mp-control-bg); min-width: 14rem;
}
.mp-fed-confirm p { margin: 0 0 0.5rem; color: var(--mp-muted); font-size: 0.78rem; line-height: 1.45; }

.mp-fed-archive-notice { margin-top: 0.9rem; }

/* ---- shared form grid (new-federation form + editor sections) ---- */
.mp-fed-form-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0.8rem; }
.mp-fed-f12 { grid-column: span 12; }
.mp-fed-f8 { grid-column: span 8; }
.mp-fed-f6 { grid-column: span 6; }
.mp-fed-f4 { grid-column: span 4; }
.mp-fed-f3 { grid-column: span 3; }
.mp-fed-form-grid label { display: block; margin-bottom: 0.3rem; color: var(--mp-muted); font-size: 0.75rem; font-weight: 700; }

/* ---- ruleset editor shell ---- */
.mp-fed-editor-shell { display: grid; grid-template-columns: 15.5rem minmax(0, 1fr); gap: 0.9rem; align-items: start; }
.mp-fed-editor-nav { position: sticky; top: 5rem; padding: 0.4rem; display: flex; flex-direction: column; gap: 0.15rem; }
.mp-fed-editor-nav a {
    display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
    padding: 0.55rem 0.6rem; border-radius: 7px; color: var(--mp-muted); text-decoration: none; font-size: 0.78rem; font-weight: 700;
}
.mp-fed-editor-nav a:hover, .mp-fed-editor-nav a:focus-visible { color: var(--mp-text); background: var(--mp-control-bg); outline: none; }
.mp-fed-editor-nav a em { min-width: 1.3rem; padding: 0.05rem 0.3rem; border: 1px solid var(--mp-border); border-radius: 999px; color: var(--mp-muted); font-size: 0.62rem; font-style: normal; text-align: center; }
.mp-fed-editor-body { min-width: 0; display: flex; flex-direction: column; gap: 0.9rem; }
.mp-fed-sec { scroll-margin-top: 5rem; }
.mp-fed-sec-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.6rem; }
.mp-fed-sec h2 { margin: 0 0 0.2rem; font-size: 1.02rem; }

.mp-fed-draft-banner {
    display: flex; align-items: center; justify-content: space-between; gap: 0.9rem; flex-wrap: wrap;
    margin-bottom: 0.9rem; padding: 0.65rem 0.75rem; border: 1px solid var(--mp-info); border-radius: 9px;
    background: color-mix(in srgb, var(--mp-info) 8%, transparent);
}
.mp-fed-draft-banner p { margin: 0.15rem 0 0; }
.mp-fed-readonly-notice { margin-bottom: 0.9rem; }

/* ---- overall matrix generator ---- */
.mp-fed-matrix-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.mp-fed-matrix-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.7rem; }
.mp-fed-matrix-count {
    margin-top: 0.7rem; align-items: flex-start;
}
.mp-fed-matrix-count span { font-weight: 800; color: var(--mp-accent); }

/* ---- review section ---- */
.mp-fed-review-list { display: grid; gap: 0; }
.mp-fed-review-row { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; padding: 0.5rem 0; border-bottom: 1px solid var(--mp-border); }
.mp-fed-review-row:last-child { border-bottom: 0; }
.mp-fed-review-row span { color: var(--mp-muted); font-size: 0.78rem; }
.mp-fed-status-good { color: var(--mp-good); }
.mp-fed-status-warn { color: var(--mp-accent); }
.mp-fed-status-bad { color: var(--mp-nolift); }
.mp-fed-issue-list { margin: 0.7rem 0 0; padding-left: 1.1rem; font-size: 0.8rem; line-height: 1.6; }
.mp-fed-publish-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.8rem; }

.mp-fed-savebar {
    position: sticky; bottom: 0.8rem; z-index: 5; display: flex; justify-content: flex-end;
    padding: 0.6rem; border: 1px solid var(--mp-border); border-radius: 10px; background: var(--mp-surface);
    box-shadow: 0 10px 30px rgba(0,0,0,0.3);
}

@media (max-width: 1040px) {
    .mp-fed-editor-shell { grid-template-columns: 1fr; }
    .mp-fed-editor-nav { position: static; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.3rem; }
    .mp-fed-editor-nav a { flex-direction: column; text-align: center; gap: 0.2rem; }
}
@media (max-width: 760px) {
    .mp-fed-metric-grid { grid-template-columns: repeat(3, 1fr); }
    .mp-fed-filters { grid-template-columns: 1fr 1fr; }
    .mp-fed-filters .search { grid-column: 1 / -1; }
    .mp-fed-f8, .mp-fed-f6, .mp-fed-f4, .mp-fed-f3 { grid-column: span 12; }
    .mp-fed-editor-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mp-fed-head { align-items: flex-start; flex-direction: column; }
    .mp-fed-heading-actions { width: 100%; }
    .mp-fed-heading-actions .mp-btn { flex: 1; }
}
@media (max-width: 480px) {
    .mp-fed-metric-grid { grid-template-columns: repeat(2, 1fr); }
    .mp-fed-filters { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
    /* 44px touch targets, matching the Setup/admin-roles precedent. */
    .mp-fed-scope .form-control, .mp-fed-scope .mp-btn, .mp-fed-scope input[type="checkbox"] { min-height: 44px; }
    .mp-fed-scope .mp-fed-btn-sm { min-height: 2.4rem; }
    .mp-fed-savebar .mp-btn { width: 100%; }
}
/* ===== meet creation (.mp-create-*) =====
   Federation defaults WP4 (docs/specs/federation-defaults §7.1/§7.2; visual reference
   strength-meet-federation-create-mockup.html "Create meet"). Appended block, every class prefixed .mp-create-, every
   colour a --mp-* token. Deliberately NO max-width anywhere: the page sits directly inside .mp-container and honours
   the global wide/narrow toggle (spec §7.1 "remove the page-local max-width:860px").

   The control styling mirrors the Setup tab's muted-field family (.mp-setup-scope) rather than reusing that class, so
   /meets/create picks up the same dark field surface, 38px minimum height, 7px radius and accent focus ring without
   inheriting the Setup shell's savebar padding or grid. */
.mp-create-scope .form-control {
    display: block; width: 100%; min-height: 38px; padding: 0 0.65rem; color: var(--mp-text);
    background: var(--mp-control-bg); border: 1px solid var(--mp-control-border); border-radius: 7px;
    box-shadow: inset 0 1px 1px rgba(0,0,0,0.2); outline: none;
    transition: border-color .14s ease, background-color .14s ease, box-shadow .14s ease;
}
.mp-create-scope .form-control::placeholder { color: var(--mp-control-placeholder); opacity: 1; }
.mp-create-scope .form-control:hover:not(:disabled):not([readonly]) { background: var(--mp-control-bg-hover); border-color: #435164; }
.mp-create-scope .form-control:focus, .mp-create-scope .form-control:focus-visible {
    border-color: var(--mp-control-border-focus); background: #19212b;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-control-border-focus) 22%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-create-scope .form-control[readonly] { color: var(--mp-muted); background: color-mix(in srgb, var(--mp-control-bg) 70%, var(--mp-bg)); border-style: dashed; }
.mp-create-scope .form-control.invalid, .mp-create-scope .form-control[aria-invalid="true"] {
    border-color: var(--mp-nolift);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mp-nolift) 18%, transparent), inset 0 1px 1px rgba(0,0,0,0.2);
}
.mp-create-scope select.form-control {
    appearance: none; -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, #7d8999 50%), linear-gradient(135deg, #7d8999 50%, transparent 50%);
    background-position: calc(100% - 15px) 52%, calc(100% - 10px) 52%; background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
    padding-right: 1.7rem;
}
.mp-create-scope input[type="checkbox"] { accent-color: var(--mp-accent); width: 15px; height: 15px; }
.mp-create-scope .validation-message { display: block; margin-top: 0.3rem; color: var(--mp-nolift); font-size: 0.78rem; font-weight: 700; }

/* ---- layout: ~70/30 with a sticky summary, one column below 1040px (spec §7.2) ---- */
.mp-create-layout {
    display: grid; grid-template-columns: minmax(0, 1.75fr) minmax(290px, 0.68fr);
    gap: 1rem; align-items: start; width: 100%;
}
.mp-create-main { min-width: 0; }
.mp-create-aside { min-width: 0; }
.mp-create-sticky { position: sticky; top: 1rem; }
@media (max-width: 1040px) {
    .mp-create-layout { grid-template-columns: 1fr; }
    .mp-create-sticky { position: static; }
}

/* ---- cards ---- */
.mp-create-card { padding: 0.95rem 1.05rem 1.1rem; margin-bottom: 0.9rem; }
.mp-create-card .mp-card-head { margin-bottom: 0.85rem; }
.mp-create-cardtitle { display: flex; align-items: flex-start; gap: 0.65rem; min-width: 0; }
.mp-create-cardtitle h2 { margin: 0; font-size: 1.02rem; letter-spacing: -0.015em; }
.mp-create-cardtitle p { margin: 0.15rem 0 0; font-size: 0.78rem; }
.mp-create-cardicon {
    width: 31px; height: 31px; flex: 0 0 auto; display: grid; place-items: center;
    border: 1px solid var(--mp-control-border); border-radius: 8px;
    color: var(--mp-accent); background: var(--mp-surface-2); font-weight: 800; font-size: 0.8rem;
}

/* ---- ruleset picker + preview ---- */
.mp-create-picker {
    display: grid; grid-template-columns: minmax(220px, 0.8fr) minmax(0, 1.2fr); gap: 0.9rem;
    padding: 0.85rem; border: 1px solid var(--mp-control-border); border-radius: 10px;
    background: linear-gradient(105deg, color-mix(in srgb, var(--mp-accent) 9%, transparent), transparent 45%), var(--mp-surface-2);
}
.mp-create-preview { min-width: 0; padding-left: 0.85rem; border-left: 1px solid var(--mp-border); }
.mp-create-preview-line { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.5rem; }
.mp-create-preview-name { font-size: 0.95rem; font-weight: 750; }
.mp-create-preview-meta { color: var(--mp-muted); font-size: 0.78rem; }
.mp-create-badges { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.mp-create-badges .mp-badge { font-size: 0.68rem; text-transform: none; letter-spacing: 0; }
@media (max-width: 760px) {
    .mp-create-picker { grid-template-columns: 1fr; }
    .mp-create-preview { padding: 0.8rem 0 0; border-left: 0; border-top: 1px solid var(--mp-border); }
}

/* ---- skeleton (selector not yet resolved) ---- */
.mp-create-skeleton { display: grid; gap: 0.5rem; padding: 0.85rem; border: 1px solid var(--mp-border); border-radius: 10px; }
.mp-create-skeleton-bar { display: block; height: 38px; border-radius: 7px; background: var(--mp-surface-2); }
.mp-create-skeleton-bar.short { width: 55%; height: 14px; }

/* ---- notices ---- */
.mp-create-notice, .mp-create-alert {
    display: flex; gap: 0.6rem; margin-top: 0.75rem; padding: 0.65rem 0.7rem;
    border: 1px solid var(--mp-border); border-radius: 8px;
    color: var(--mp-muted); background: var(--mp-surface-2); font-size: 0.8rem; line-height: 1.5;
}
.mp-create-notice strong, .mp-create-alert strong { color: var(--mp-text); }
.mp-create-notice.info { border-color: color-mix(in srgb, var(--mp-info) 45%, transparent); background: color-mix(in srgb, var(--mp-info) 9%, transparent); }
.mp-create-notice.warning { border-color: color-mix(in srgb, var(--mp-accent) 45%, transparent); background: color-mix(in srgb, var(--mp-accent) 9%, transparent); }
.mp-create-alert { margin: 0 0 1rem; border-color: var(--mp-nolift); background: color-mix(in srgb, var(--mp-nolift) 12%, transparent); }
.mp-create-notice-icon { flex: 0 0 auto; color: var(--mp-accent); font-weight: 800; }
.mp-create-alert .mp-create-notice-icon { color: var(--mp-nolift); }

/* ---- 12-column form grid (mock-up f12/f8/f6/f4/f3 spans) ---- */
.mp-create-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0.8rem; }
.mp-create-field { min-width: 0; grid-column: span 12; }
.mp-create-f12 { grid-column: span 12; }
.mp-create-f8 { grid-column: span 8; }
.mp-create-f6 { grid-column: span 6; }
.mp-create-f4 { grid-column: span 4; }
.mp-create-f3 { grid-column: span 3; }
.mp-create-field label { display: block; margin-bottom: 0.3rem; color: #a0aaba; font-size: 0.72rem; font-weight: 720; }
.mp-create-field label span { color: var(--mp-muted); font-weight: 550; }
.mp-create-help { margin-top: 0.3rem; color: var(--mp-muted); font-size: 0.7rem; }
@media (max-width: 760px) {
    .mp-create-f8, .mp-create-f6, .mp-create-f4, .mp-create-f3 { grid-column: span 12; }
}

/* ---- sticky summary ---- */
.mp-create-summary-list { display: grid; gap: 0; margin-top: 0.55rem; }
.mp-create-summary-row {
    display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem;
    padding: 0.5rem 0; border-bottom: 1px solid var(--mp-border);
}
.mp-create-summary-row:last-child { border-bottom: 0; }
.mp-create-summary-row span { color: var(--mp-muted); font-size: 0.75rem; }
.mp-create-summary-row strong { min-width: 0; text-align: right; font-size: 0.8rem; overflow-wrap: anywhere; }
.mp-create-check { display: flex; align-items: flex-start; gap: 0.5rem; margin-top: 0.7rem; color: var(--mp-muted); font-size: 0.75rem; line-height: 1.5; }
.mp-create-actions { display: grid; gap: 0.5rem; margin-top: 0.9rem; }
.mp-create-actions .mp-btn { width: 100%; min-height: 36px; text-align: center; }
.mp-create-foot { margin: 0.7rem 0 0; color: var(--mp-muted); font-size: 0.7rem; text-align: center; }

@media (max-width: 640px) {
    /* 44px touch targets, matching the Setup/profile/admin rules above. */
    .mp-create-scope .form-control, .mp-create-scope .mp-btn { min-height: 44px; }
    .mp-create-card { padding: 0.85rem 0.9rem 1rem; }
}

/* ==== Email notifications WP4 (spec §4, §9) — Communications workspace, settings, composer, providers ====
   Everything below is scoped under .mp-comms-scope (CommunicationsPanel's outer wrapper, plus the Setup tab's
   compact CommsSummaryCard and the results-publish dialog's email option). Reuses --mp-* tokens and the existing
   .mp-card/.mp-btn/.mp-badge/.mp-table/.mp-toggle-line/.mp-overflow/.mp-muted/.form-control system — no new CSS
   framework, no copy from the mock-up's own :root variables (WP0 §1.3). Breakpoints per spec §9: desktop >=1280
   (default), tablet 768-1279, mobile <=767 — no new fixed page max-width is introduced. */

.mp-comms-scope { width: 100%; max-width: none; }
.mp-comms-scope .mp-muted { color: var(--mp-muted); }

.mp-comms-view-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.85rem; }
.mp-comms-view-head h2 { margin: 0 0 0.2rem; }
.mp-comms-header-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }

.mp-comms-status { border-radius: 10px; padding: 0.7rem 0.9rem; font-weight: 700; margin-bottom: 0.75rem; }
.mp-comms-status.success { border: 1px solid var(--mp-good); color: var(--mp-good); background: color-mix(in srgb, var(--mp-good) 12%, var(--mp-surface)); }
.mp-comms-status.error { border: 1px solid var(--mp-nolift); color: var(--mp-nolift); background: color-mix(in srgb, var(--mp-nolift) 12%, var(--mp-surface)); }
.mp-comms-status.warn { border: 1px solid var(--mp-accent); color: var(--mp-accent); background: color-mix(in srgb, var(--mp-accent) 12%, var(--mp-surface)); font-weight: 700; padding: 0.4rem 0.6rem; border-radius: 8px; }

.mp-comms-scope .mp-banner {
    display: flex; gap: 0.7rem; align-items: flex-start; border-radius: 10px; padding: 0.75rem 0.9rem;
    margin-bottom: 0.85rem; border: 1px solid color-mix(in srgb, var(--mp-info, #4da3ff) 40%, var(--mp-border));
    background: color-mix(in srgb, var(--mp-info, #4da3ff) 8%, var(--mp-surface));
}
.mp-comms-scope .mp-banner.warn { border-color: color-mix(in srgb, var(--mp-accent) 45%, var(--mp-border)); background: color-mix(in srgb, var(--mp-accent) 9%, var(--mp-surface)); }
.mp-comms-scope .mp-banner.bad { border-color: color-mix(in srgb, var(--mp-nolift) 45%, var(--mp-border)); background: color-mix(in srgb, var(--mp-nolift) 9%, var(--mp-surface)); }
.mp-comms-scope .mp-banner b { display: block; margin-bottom: 0.15rem; }

.mp-comms-grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; align-items: start; }
.mp-comms-grid4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.85rem; }
.mp-comms-two-col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 0.85rem; }
.mp-comms-full { grid-column: 1 / -1; }

.mp-comms-metric-value { font-size: 1.35rem; font-weight: 850; margin: 0.35rem 0 0.3rem; }
.mp-comms-section-title { display: flex; align-items: center; justify-content: space-between; gap: 0.85rem; margin-bottom: 0.5rem; flex-wrap: wrap; }
.mp-comms-section-title h3 { margin: 0; }
.mp-comms-row-actions { display: flex; gap: 0.5rem; white-space: nowrap; }
.mp-comms-footer-actions { display: flex; justify-content: flex-end; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.9rem; padding-top: 0.85rem; border-top: 1px solid var(--mp-border); }
.mp-comms-savebar { display: flex; justify-content: flex-end; margin-top: 1rem; }

.mp-comms-scope .mp-title { font-weight: 760; }
.mp-comms-table-wrap { overflow-x: auto; }

.mp-comms-provider-row {
    display: flex; align-items: center; gap: 0.75rem; padding: 0.7rem 0.85rem; border: 1px solid var(--mp-border);
    border-radius: 10px; margin-bottom: 0.5rem; cursor: pointer; text-decoration: none; color: inherit;
}
.mp-comms-provider-row.selected { border-color: var(--mp-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--mp-accent) 12%, transparent); }
.mp-comms-provider-row input[type="radio"] { width: 1.05rem; height: 1.05rem; accent-color: var(--mp-accent); flex: 0 0 auto; }
.mp-comms-provider-row > span.mp-badge { margin-left: auto; }

.mp-comms-rule { display: grid; grid-template-columns: 42px minmax(0, 1fr) auto; align-items: start; gap: 0.85rem; padding: 0.85rem 0; border-top: 1px solid var(--mp-border); }
.mp-comms-rule:first-of-type { border-top: 0; }
.mp-comms-rule h4 { margin: 0 0 0.2rem; }
.mp-comms-rule p { margin: 0; }
.mp-comms-rule-icon { width: 1.8rem; height: 1rem; }
.mp-comms-rule > a.mp-linkbtn { white-space: nowrap; }
@media (max-width: 767px) {
    .mp-comms-rule { grid-template-columns: 42px minmax(0, 1fr); }
    .mp-comms-rule > a.mp-linkbtn { grid-column: 2; }
}

.mp-comms-recipients { margin-top: 0.6rem; display: flex; flex-direction: column; gap: 0.4rem; max-width: 26rem; }
.mp-comms-recipient-row { display: flex; align-items: center; gap: 0.5rem; }
.mp-comms-recipient-row .form-control { flex: 1 1 auto; }

.mp-comms-chip-row { display: flex; gap: 0.45rem; flex-wrap: wrap; margin: 0.4rem 0 0.7rem; }
.mp-comms-chip {
    display: inline-flex; align-items: center; gap: 0.35rem; border: 1px solid var(--mp-border); background: var(--mp-surface-2);
    color: var(--mp-muted); border-radius: 999px; padding: 0.4rem 0.7rem; cursor: pointer; font-size: 0.82rem;
}
.mp-comms-chip.selected { border-color: var(--mp-accent); color: var(--mp-text); background: color-mix(in srgb, var(--mp-accent) 10%, var(--mp-surface-2)); }
.mp-comms-chip input[type="checkbox"] { accent-color: var(--mp-accent); }

.mp-comms-count {
    display: flex; gap: 0.85rem; align-items: center; padding: 0.7rem 0.8rem; border-radius: 10px;
    border: 1px solid color-mix(in srgb, var(--mp-info, #4da3ff) 30%, var(--mp-border));
    background: color-mix(in srgb, var(--mp-info, #4da3ff) 7%, var(--mp-surface)); margin: 0.6rem 0;
}
.mp-comms-count strong { font-size: 1.35rem; }

.mp-comms-review { display: grid; grid-template-columns: 8rem 1fr; gap: 0.5rem 0.6rem; margin: 0; }
.mp-comms-review dt { color: var(--mp-muted); }
.mp-comms-review dd { margin: 0; overflow-wrap: anywhere; }

.mp-comms-radio-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.mp-comms-radio-choice {
    display: inline-flex; align-items: center; gap: 0.4rem; border: 1px solid var(--mp-border); border-radius: 9px;
    padding: 0.5rem 0.75rem; cursor: pointer; font-size: 0.85rem;
}
.mp-comms-radio-choice.selected { border-color: var(--mp-accent); background: color-mix(in srgb, var(--mp-accent) 8%, transparent); }
.mp-comms-radio-choice input[type="radio"] { accent-color: var(--mp-accent); }

.mp-comms-editor-tools {
    display: flex; gap: 0.2rem; flex-wrap: wrap; align-items: center; border: 1px solid var(--mp-border);
    border-bottom: 0; border-radius: 9px 9px 0 0; padding: 0.35rem; background: var(--mp-surface-2);
}
.mp-comms-editor-tools button {
    border: 0; background: transparent; color: var(--mp-muted); padding: 0.3rem 0.5rem; border-radius: 5px; cursor: pointer;
}
.mp-comms-editor-tools button:hover { color: var(--mp-text); background: var(--mp-surface-3, var(--mp-surface)); }
.mp-comms-editor-tools select {
    margin-left: auto; background: var(--mp-control-bg); color: var(--mp-text); border: 1px solid var(--mp-control-border);
    border-radius: 6px; padding: 0.2rem 0.4rem; font-size: 0.8rem;
}
.mp-comms-editor-textarea { border-radius: 0 0 9px 9px !important; }

.mp-comms-preview-body { border: 1px solid var(--mp-border); border-radius: 8px; padding: 0.75rem 0.9rem; background: var(--mp-surface-2); }
.mp-comms-preview-body p { margin: 0 0 0.6rem; }
.mp-comms-preview-body p:last-child { margin-bottom: 0; }

.mp-comms-webhook-reveal { border-color: var(--mp-accent); margin-bottom: 0.85rem; }
.mp-comms-reveal-row { display: flex; gap: 0.5rem; align-items: center; }
.mp-comms-reveal-row .form-control { flex: 1 1 auto; font-family: monospace; font-size: 0.8rem; }

.mp-comms-summary-card .mp-comms-summary-list { display: grid; grid-template-columns: auto 1fr; gap: 0.35rem 0.7rem; margin: 0.5rem 0 0.85rem; font-size: 0.85rem; }
.mp-comms-summary-card dt { color: var(--mp-muted); }
.mp-comms-summary-card dd { margin: 0; }

/* Native <dialog> chrome — same shape as ResultsWorkspace's mp-rw-dialog, kept as an independent class here so
   this feature never depends on another feature's CSS-isolated stylesheet (which would not even apply, since
   isolation scopes rules to elements ResultsWorkspace itself renders). */
.mp-comms-dialog {
    background: var(--mp-surface); color: var(--mp-text); border: 1px solid var(--mp-border);
    border-radius: 12px; padding: 1.25rem 1.4rem; width: min(30rem, calc(100vw - 2rem)); max-width: 30rem;
}
.mp-comms-dialog::backdrop { background: rgba(0, 0, 0, 0.55); }
.mp-comms-dialog h3 { margin-top: 0; }
.mp-comms-dialog-wide { width: min(46rem, calc(100vw - 2rem)); max-width: 46rem; max-height: calc(100vh - 4rem); overflow-y: auto; }

.mp-comms-entry-picker { margin: 0.6rem 0; padding-top: 0.5rem; border-top: 1px dashed var(--mp-border); }
.mp-comms-entry-search { margin: 0.5rem 0 0.75rem; max-width: 24rem; }

/* Mobile card fallback for tables (mock-up pattern, spec §9) — hidden by default, swapped in under the mobile
   breakpoint below. */
.mp-comms-mobile-cards { display: none; }
.mp-comms-mobile-row { border: 1px solid var(--mp-border); background: var(--mp-surface-2); padding: 0.75rem; border-radius: 10px; margin-bottom: 0.5rem; }
.mp-comms-mobile-split { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; margin-top: 0.4rem; }

/* ---- tablet (768-1279px) ---- */
@media (max-width: 1279px) {
    .mp-comms-grid4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- mobile (<=767px) ---- */
@media (max-width: 767px) {
    .mp-comms-grid2, .mp-comms-two-col, .mp-comms-grid4 { grid-template-columns: 1fr; }
    .mp-comms-full { grid-column: auto; }
    .mp-comms-view-head { flex-direction: column; align-items: stretch; }
    .mp-comms-header-actions { width: 100%; }
    .mp-comms-header-actions .mp-btn { flex: 1 1 auto; text-align: center; }
    .mp-comms-desktop-table { display: none; }
    .mp-comms-mobile-cards { display: block; }
    .mp-comms-review { grid-template-columns: 1fr; gap: 0.15rem; }
    .mp-comms-review dd { margin-bottom: 0.5rem; }
    .mp-comms-dialog { padding: 1rem; }
}

/* ---- Email notifications WP6: pre-start locked-board panel (LockedBoardPanel.razor) ----
   Shared by Scoreboard/PlatformDisplay/WarmupScreen/RunMeet — everything renders around it (roster/grid shape
   stays visible; see each page's own hidden-cell rendering), so this is a quiet inline card, not a full takeover. */
.mp-lock-panel {
    display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.4rem;
    padding: 1.6rem 1.2rem; margin: 0.75rem 0; border: 1px dashed var(--mp-border); border-radius: 12px;
    background: var(--mp-surface-2);
}
.mp-lock-panel .mp-lock-icon { font-size: 1.8rem; line-height: 1; }
.mp-lock-panel b { font-size: 1.05rem; }
.mp-lock-panel .mp-lock-sub { color: var(--mp-muted); font-size: 0.85rem; max-width: 36rem; }

/* OBS-safe variant (Overlay.razor): no opaque backdrop over the transparent canvas, thin accent border, small
   footprint centred over whatever the scene composites behind it. */
.mp-ovl-lock-panel {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.5rem;
    position: fixed; left: 50%; top: 46%; transform: translate(-50%, -50%); z-index: 20;
    padding: 1.2rem 1.6rem; border-radius: 12px; text-align: center; max-width: 26rem;
    background: color-mix(in srgb, var(--mp-bg, #0d1117) 74%, transparent);
    border: 1px solid color-mix(in srgb, var(--mp-accent, #f0a500) 45%, transparent);
    color: var(--mp-text, #e6edf3);
}
.mp-ovl-lock-panel .mp-ovl-lock-icon { font-size: 2rem; }
.mp-ovl-lock-panel b { font-size: 1rem; }
.mp-ovl-lock-panel .mp-lock-sub { font-size: 0.78rem; opacity: 0.85; }
