/* ============================================================
   Shared components — cards, buttons, badges, forms, tables,
   brackets, votes, modals, alerts, scores.
   Tokens only; status/score hues use Bootstrap palette vars.
   ============================================================ */

/* ===== PUBLIC EVENT CARDS ===== */
.scb-card {
    background: var(--color-surface);
    border: 1px solid color-mix(in srgb, var(--color-text) 10%, transparent);
    border-radius: var(--radius);
    overflow: hidden;
    transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
    position: relative;
}
.scb-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--color-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s ease;
}
.scb-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 12px 40px color-mix(in srgb, black 40%, transparent), 0 0 30px var(--color-accent-glow);
    border-color: color-mix(in srgb, var(--color-accent) 20%, transparent);
}
.scb-card:hover::before { transform: scaleX(1); }
.scb-card-banner {
    height: 200px;
    background: linear-gradient(135deg, var(--color-surface-2), var(--color-bg));
    position: relative;
    overflow: hidden;
}
.scb-card-banner img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.4s ease;
}
.scb-card:hover .scb-card-banner img { transform: scale(1.05); }
.scb-card-body { padding: 1.5rem; }
.scb-card-title {
    font-family: var(--font-display);
    font-size: 1.3rem;
    text-transform: uppercase;
    color: var(--color-on-surface);
    margin-bottom: 0.5rem;
}
.scb-card-meta {
    font-size: 0.85rem;
    color: var(--color-muted);
}
.scb-card-meta i { color: var(--color-accent); margin-right: 0.25rem; }

/* ===== PUBLIC STATUS BADGES ===== */
.scb-badge {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    border-radius: 2px;
}
.scb-badge-live { background: var(--color-accent); color: var(--color-on-accent); }
.scb-badge-upcoming { background: var(--bs-blue); color: #FFFFFF; }
.scb-badge-registration { background: var(--bs-cyan); color: #000; }
.scb-badge-finished { background: var(--color-border); color: var(--color-text); }

/* #1154 — Bootstrap's yellow and cyan badge fills are light on every theme, so
   their text is near-black, as .btn-warning / .btn-info / .text-bg-* have it.
   The #294 legibility remaps turn .text-dark into the theme's text colour
   (near-white on the dark themes: 1.2-1.5:1 on yellow) and a plain .badge is
   white (1.96:1 on cyan). These selectors outrank both remaps, which are
   !important at (0,1,0) and (0,2,0). #1186: Bootstrap's light fill
   (#F8F9FA) too: the schedule's white "Registration" badge was 1.05:1 on
   every theme, and .text-dark on it the theme's text (near-white on the
   dark themes). */
.badge.bg-warning,
.badge.bg-warning.text-dark,
.badge.bg-info,
.badge.bg-info.text-dark,
.badge.bg-light,
.badge.bg-light.text-dark { color: #000 !important; }
/* #1200 — "In the draft" on /me/events sat beside "Checked in" in the same
   cyan. Its own fill (Bootstrap's purple), the same on every theme, with
   white text (6.5:1); !important beats the light themes' on-accent badge
   text, as the rules above do. */
.badge.scb-badge-draft { background-color: #6F42C1; color: #fff !important; }

/* ===== PUBLIC BUTTONS ===== */
.scb-btn {
    display: inline-block;
    padding: 0.7rem 1.8rem;
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    text-decoration: none;
    border: none;
    cursor: pointer;
    transition: all var(--transition);
}
.scb-btn-primary {
    background: var(--color-accent);
    color: var(--color-on-accent);
    clip-path: polygon(8px 0%, 100% 0%, calc(100% - 8px) 100%, 0% 100%);
}
.scb-btn-primary:hover {
    background: var(--color-accent-hot-fill);
    color: var(--color-on-accent);
    transform: scale(1.03);
}
.scb-btn-primary.scb-btn-live {
    background: var(--color-accent-hot-fill);
}
.scb-btn-outline {
    background: transparent;
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}
.scb-btn-outline:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
}
.scb-btn-amber {
    background: var(--color-warn);
    color: var(--color-bg);
    clip-path: polygon(8px 0%, 100% 0%, calc(100% - 8px) 100%, 0% 100%);
}

/* ===== PUBLIC FORM STYLING ===== */
.scb-form .form-control, .scb-form .form-select {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    color: var(--color-text);
    border-radius: var(--radius);
    padding: 0.65rem 1rem;
    font-family: var(--font-body);
}
.scb-form .form-control:focus, .scb-form .form-select:focus {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 0.2rem var(--color-accent-glow);
    background: var(--color-surface-2);
    color: var(--scb-chalk);
}
.scb-form .form-label {
    color: var(--color-text);
    font-weight: 500;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.scb-form .form-check-input:checked { background-color: var(--color-accent); border-color: var(--color-accent); }

.scb-public .form-control,
.scb-public .form-select {
    background: var(--color-surface-2);
    border: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
    color: var(--color-text);
    border-radius: var(--radius);
}
.scb-public .form-control:focus,
.scb-public .form-select:focus {
    background: var(--color-surface-2);
    border-color: var(--color-accent);
    color: var(--color-text);
    box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--color-accent) 15%, transparent);
}
.scb-public .form-control::placeholder { color: var(--color-border); }
.scb-public .form-check-input {
    background-color: var(--color-surface-2);
    border-color: color-mix(in srgb, var(--color-text) 15%, transparent);
}
.scb-public .form-check-input:checked {
    background-color: var(--color-accent);
    border-color: var(--color-accent);
}
.scb-public .alert { border-radius: var(--radius); }

/* ===== APP CARDS ===== */
.bb-card {
    background: var(--color-surface);
    border: 1px solid var(--bb-border-soft);
    border-radius: var(--radius);
}
.bb-card .card-body { padding: 1.25rem; }
.bb-card .card-header {
    padding: 0.85rem 1.25rem;
    background: transparent;
    border-bottom: 1px solid var(--bb-border-soft);
}
.bb-card .card-header h5 {
    font-size: 0.95rem;
    font-weight: 700;
    margin: 0;
    color: var(--color-text);
}
.bb-card .card-footer {
    padding: 0.85rem 1.25rem;
    background: transparent;
    border-top: 1px solid var(--bb-border-soft);
}

/* Card header override */
.card-header {
    background: transparent;
    border-bottom: 1px solid var(--bb-border-soft);
}

/* ===== APP BUTTONS ===== */
.bb-btn { background: var(--color-accent); border: none; font-weight: 600; }
/* #1215: on an outline button (the pay pages' "Back to the event", the
   logout page's Cancel) the accent fill sat under the outline's muted label,
   1.0-1.9:1 on every theme, and Cancel looked like the Log out button. An
   outline .bb-btn keeps Bootstrap's transparent fill and its border; the
   hover and active fills (.btn:hover, (0,2,0)) still outrank this. */
.bb-btn:where([class*="btn-outline-"]) {
    background: transparent;
    border: var(--bs-btn-border-width) solid var(--bs-btn-border-color);
}
.btn-primary {
    --bs-btn-bg: var(--color-accent);
    --bs-btn-border-color: var(--color-accent);
    --bs-btn-hover-bg: var(--color-accent-hot);
    --bs-btn-hover-border-color: var(--color-accent-hot);
    --bs-btn-active-bg: var(--color-accent-hot);
    --bs-btn-active-border-color: var(--color-accent-hot);
    --bs-btn-disabled-bg: var(--color-accent);
    --bs-btn-disabled-border-color: var(--color-accent);
}
.btn-outline-primary {
    --bs-btn-color: var(--color-accent-text);
    --bs-btn-border-color: var(--color-accent);
    --bs-btn-hover-bg: var(--color-accent);
    --bs-btn-hover-border-color: var(--color-accent);
    --bs-btn-hover-color: var(--color-on-accent);
    --bs-btn-active-bg: var(--color-accent);
    --bs-btn-active-border-color: var(--color-accent);
}
.btn-xs { padding: 2px 6px; font-size: 0.75rem; }
.btn { border-radius: var(--radius-sm); }
.btn-sm { padding: 0.3rem 0.65rem; font-size: 0.825rem; }
/* #1155: the danger red as text takes the theme's shade; fills keep #DC3545.
   html[data-theme] (0,1,1) outranks Bootstrap's own !important .text-danger. */
html[data-theme] .text-danger {
    color: var(--color-danger-text) !important;
}
/* The sidebar's Factory Reset item kept the active item's hot accent on its
   own page (3.4:1 under live's accent). html[data-theme] (0,5,1) outranks the
   light themes' active-item rule (0,4,1, #1173). Its icon chip is the danger
   fill under white, not danger text on the accent chip (1.1-2.0:1). */
html[data-theme] .bb-sidebar .list-group-item.active.text-danger,
html[data-theme] .bb-sidebar .list-group-item.active.text-danger i {
    color: var(--color-danger-text) !important;
}
html[data-theme] .bb-sidebar .list-group-item.active.text-danger i:first-child {
    background: #DC3545;
    color: #FFFFFF !important;
}
html[data-theme] .link-danger {
    color: var(--color-danger-text) !important;
    text-decoration-color: var(--color-danger-text) !important;
}
.btn-outline-danger {
    --bs-btn-color: var(--color-danger-text);
    --bs-btn-disabled-color: var(--color-danger-text);
}
/* #1194: the success green as text and outline takes the theme's shade, as
   the danger red does; fills (.btn-success, .bg-success, the outline hover)
   keep #198754. The score colours are set with the score rules below. */
html[data-theme] .text-success {
    color: var(--color-ok-text) !important;
}
html[data-theme] .link-success {
    color: var(--color-ok-text) !important;
    text-decoration-color: var(--color-ok-text) !important;
}
.btn-outline-success {
    --bs-btn-color: var(--color-ok-text);
    --bs-btn-border-color: var(--color-ok-text);
    --bs-btn-disabled-color: var(--color-ok-text);
    --bs-btn-disabled-border-color: var(--color-ok-text);
}
/* Bootstrap's contextual table rows are light on every theme (the battles
   page's tie row is .table-warning, #FFF3CD, and its live row .table-danger):
   the dark themes' light green was 1.9:1 there (#1194), and their danger,
   warning, info and muted text 1.2-2.9:1 (#1203). Inside them the status text
   takes a dark shade of the light themes' hue that reads at 4.5:1 or better
   on every row background, striped, hovered and active included (#B02A37 was
   4.1:1 on a hovered row, #0B7285 4.2:1 on a danger row). */
html[data-theme] .table-primary,
html[data-theme] .table-secondary,
html[data-theme] .table-success,
html[data-theme] .table-danger,
html[data-theme] .table-warning,
html[data-theme] .table-info,
html[data-theme] .table-light {
    --color-ok-text: #125F3B;
    --color-danger-text: #9B2531;
    --color-warn-text: #893C0D;
    --color-info-text: #095A69;
}
/* The dark scheme leaves .text-warning, .text-info and their outline buttons
   on Bootstrap's own colours, and .text-muted and the outline-secondary text
   on the page's muted grey; inside a light row they take the row's shades. The outline-danger border follows
   its text there (Bootstrap's #DC3545 border was 2.9:1 on a hovered row). */
html[data-theme] :is(.table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light) .text-warning {
    color: var(--color-warn-text) !important;
}
html[data-theme] :is(.table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light) .text-info {
    color: var(--color-info-text) !important;
}
html[data-theme] :is(.table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light) :is(.text-muted, .text-body-secondary) {
    color: #4B5563 !important;
}
html[data-theme] :is(.table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light) .btn-outline-secondary {
    --bs-btn-color: #4B5563;
    --bs-btn-disabled-color: #4B5563;
}
html[data-theme] :is(.table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light) .btn-outline-danger {
    --bs-btn-border-color: var(--color-danger-text);
    --bs-btn-disabled-border-color: var(--color-danger-text);
}
html[data-theme] :is(.table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light) .btn-outline-warning {
    --bs-btn-color: var(--color-warn-text);
    --bs-btn-border-color: var(--color-warn-text);
    --bs-btn-disabled-color: var(--color-warn-text);
    --bs-btn-disabled-border-color: var(--color-warn-text);
}
html[data-theme] :is(.table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light) .btn-outline-info {
    --bs-btn-color: var(--color-info-text);
    --bs-btn-border-color: var(--color-info-text);
    --bs-btn-disabled-color: var(--color-info-text);
    --bs-btn-disabled-border-color: var(--color-info-text);
}
/* #1216: Bootstrap's code pink (#D63384) is 4.5:1 only on white: 4.2:1 on
   the warning alert (the Dev Scenarios logins) and the light themes' page,
   3.4-3.9:1 on the other alert fills. Behind the light gate it is
   Bootstrap's pink-600, 4.8:1 or more on the alert fills the app uses; the dark
   themes keep their own pink. */
html[data-scb-scheme="light"] {
    --bs-code-color: #AB296A;
}
/* #1215: the my-events check-in footer darkens the card by 20% black, which
   on a light page is #CCC: the token was white on it (1.6:1) and the success
   text 4.0:1. Behind the light gate it is the light surface and the token
   the page text; the dark themes keep their darker band and white token. */
.bb-card .card-footer.bb-entry-qr-footer {
    background: rgba(0, 0, 0, 0.2);
    border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.bb-entry-qr-token { color: #fff; }
html[data-scb-scheme="light"] .bb-card .card-footer.bb-entry-qr-footer {
    background: var(--color-surface-3);
    border-top-color: var(--color-border);
}
html[data-scb-scheme="light"] .bb-entry-qr-token { color: var(--color-text); }
/* #1186: Bootstrap's secondary grey (#6C757D) as text was 3.0-4.2:1 on the
   dark themes and 4.1-4.3:1 on the light themes' page: .text-secondary
   (registration form hints, profile stats) and, on the public shell, the
   outline button's label (admin-modern.css already does this in the app).
   Both take the theme's muted text; the fills keep #6C757D. */
html[data-theme] .text-secondary {
    color: var(--color-muted) !important;
}
.btn-outline-secondary {
    --bs-btn-color: var(--color-muted);
    --bs-btn-disabled-color: var(--color-muted);
}
.btn-outline-primary, .btn-outline-danger, .btn-outline-info,
.btn-outline-success, .btn-outline-warning, .btn-outline-secondary,
.btn-outline-light {
    border-width: 1px;
}
/* outline-light is a near-white stroke. On a light theme that matches the
   page, so the label disappears (Team on the event header). Keep the white
   stroke on dark themes; on light themes use the normal text and border.
   #1193: and on a dark theme painted light by a background override. */
html:is([data-bs-theme="light"], [data-scb-scheme="light"]) .btn-outline-light {
    --bs-btn-color: var(--color-text);
    --bs-btn-border-color: var(--color-border);
    --bs-btn-hover-color: var(--color-on-accent);
    --bs-btn-hover-bg: var(--color-accent);
    --bs-btn-hover-border-color: var(--color-accent);
    --bs-btn-active-color: var(--color-on-accent);
    --bs-btn-active-bg: var(--color-accent-hot);
    --bs-btn-active-border-color: var(--color-accent-hot);
    --bs-btn-disabled-color: var(--color-muted);
    --bs-btn-disabled-border-color: var(--color-border);
    --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

/* #1193 — a dark theme painted light by a background override: the light
   themes' remaps of the dark-era utilities (standard.css, modern.css), which
   kept #F8F9FA text and #212529 chips on the light page (1.1:1). */
html[data-bs-theme="dark"][data-scb-scheme="light"] .text-light {
    color: var(--color-text) !important;
}
html[data-bs-theme="dark"][data-scb-scheme="light"] .bg-dark,
html[data-bs-theme="dark"][data-scb-scheme="light"] .bg-black {
    background-color: var(--color-surface) !important;
    color: var(--color-text) !important;
}

/* #1121 — warning text and outline buttons on a themed surface (the team
   draft Top N screen: its cut line and its correction buttons). Bootstrap's
   warning yellow (#ffc107) is 1.6:1 on the light themes' white card;
   --color-warn is each theme's own warning colour, readable on its surface
   (#B45309 on white is 5.0:1, the dark themes keep an amber). !important
   as on .text-warning: the cut line is a table cell, and Bootstrap's
   `.table>:not(caption)>*>*` colour (0,1,1) beats a lone class. */
.scb-warn-text { color: var(--color-warn) !important; }
/* #1136 — the cypher leaderboard's cut line on the admin scores and heats
   pages (a <tr class="bb-cypher-cutoff"> holding an <hr>). It was an inline
   3px #ffc107 rule: 1.6:1 on the light themes' white card, under the 3:1 a
   graphic needs. --color-warn is readable on every theme's surface.
   Bootstrap's `hr` is opacity .25 and currentColor, so both are set here. */
.bb-cypher-cutoff hr { border: 0; border-top: 3px solid var(--color-warn); opacity: 1; margin: 0; }
.btn-outline-warning.scb-btn-warn {
    --bs-btn-color: var(--color-warn);
    --bs-btn-border-color: var(--color-warn);
    --bs-btn-hover-color: var(--color-surface);
    --bs-btn-hover-bg: var(--color-warn);
    --bs-btn-hover-border-color: var(--color-warn);
    --bs-btn-active-color: var(--color-surface);
    --bs-btn-active-bg: var(--color-warn);
    --bs-btn-active-border-color: var(--color-warn);
    --bs-btn-disabled-color: var(--color-warn);
    --bs-btn-disabled-border-color: var(--color-warn);
}

/* #1169 — Bootstrap's warning yellow and info cyan as text were 1.4-2.0:1
   on the light themes' page and cards. The light themes set a readable shade
   for the text and the outline; the fills (hover, .bg-*) keep Bootstrap's.
   Only on a page painted light: the dark themes keep Bootstrap's own colours,
   and so does a light theme under a dark background override. #1173: a dark
   theme under a light override is a light page too (data-scb-scheme, as in
   guide.css); the override reshades both tokens for its surfaces. */
html[data-scb-scheme="light"] .text-warning {
    color: var(--color-warn-text) !important;
}
html[data-scb-scheme="light"] .text-info {
    color: var(--color-info-text) !important;
}
html[data-scb-scheme="light"] .btn-outline-warning {
    --bs-btn-color: var(--color-warn-text);
    --bs-btn-border-color: var(--color-warn-text);
    --bs-btn-disabled-color: var(--color-warn-text);
    --bs-btn-disabled-border-color: var(--color-warn-text);
}
html[data-scb-scheme="light"] .btn-outline-info {
    --bs-btn-color: var(--color-info-text);
    --bs-btn-border-color: var(--color-info-text);
    --bs-btn-disabled-color: var(--color-info-text);
    --bs-btn-disabled-border-color: var(--color-info-text);
}
/* #1173 — a panel that paints its own dark scrim on any theme (the judge's
   lock screen) keeps the dark-scheme text on a light page: the warning token
   was #92400E there (2.2:1) and the light themes' .text-light the page text
   (1.1:1). The dark themes already paint it so. */
html[data-scb-scheme="light"] .scb-dark-stage {
    --color-warn-text: #FFC107;
    --color-text: #F8F9FA;
}

/* ===== APP FORMS ===== */
.form-control, .form-select {
    background: var(--color-surface-3);
    border-color: var(--color-border);
    color: var(--color-text);
    border-radius: var(--radius-sm);
}
.form-control:focus, .form-select:focus {
    background: var(--color-surface-3);
    border-color: var(--color-accent);
    color: var(--color-text);
    box-shadow: 0 0 0 0.2rem color-mix(in srgb, var(--color-accent) 20%, transparent);
}
.form-label { font-size: 0.85rem; margin-bottom: 0.35rem; color: var(--color-muted); font-weight: 500; }

/* ===== TABLES ===== */
.table { font-size: 0.875rem; }
.table td, .table th { padding: 0.65rem 0.85rem; vertical-align: middle; }
.table-dark { --bs-table-bg: transparent; }
.table > thead > tr > th {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--color-muted);
    border-bottom: 1px solid var(--color-border);
}
.table > tbody > tr > td {
    border-bottom: 1px solid var(--bb-border-soft);
}
.table > tbody > tr:last-child > td { border-bottom: none; }
.table-hover > tbody > tr:hover > td {
    background: var(--bb-hover);
}

/* ===== APP STATUS BADGES ===== */
.badge {
    font-weight: 600;
    font-size: 0.72rem;
    padding: 0.3em 0.6em;
    border-radius: var(--radius);
}
.bb-status-draft { background: var(--color-muted); }
.bb-status-registration { background: var(--bs-blue); }
.bb-status-running { background: var(--color-accent); }
.bb-status-finished { background: var(--bs-green); }
.bb-status-archived { background: var(--color-muted); }
.bb-status-pending { background: var(--color-muted); }
.bb-status-live { background: var(--color-accent); }
.bb-status-active { background: var(--bs-orange); }
.bb-status-completed { background: var(--bs-green); }
.bb-status-approved { background: var(--bs-green); }
.bb-status-rejected { background: var(--color-accent); }
.bb-status-withdrawn { background: var(--color-muted); }
.bb-status-waitlist { background: var(--bs-orange); }
.bb-status-bye { background: var(--color-muted); }
.bb-status-pending_head_judge { background: var(--color-warn); }
/* Tiebreaker badge — no animation. The red colour + "TB" label are
   enough; per user feedback live-event surfaces should not blink. */
.bb-status-tiebreaker { background: var(--color-accent); }

/* ===== NAV PILLS (if still used anywhere) ===== */
.nav-pills {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    white-space: nowrap;
    gap: 0.35rem;
    padding-bottom: 0.25rem;
}
.nav-pills::-webkit-scrollbar { display: none; }
.nav-pills .nav-item { flex-shrink: 0; }
.nav-pills .nav-link {
    color: var(--color-muted);
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    padding: 0.4rem 0.85rem;
    transition: background 0.15s;
}
.nav-pills .nav-link:hover { background: var(--bb-hover); color: var(--color-text); }
.nav-pills .nav-link.active { background: var(--color-accent); color: var(--color-on-accent); }

/* ===== BRACKET ===== */
.bb-bracket-container {
    overflow-x: auto;
    padding: 20px;
    background: var(--color-bg);
    border-radius: var(--radius);
    border: 1px solid var(--bb-border-soft);
}
.bb-bracket-svg { width: 100%; height: auto; min-height: 300px; }

/* ===== VOTE BUTTONS ===== */
.vote-btn { min-height: 80px; min-width: 48px; touch-action: manipulation; }

/* ===== MODAL ===== */
.modal-content {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
}

/* ===== LIST GROUP (sidebar-compatible) ===== */
.list-group-item-action:focus,
.list-group-item-action:active {
    background: var(--bb-hover) !important;
    color: var(--color-text) !important;
}

/* ===== ALERTS ===== */
.alert { border-radius: var(--radius-sm); font-size: 0.9rem; }

/* ===== SCORE COLOR CODING ===== */
/* #1185 — the score text each band paints, as text and on its 15% tint (the
   judge's score badges). Bootstrap's green was 2.7-3.6:1 on the dark themes'
   tint, so it is mixed halfway toward the theme's text: lighter on a dark
   page, darker on a light one (4.8:1 at worst, semidark's surface-3). The
   yellow takes the warning text shade on a page painted light (#1169) and
   stays Bootstrap's on a dark one. The fills keep Bootstrap's colours. */
.score-low, .score-low-bg { --score-text: var(--color-danger-text); }
.score-mid, .score-mid-bg { --score-text: var(--bs-warning); }
html[data-scb-scheme="light"] .score-mid,
html[data-scb-scheme="light"] .score-mid-bg { --score-text: var(--color-warn-text, var(--bs-warning)); }
.score-high, .score-high-bg { --score-text: color-mix(in srgb, var(--bs-success) 50%, var(--color-text)); }
.score-low { color: var(--color-danger-text); }
.score-mid, .score-high { color: var(--score-text); }
.score-low-bg { background-color: color-mix(in srgb, var(--bs-danger) 15%, transparent); color: var(--score-text); }
.score-mid-bg { background-color: color-mix(in srgb, var(--bs-warning) 15%, transparent); color: var(--score-text); }
.score-high-bg { background-color: color-mix(in srgb, var(--bs-success) 15%, transparent); color: var(--score-text); }
/* The light themes paint every other badge's text --color-on-accent
   (html[data-theme] .badge:not([class*="bb-status-"]), 0,3,1): white on the
   tints, 1.1-1.2:1. One class more keeps the band's text. */
html[data-theme] .badge.score-badge:not([class*="bb-status-"]) { color: var(--score-text); }
.score-badge { font-weight: 700; padding: 0.2em 0.5em; border-radius: var(--radius); font-size: 0.85em; }
.score-badge.score-low-bg { border: 1px solid color-mix(in srgb, var(--bs-danger) 30%, transparent); }
.score-badge.score-mid-bg { border: 1px solid color-mix(in srgb, var(--bs-warning) 30%, transparent); }
.score-badge.score-high-bg { border: 1px solid color-mix(in srgb, var(--bs-success) 30%, transparent); }

/* ===== THEME PICKER (admin Appearance card) ===== */
.scb-theme-swatch { cursor: pointer; margin: 0; }
.scb-theme-swatch input { position: absolute; opacity: 0; pointer-events: none; }
.scb-theme-swatch-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 8.5rem;
    padding: 0.55rem 0.85rem;
    border: 2px solid var(--color-border);
    border-radius: var(--radius);
    font-size: 0.85rem;
    font-weight: 600;
}
.scb-theme-swatch input:checked + .scb-theme-swatch-chip {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.scb-theme-swatch input:focus-visible + .scb-theme-swatch-chip {
    outline: 2px solid var(--color-accent-hot);
    outline-offset: 2px;
}
.scb-theme-swatch-accent {
    width: 0.85rem;
    height: 0.85rem;
    border-radius: 50%;
    flex-shrink: 0;
}

.scb-choice-chip { cursor: pointer; margin: 0; }
.scb-choice-chip input { position: absolute; opacity: 0; pointer-events: none; }
.scb-choice-chip span {
    display: inline-flex;
    align-items: center;
    min-height: 2.5rem;
    padding: 0.45rem 0.85rem;
    border: 2px solid var(--color-border);
    border-radius: var(--radius);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-text);
    touch-action: manipulation;
}
.scb-choice-chip input:checked + span {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-color: var(--color-accent);
}
.scb-choice-chip input:focus-visible + span {
    outline: 2px solid var(--color-accent-hot);
    outline-offset: 2px;
}

.scb-color-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.45rem;
}
.scb-color-chip {
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
    border-radius: 50%;
    border: 2px solid var(--color-border);
    background: var(--color-surface-3);
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    touch-action: manipulation;
}
.scb-color-chip.is-selected {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}
.scb-color-chip:focus-visible {
    outline: 2px solid var(--color-accent-hot);
    outline-offset: 2px;
}
.scb-color-custom {
    position: relative;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.55rem;
    border: 2px dashed var(--color-muted);
    overflow: hidden;
    cursor: pointer;
    flex-shrink: 0;
    margin: 0 0 0 0.25rem;
    touch-action: manipulation;
    background:
        conic-gradient(#f44, #ff0, #4f4, #0ff, #44f, #f0f, #f44);
}
.scb-color-custom::after {
    content: "+";
    position: absolute;
    inset: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 0.3rem;
    background: color-mix(in srgb, var(--color-surface) 82%, transparent);
    font-size: 1.2rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-text);
    pointer-events: none;
    z-index: 1;
}
.scb-color-custom input[type="color"] {
    position: absolute;
    inset: -25%;
    width: 150%;
    height: 150%;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    opacity: 0;
}
/* Inherit stays editable: chips and the slider stay at full strength so a
   click immediately takes over from the theme default. */

.scb-appearance-slider { height: 44px; }
.scb-appearance-slider::-webkit-slider-thumb {
    width: 28px;
    height: 28px;
    background: var(--color-accent);
    border: 2px solid var(--color-on-accent);
    border-radius: 50%;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -10px;
}
.scb-appearance-slider::-moz-range-thumb {
    width: 28px;
    height: 28px;
    background: var(--color-accent);
    border: 2px solid var(--color-on-accent);
    border-radius: 50%;
    cursor: pointer;
}
.scb-appearance-slider::-webkit-slider-runnable-track {
    height: 8px;
    background: var(--color-surface-3);
    border-radius: 4px;
}
.scb-appearance-slider::-moz-range-track {
    height: 8px;
    background: var(--color-surface-3);
    border-radius: 4px;
}
.scb-radius-readout {
    min-width: 3.25rem;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--color-text);
}

.scb-appearance-css summary {
    cursor: pointer;
    list-style: none;
}
.scb-appearance-css summary::-webkit-details-marker { display: none; }
.scb-appearance-css summary::before {
    content: "▸ ";
    color: var(--color-muted);
}
.scb-appearance-css[open] summary::before { content: "▾ "; }

/* ===== SITE SETTINGS DASHBOARD ===== */
.scb-settings-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin-bottom: 1.15rem;
}
.scb-settings-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 2.5rem;
    padding: 0.45rem 0.85rem;
    border: 2px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-text);
    font-weight: 600;
    font-size: 0.85rem;
    touch-action: manipulation;
}
.scb-settings-tab.is-active {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-color: var(--color-accent);
}
.scb-settings-tab:focus-visible {
    outline: 2px solid var(--color-accent-hot);
    outline-offset: 2px;
}
.scb-settings-pane { display: none; }
.scb-settings-pane.is-active { display: block; }
.scb-settings-bar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.25rem;
    padding: 0.75rem 0;
    background: color-mix(in srgb, var(--color-bg) 88%, transparent);
    backdrop-filter: blur(8px);
}

/* ===== #1598 — wide tables on a phone ===== */
/* A wide table scrolls sideways inside its .table-responsive. On a phone the
   column that names the row then scrolls away, and the numbers on the right
   lose their row. .scb-sticky-first (or .scb-sticky-second, when a "#" or
   date column comes first) keeps that column at the scroller's left edge
   while the rest scroll under it. Below lg only: desktop is not touched, and
   the opaque background a sticky cell needs is never painted where a table
   fits. The background is the card's (--scb-sticky-bg), with the table's own
   row tint (a .table-danger row, say) laid over it; the inset shadow is
   Bootstrap's state tint plus a 1 px edge, since a collapsed-border table
   does not move a cell's own border with it. A row-spanning message (an
   empty table's "no rows", colspan) starts at the left edge, where a phone
   sees it, instead of being centred across the whole scroll width.
   #1607 — --scb-sticky-bg is set only on a scroller inside a .bg-dark card,
   the one place a sticky cell sits on something other than the surface;
   everywhere else (.bb-card, .scb-card) the fallback, --color-surface, is the
   card's own background. To use the classes in any other container, set
   --scb-sticky-bg on its .table-responsive to that container's opaque
   background, or the column shows the rows scrolling under it.
   #1657 — .scb-sticky-name, on the cells of one column (header and body), is
   the same sticky cell for a naming column that is neither first nor second
   (a phase after its category, a heat, the dancer whose score was
   overridden, a battle's pair). It sticks at the scroller's left edge, so
   the columns before it scroll under it, as a "#" does under
   .scb-sticky-second. A rowspan cell sticks for all its rows. */
.bg-dark .table-responsive { --scb-sticky-bg: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity, 1)); }
html[data-theme="standard"] .bg-dark .table-responsive,
html[data-theme="modern"] .bg-dark .table-responsive,
html[data-bs-theme="dark"][data-scb-scheme="light"] .bg-dark .table-responsive { --scb-sticky-bg: var(--color-surface); }
@media (max-width: 991.98px) {
    .table-responsive > .scb-sticky-first > :is(thead, tbody, tfoot) > tr > :first-child:not([colspan]),
    .table-responsive > .scb-sticky-second > :is(thead, tbody, tfoot) > tr > :nth-child(2):not([colspan]),
    .table-responsive > table > :is(thead, tbody, tfoot) > tr > .scb-sticky-name {
        position: sticky;
        left: 0;
        z-index: 1;
        background-color: var(--scb-sticky-bg, var(--color-surface));
        background-image: linear-gradient(var(--bs-table-bg, transparent), var(--bs-table-bg, transparent));
        box-shadow: inset -1px 0 0 var(--scb-sticky-edge, var(--color-border)),
            inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg, transparent)));
    }
    .table-responsive > :is(.scb-sticky-first, .scb-sticky-second) > tbody > tr > td[colspan] { text-align: start !important; }
}
/* #1615 — .scb-sticky-always (with .scb-sticky-first or .scb-sticky-second)
   keeps the naming column in view at every width, for a table that is wider
   than its card on a desktop too: Admin → Judges in LT (689 px in a 430 to
   671 px card from 992 to 1366 px) and the scores page's combined
   leaderboard (one column per judge, so no width is always enough). The
   same cell as below lg; where the table fits, the opaque background is the
   card's own, so nothing shows. The desktop hover tint and the header tint
   are laid over it in admin-modern.css. */
.table-responsive > .scb-sticky-always.scb-sticky-first > :is(thead, tbody, tfoot) > tr > :first-child:not([colspan]),
.table-responsive > .scb-sticky-always.scb-sticky-second > :is(thead, tbody, tfoot) > tr > :nth-child(2):not([colspan]) {
    position: sticky;
    left: 0;
    z-index: 1;
    background-color: var(--scb-sticky-bg, var(--color-surface));
    background-image: linear-gradient(var(--bs-table-bg, transparent), var(--bs-table-bg, transparent));
    box-shadow: inset -1px 0 0 var(--scb-sticky-edge, var(--color-border)),
        inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg, transparent)));
}
/* #1709 — .scb-sticky-pairs (with .scb-sticky-always and .scb-sticky-first
   or .scb-sticky-second): the sticky naming column holds at least 9ch of
   text. In a table wider than its scroller the browser squeezes the wrapping
   columns to their longest word, so on a phone "QA Head Judge" stood one
   word per line in the scores page's judge column (54 px of text at 390 px,
   V39). With 9ch it wraps at word pairs ("QA Head / Judge"). The text box,
   not the padded cell (content-box), so the first column's wider edge
   padding does not eat into it. Only on the scores page's per-dancer
   criteria tables (battle and heat) and its Criteria Scores table, which
   scroll on every phone anyway: on every .scb-sticky-* column it widened
   short columns for nothing and made tables that fitted scroll (the recap's
   judge table, 16 px at 390), and a scroll-state query cannot limit it to
   tables that scroll (one that overflowed for a frame, before the web font,
   kept the 9ch and its scroll). */
.table-responsive > .scb-sticky-pairs.scb-sticky-always.scb-sticky-first > :is(thead, tbody, tfoot) > tr > :first-child:not([colspan]),
.table-responsive > .scb-sticky-pairs.scb-sticky-always.scb-sticky-second > :is(thead, tbody, tfoot) > tr > :nth-child(2):not([colspan]) {
    box-sizing: content-box;
    min-width: 9ch;
}
/* #1729 — .scb-pairs-cell: a naming column that is not the sticky one holds
   9ch of text at every width, as .scb-sticky-pairs does for the sticky one.
   The scores page's Criteria Scores judge stood "QA / Head / Judge" one word
   per line wherever the table is wider than its card (390 to 1280 px). The
   table already scrolls there and fits from 1440 with the 9ch (EN and LT). */
.table-responsive > table > :is(thead, tbody, tfoot) > tr > .scb-pairs-cell {
    box-sizing: content-box;
    min-width: 9ch;
}
/* #1729 — .scb-phone-names (with .scb-sticky-first or .scb-sticky-second):
   on a phone (below 576 px) the naming column reads as a name, not a word
   stack, on tables that scroll on every phone anyway.
   - It holds 9ch of text, as .scb-sticky-pairs does at every width: Admin →
     Judges stood "QA / Head / Judge" one word per line at 390 px, the heats
     page's tables "Rhythm / Ghost / — Legal / Rhythm / Ghost". Phones only:
     from 576 px these tables can fit, and the 9ch made some that fitted
     scroll (Admin → Judges at 992 px in EN, a heat table at 992 in LT, the
     scores leaderboard at 1280 in LT).
   - Dancer cells show the display name only. participant_name() writes the
     legal name after it (<small class="bb-legal-name">— Legal Name</small>,
     or on a line of its own in its stacked form, which the scores page's
     dancer cells use from 576 px), and in a squeezed column the two took 4
     to 6 lines ("Finished Champion — Legal Finished Champion" took 4 in the
     scores page's Criteria Scores table, "Rhythm Ghost — Legal Rhythm Ghost"
     6 on the heats page). From 576 px the legal name shows again. Visually
     hidden, not display: none, so a screen reader still reads the full name;
     out of flow, so the stacked form's <br> adds no empty line. */
@media (max-width: 575.98px) {
    .table-responsive > .scb-phone-names.scb-sticky-first > :is(thead, tbody, tfoot) > tr > :first-child:not([colspan]),
    .table-responsive > .scb-phone-names.scb-sticky-second > :is(thead, tbody, tfoot) > tr > :nth-child(2):not([colspan]) {
        box-sizing: content-box;
        min-width: 9ch;
    }
    .scb-phone-names .bb-legal-name {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }
}
/* #1657 — the sticky cell's 1 px edge shows where the rows scroll under it,
   so it is drawn only while its table overflows the scroller (at any scroll
   position, the first included): a table that fits (Admin → Judges and the
   scores leaderboard on a desktop, a narrow table on a phone) has no edge.
   The scroller is a scroll-state container; its table sets
   --scb-sticky-edge (which the sticky cells inherit) to transparent, and a
   scroll-state query (scrollable: x, true when the scroller can scroll
   sideways either way) sets it to the border colour. Not an animation:
   a scroll-timeline animation did the same in a browser, but the visual
   suite's shots disable animations (animations: 'disabled'), so they showed
   no edge on an overflowing table at scroll 0 (W3, V10 at 390 px). A browser
   without scroll-state queries keeps the edge at all times, as before. */
@supports (container-type: scroll-state) {
    .table-responsive:has(> table) { container-type: scroll-state; }
    .table-responsive > table { --scb-sticky-edge: transparent; }
    @container scroll-state(scrollable: x) {
        .table-responsive > table { --scb-sticky-edge: var(--color-border); }
    }
}

/* #1609 — no-JS fallbacks. Every layout (main, public, minimal) starts <html>
   as .no-js and removes the class with a nonce'd inline script, so these
   apply only without JS: .scb-nojs-only shows a control that works without
   JS (a GET form's submit button, inline-block like .btn), .scb-js-only hides
   one that needs JS. */
.scb-nojs-only { display: none; }
.no-js .scb-nojs-only { display: inline-block; }
.no-js .scb-js-only { display: none; }
