/**
 * Bodybuilding - Main Stylesheet
 *
 * Clean modern design system - light mode, mobile-first.
 * Matches strongman design system exactly with bb- prefix.
 * All styles scoped to .bb-app to prevent WordPress conflicts.
 *
 * @package Bodybuilding
 * @since 2.0.0
 */

/* ==========================================================================
   0. BRAND FONTS - Archivo + IBM Plex Mono (self-hosted, no external request)

   Replaced DM Sans on 2026-07-29 with the Iron & Bone design. Both faces are
   OFL and are served from public/fonts/ rather than fonts.googleapis.com the
   way the design prototype does. The Foxiz theme already opens a connection to
   Google Fonts, so this is not about avoiding a new third party - it is about
   not adding two more render-blocking families to a request the plugin does
   not control. Same call already made for the flag images.

   Archivo is the VARIABLE cut and carries two axes in one file: weight
   400-800 and width 75-125%. The width axis is load-bearing, not a nicety -
   every display heading in the design sets font-stretch between 84% and 90%,
   and a static cut would silently render those at 100% and reflow the hero.

   IBM Plex Mono is static at 400/500/600 because every figure in the design
   picks one of exactly those three. It is the face that makes placements line
   up: see --bb-font-mono and the tabular-nums base rule.

   latin-ext covers accented athlete names (Bjornsson, Krizo, Choopan).
   font-display:swap keeps first paint unblocked.
   ========================================================================== */
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 400 800;
    font-stretch: 75% 125%;
    font-display: swap;
    src: url('../fonts/archivo-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Archivo';
    font-style: normal;
    font-weight: 400 800;
    font-stretch: 75% 125%;
    font-display: swap;
    src: url('../fonts/archivo-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/plex-mono-400-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('../fonts/plex-mono-400-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/plex-mono-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/plex-mono-500-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/plex-mono-600-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'IBM Plex Mono';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/plex-mono-600-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Every figure lines up. This is the single rule that makes a column of
   placements read as a record rather than as prose, and it is why the design
   puts IBM Plex Mono on numbers everywhere. Scoped to .bb-app so the theme's
   own type is untouched. */
.bb-app {
    font-variant-numeric: tabular-nums;
}

/*
 * Full-bleed page ground.
 *
 * .bb-app is 356px wide inside a 375px viewport, so painting only the wrapper
 * leaves a white gutter down both sides of every phone screen and the bone
 * ground reads as a stripe rather than a page.
 *
 * A fixed layer rather than a body rule, because every design token including
 * --bb-bone is declared on .bb-app and nowhere else. `body { background:
 * var(--bb-bone) }` resolves against a scope that has never heard of the token
 * and paints nothing, and hardcoding the hex would put a literal back into the
 * one file the token ratchet guards. This keeps the single token owner.
 */
/*
 * BOUND TO .bb-app, NOT FIXED TO THE VIEWPORT. This layer was position:fixed with
 * inset:0, and it painted over the theme footer on every plugin page.
 *
 * Why a z-index:-1 layer ended up ON TOP of anything: .bb-app is position:static, so
 * the pseudo joins the nearest ancestor stacking context, which is the theme's
 * `.site-wrap { z-index: 1 }`. The footer sits OUTSIDE .site-wrap, so the whole
 * site-wrap layer paints above it - and a fixed inset:0 sheet inside that layer
 * therefore covered the footer at every scroll position, at full viewport size. The
 * -1 only ordered it behind .bb-app's own content, never behind the footer.
 *
 * It hid from every diagnostic: pointer-events:none kept elementFromPoint returning
 * the footer's own links, and because the rule targets .bb-app it never appeared when
 * enumerating rules that match footer elements. The footer measured perfectly - right
 * height, right colour, 912 characters of innerText - and simply had a cream sheet
 * painted over it.
 *
 * Absolute + full-bleed keeps the reason the layer exists. .bb-app is 356px wide in a
 * 375px viewport, so painting only the wrapper leaves a white gutter down both sides of
 * a phone screen. This still reaches both viewport edges, and still resolves --bb-bone
 * in the scope that owns it, so the token stays in one place and no hex literal comes
 * back into the file the ratchet guards. What it cannot do any more is extend past
 * .bb-app's own box, which is where the footer begins.
 */
.bb-app {
    position: relative;
}

.bb-app::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(-50vw + 50%);
    width: 100vw;
    max-width: 100vw;
    z-index: -1;
    background: var(--bb-bone);
    pointer-events: none;
}

/*
 * The plugin owns hiding. Every empty state, panel and toggled block in here is
 * shown and hidden with the `hidden` attribute, and the UA rule for it is plain
 * `display: none`, which loses to any author `display` declaration. Components
 * like .bb-empty-state (flex) and .bb-compare-h2h-grid (grid) declare one, so
 * `hidden` only worked because the Foxiz theme's main.css happens to carry a
 * bare `[hidden] { display: none }` that loads after this file. That is enqueue
 * order, not a contract: reorder the styles and every hidden block appears.
 *
 * Verified in the browser rather than reasoned about. A standalone page with
 * `.g { display: grid }` plus `hidden` computes `grid`, so the attribute alone is
 * genuinely not enough. Compare had already hit this and shipped an inline
 * `#bb-compare-app [hidden] { display: none !important }` patch, which is the same
 * conclusion reached one route at a time; this replaces it for every route.
 *
 * `!important` is deliberate: it has to beat component display declarations,
 * which is exactly what that inline patch needed too.
 */
.bb-app [hidden] {
    display: none !important;
}

/*
 * Baseline focus ring for everything focusable inside the plugin.
 *
 * 43 :focus-visible rules already existed, one per component, and no baseline. So
 * every component added since had to remember, and five did not: measured on
 * /olympia/, .bb-olympia-div-winner, .bb-olympia-year-num-link,
 * .bb-olympia-open-name, .bb-state-action and .bb-nav-dropdown-trigger all computed
 * outline-style: none and box-shadow: none, with zero :focus or :focus-visible rules
 * anywhere in the stylesheet for the first three. A keyboard user tabbing the
 * results grid - the actual content of the page - got no feedback at all.
 *
 * Per-component rules keep winning over this: .bb-app .bb-btn:focus-visible is three
 * classes against this rule's two-classes-plus-an-element, and this sits near the top
 * of the file so a later rule also wins any genuine tie. So a component that wants a
 * different treatment still gets it; a component whose author forgot gets a visible
 * ring instead of nothing.
 *
 * Uses the existing --bb-focus-ring-* tokens rather than new values.
 *
 * !important is not laziness here, it is the only thing that works. The Foxiz theme
 * strips focus outlines with !important of its own, verified by reading the parsed
 * CSSOM rather than guessing:
 *
 *   button, input, optgroup, select, textarea { outline: none !important }
 *   button                                    { outline: none !important }
 *   select                                    { outline: none !important }
 *   input[type=text|tel|password|...]         { outline: none !important }
 *   input[type=submit], .is-btn, .button, ... { outline: none !important }
 *
 * So every button and form control in the plugin had NO keyboard focus indicator at
 * all, on every route, and no amount of plugin specificity could recover it. That is
 * why the components which did work were the ones that are anchors or spans with
 * tabindex, not buttons. A focus indicator must not be silently defeatable, which is
 * exactly the case !important exists for.
 */
.bb-app a:focus-visible,
.bb-app button:focus-visible,
.bb-app summary:focus-visible,
.bb-app input:focus-visible,
.bb-app select:focus-visible,
.bb-app textarea:focus-visible,
.bb-app [tabindex]:focus-visible {
    outline: var(--bb-focus-ring-width) solid var(--bb-focus-ring-color) !important;
    outline-offset: var(--bb-focus-ring-offset) !important;
}

.bb-app .bb-trust-panel,
.bb-app .bb-filter-state,
.bb-app .bb-starter-panel,
.bb-app .bb-hero-start {
    background: var(--bb-surface-raised);
    border: 1px solid var(--bb-border);
    border-radius: 6px;
    box-shadow: none;
}

.bb-app .bb-trust-panel,
.bb-app .bb-starter-panel {
    display: grid;
    /*
     * Two columns need 240px for the second plus a gutter plus this panel's own
     * 24px of padding on each side. Below roughly 560px that no longer fits, and
     * the grid held its column anyway: on a 390px screen the panel measured
     * 354px and its children 475px, hanging 146px past the edge - the largest
     * single overflow in the sweep. auto-fit collapses to one column instead of
     * forcing a width the viewport does not have.
     */
    grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
    gap: 24px;
    align-items: start;
    margin: 24px 0;
    padding: 24px;
}
/* A grid item defaults to min-width:auto, which is min-content, so it refuses to
   shrink below its widest unbreakable run and drags the column with it - the
   column resolved to 475px inside a 354px panel. min-width:0 lets it shrink and
   the text wrap as it already knows how to. */
.bb-app .bb-starter-panel > * {
    min-width: 0;
}

.bb-app .bb-trust-eyebrow,
.bb-app .bb-starter-eyebrow {
    display: inline-flex;
    align-items: center;
    width: fit-content;
    margin-bottom: 8px;
    padding: 4px 10px;
    border-radius: 999px;
    background: rgba(217, 139, 74, 0.12);
    color: #7a5207;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.bb-app .bb-trust-panel h2,
.bb-app .bb-starter-panel h2 {
    margin: 0 0 8px;
    color: var(--bb-text-primary);
    /* The card tier. This was clamp(1.25rem, 2vw, 1.65rem), landing on 25.6px -
       a value on no tier at all, and the last thing keeping a heading off the
       scale. A panel heading is a card title, and claude-design sets those at
       24 flat: a card's own edge already separates it, so it does not need to
       scale with the viewport the way a page-level section heading does. */
    font-size: var(--bb-fs-xl);
    letter-spacing: normal;
}

.bb-app .bb-trust-panel p,
.bb-app .bb-starter-panel p {
    color: var(--bb-text-secondary);
    line-height: 1.65;
}

.bb-app .bb-trust-list,
.bb-app .bb-starter-list {
    display: grid;
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.bb-app .bb-trust-list li,
.bb-app .bb-starter-list li {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    color: var(--bb-text-secondary);
    font-size: 14px;
    line-height: 1.5;
}

.bb-app .bb-trust-list li::before,
.bb-app .bb-starter-list li::before {
    content: "";
    flex: 0 0 8px;
    width: 8px;
    height: 8px;
    margin-top: 7px;
    border-radius: 50%;
    background: var(--bb-primary);
    box-shadow: 0 0 0 4px rgba(178, 58, 53, 0.1);
}

.bb-app .bb-filter-state {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    align-items: center;
    margin: 14px 0 24px;
    padding: 14px 16px;
}

.bb-app .bb-filter-state-main,
.bb-app .bb-filter-state-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}

.bb-app .bb-state-chip {
    display: inline-flex;
    align-items: center;
    min-height: 30px;
    padding: 6px 10px;
    border-radius: 999px;
    background: rgba(34, 28, 24, 0.08);
    color: var(--bb-navy-mid);
    font-size: 12px;
    font-weight: 700;
}

.bb-app .bb-state-chip--muted {
    background: var(--bb-gray-100);
    color: #6e665e;
}

.bb-app .bb-state-action {
    display: inline-flex;
    align-items: center;
    /* Was 30px, under the plugin's own --bb-touch-min. This is the retry/clear
       control inside an empty state, so it is the one thing on the surface a
       visitor needs to hit, and it was the smallest target on the page. */
    min-height: var(--bb-touch-min);
    padding: 6px 14px !important;
    border: 1px solid var(--bb-border) !important;
    /* Pill by intent; through the token so it cannot drift from the other pills. */
    border-radius: var(--bb-radius-full) !important;
    background: #fff !important;
    color: var(--bb-text-primary) !important;
    font-size: 12px !important;
    font-weight: 700 !important;
    line-height: 1 !important;
    cursor: pointer;
    transition: border-color 150ms ease, transform 150ms ease;
}

.bb-app .bb-state-action:hover {
    border-color: var(--bb-primary) !important;
    transform: translateY(-1px);
}

.bb-app .bb-hero-start {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 12px;
    align-items: center;
    width: min(720px, 100%);
    /*
     * Left, not auto-centred. The hero was built centred and the old 600px content cap
     * hid it, because a 720px form inside a 600px column simply filled it. Once the cap
     * came off with the champions board, the form and the path pills centred themselves
     * under a left-aligned headline, which read as two different layouts stacked.
     */
    margin: 26px 0 18px;
    padding: 10px;
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.16);
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.18);
}

.bb-app .bb-hero-start input {
    width: 100%;
    min-height: 48px;
    border: 0;
    border-radius: 12px;
    background: #fff;
    color: var(--bb-text-primary);
    font-size: 15px;
    padding: 0 16px;
}

.bb-app .bb-hero-paths {
    display: flex;
    /* Left, to match the headline and the search box above it. */
    justify-content: flex-start;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 10px;
}

.bb-app .bb-hero-path {
    display: inline-flex;
    align-items: center;
    min-height: 38px;
    padding: 8px 14px;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.9) !important;
    font-size: 13px;
    font-weight: 700;
}

.bb-app .bb-starter-code {
    margin: 0;
    padding: 16px;
    border-radius: 14px;
    background: var(--bb-navy);
    color: var(--bb-on-dark);
    font-family: var(--bb-font-mono);
    font-size: 12px;
    line-height: 1.6;
    white-space: pre-wrap;
    overflow-x: auto;
}

@media (max-width: 760px) {
    .bb-app .bb-trust-panel,
    .bb-app .bb-starter-panel,
    .bb-app .bb-hero-start {
        grid-template-columns: 1fr;
    }

    .bb-app .bb-filter-state {
        align-items: stretch;
        flex-direction: column;
    }
}

/* ==========================================================================
   1. DESIGN TOKENS
   ========================================================================== */

.bb-app,
.bb-editorial-post {
    /* .bb-editorial-post is here because a bound editorial post renders on the
       THEME's layout, so its article body sits outside any .bb-app scope. Rules
       written for that body resolved every var() to nothing, and a declaration
       with an unresolved var is dropped whole - so a border-bottom read as
       "2px solid <nothing>" and simply did not paint, silently, while the
       literal font-size beside it applied. Hosting the tokens on the layout
       wrapper too is what makes the token layer reachable there. It shares only
       the tokens: the page-ground .bb-app::before is a separate rule and this
       wrapper deliberately does not get it.

       Editorial data-authority system. Near-monochrome warm-paper base with a
       single restrained oxblood accent. This block is the ONE source of truth
       for every .bb-app design token (consolidated 2026-06-20 from the two
       former lower token layers); change a token here and nowhere else.
       NOTE: .bb-report-modal (defined later) intentionally mirrors these tokens
       with literal values because it renders on document.body (outside .bb-app
       scope, so it cannot inherit the vars). Keep that mirror in lockstep when
       a core token changes. */

    /* ---- Iron & Bone base ramp -------------------------------------------
       Adopted 2026-07-29 from Claude Design project 426d8189. This is the one
       place a colour is chosen; every semantic token below resolves to one of
       these, so no rule outside this block should carry a literal hex.
       Rationale and the four owner decisions: DESIGN-IRON-AND-BONE.md.

       There is no blue here, and that is deliberate. UI-72 documented three
       jobs the old --bb-navy-mid (#12365a) was carrying; reading all 17 design
       pages retired every one of them:
         1. gradient light end  -> there are no gradients, dark surfaces are
                                   flat ink with a 1px vertical rule texture
         2. male gender coding  -> DROPPED by owner decision, gender is now
                                   labelled text tabs (All / Men / Women)
         3. athlete B / series 2 -> ink, opposite the oxblood athlete A
       Keep public/js/bb-charts.js SERIES_2 in step with --bb-chart-series-2. */
    --bb-ink: #221c18;
    --bb-bone: #faf6ef;
    --bb-paper: #ffffff;
    /* Text on dark surfaces. Was a raw #fffdf8 repeated ten times across the
       file with no owner, which is what the ratchet exists to catch. */
    --bb-on-dark: #fffdf8;
    --bb-tint: #f0e9dc;
    --bb-tint-2: #e2d8c6;
    --bb-oxblood: #a8372a;
    --bb-oxblood-hover: #85291f;
    --bb-amber: #d98b4a;
    --bb-amber-dark: #8f5a1e;
    --bb-amber-deep: #7a4c19;
    --bb-warm-grey: #5a524a;
    --bb-warm-grey-2: #6b6259;
    --bb-moss: #45723f;
    --bb-moss-dark: #2f5129;
    --bb-moss-light: #8fbd86;
    /* Validation only. Deviation B: kept off the brand oxblood so an invalid
       field never wears the same colour as a link or a first-place badge. */
    --bb-danger: #8f2420;

    /* Dark surface treatment for heroes and headers.
       The design does not use a gradient at all: it is a FLAT ink field with a
       barely-there top wash and a 78px vertical rule texture, which is what
       makes the hero read like ruled ledger paper rather than a hero banner.

       This exists as a token because nine separate rules used to build the
       dark surface by hand as `linear-gradient(135deg, var(--bb-navy) 0%,
       #1a3a5c 100%)` - token for the first stop, hardcoded BLUE for the last.
       Repointing --bb-navy to ink therefore left every hero running warm ink
       into blue, which looked worse than before it was touched. One owner. */
    --bb-dark-wash:
        linear-gradient(180deg, rgba(250, 246, 239, 0.05) 0%, rgba(250, 246, 239, 0) 46%),
        repeating-linear-gradient(90deg, rgba(250, 246, 239, 0.035) 0 1px, transparent 1px 78px);

    /* ---- Semantic layer (brief DESIGN-IMPLEMENTATION.md §2) ---------------
       These are the names the brief specifies. Each points at the primitive
       above that already holds the value, which is ordinary token
       architecture - a primitive plus a semantic alias is NOT the "one value,
       two owners" trap. That trap was a LITERAL duplicating a token, as in
       `var(--bb-navy-mid, #0f3460)`, where the fallback silently disagreed
       with the token it was backing up.

       --bb-navy is kept for #221c18 only because 17k lines resolve through it.
       The brief's own annotation calls it "warm charcoal, no blue", so the
       honest primitive is --bb-ink and that is what everything resolves to. */
    --bb-surface-raised: var(--bb-paper);
    --bb-surface-sunken: var(--bb-tint);
    --bb-amber-on-dark: var(--bb-amber);
    --bb-amber-on-light: var(--bb-amber-dark);
    --bb-status-ok: var(--bb-moss);
    --bb-cat-analysis: var(--bb-moss-dark);

    /* Navy: dark surfaces for headers, heroes, footer. Names kept so the
       17k lines of existing rules keep resolving; the values are now ink.

       --bb-navy-light and --bb-navy-mid-light were deleted here: both had
       ZERO consumers in any stylesheet, template or script, so they were
       names with nothing behind them.

       --bb-navy-mid SURVIVES on a deadline, not on merit. It is misnamed - it
       resolves to ink and there is no navy - but it still has 26 consumers in
       this file plus athletes/profile.php:297, and Phase 0 is not allowed to
       edit templates. DELETE IT once that template is rebuilt: its real role
       is "the B side" (athlete B, series 2, the second half of a split bar),
       so its consumers want --bb-ink directly. Same deadline applies to
       --bb-data-blue below, which no rule in this file uses but eight
       template references still do. */
    --bb-navy: var(--bb-ink);
    --bb-navy-mid: var(--bb-ink);

    /* Record-trust status ramp, used by the .bb-confidence badge.
       Still a SIGNAL and still deliberately NOT oxblood, so a trust indicator
       never wears the same colour as every other accented control.
       The step was blue-after-green for colour-blind safety; with blue retired
       it is now moss / amber / grey, matching the qualified / bubble / out ramp
       the design uses on Road to Olympia. Hue does less work here than it did,
       which is safe because every one of these chips carries its own text
       label - the colour reinforces the word, it never replaces it. */
    --bb-status-high: var(--bb-moss-dark);
    --bb-status-high-soft: rgba(47, 81, 41, 0.1);
    --bb-status-medium: var(--bb-amber-dark);
    --bb-status-review: var(--bb-warm-grey-2);

    /* Accent: folded into the oxblood primary (one accent, gold retired) */
    --bb-accent: var(--bb-oxblood);
    --bb-accent-hover: var(--bb-oxblood-hover);
    --bb-accent-light: rgba(168, 55, 42, 0.1);
    --bb-accent-soft: rgba(168, 55, 42, 0.13);
    /* On ink, oxblood is too low-contrast to carry an accent; the design uses
       amber for every on-dark eyebrow, countdown figure and result number. */
    --bb-accent-on-dark: var(--bb-amber);

    /* Green */
    --bb-green: var(--bb-moss);
    --bb-green-soft: rgba(69, 114, 63, 0.1);
    --bb-green-400: var(--bb-moss-light);
    --bb-green-500: var(--bb-moss);
    --bb-green-600: var(--bb-moss-dark);
    --bb-green-700: var(--bb-moss-dark);

    /* Warm gray neutrals. 400-800 were blue-greys (#5f6978, #6b7688, #5a6577,
       #3d4555, #2a2f3d) sitting under a "warm-paper palette" heading - the
       lightest four were warm and the darkest five were not, which is why text
       on this ramp read cold against the paper it sat on. Now warm throughout. */
    --bb-gray-50: #f6f3ed;
    --bb-gray-100: #eee8dd;
    --bb-gray-200: #dfd7cb;
    --bb-gray-300: #cfc4b6;
    --bb-gray-400: #8a8076;
    --bb-gray-500: var(--bb-warm-grey-2);
    --bb-gray-600: var(--bb-warm-grey);
    --bb-gray-700: #3d372f;
    --bb-gray-800: #2c2620;
    --bb-gray-900: var(--bb-navy);

    /* Semantic aliases */
    /*
     * The page is bone and a raised surface is paper. That is what Iron & Bone
     * always described and the reverse of what shipped: .bb-app declared 166
     * tokens and no background, so the page took the theme's white while every
     * card filled with --bb-surface = bone. Measured on /olympia/2025/ at 375px,
     * a card sat 5/255 per channel from its own page with no shadow, which is
     * why every card in the plugin read as flat.
     *
     * One token carries the fix. All 96 background uses of --bb-surface are
     * raised things - cards, menus, dropdowns, inputs, tabs, table rows - and
     * not one of them is a page, so flipping it here lifts every one of them at
     * once instead of repainting 96 rules by hand.
     */
    --bb-bg: var(--bb-bone);
    --bb-surface: var(--bb-paper);
    --bb-border: rgba(34, 28, 24, 0.14);
    --bb-border-strong: rgba(34, 28, 24, 0.26);
    --bb-text-primary: var(--bb-ink);
    --bb-text-secondary: var(--bb-warm-grey);
    --bb-text-muted: var(--bb-warm-grey-2);

    /* CTA uses primary accent */
    --bb-cta: var(--bb-primary);
    --bb-cta-hover: var(--bb-primary-hover);
    --bb-cta-light: var(--bb-primary-light);

    /* Semantic status */
    --bb-success: var(--bb-moss);
    --bb-success-light: rgba(69, 114, 63, 0.1);
    --bb-verified: var(--bb-moss-dark);
    --bb-warning: var(--bb-amber);
    --bb-warning-light: rgba(217, 139, 74, 0.12);
    --bb-error: var(--bb-danger);
    --bb-error-light: rgba(143, 36, 32, 0.1);

    /* Data-visualization scale (charts, scores, and calculator bands).
       Was a stock Tailwind-ish spectrum - blue/lime/yellow/purple/rose - that
       shared nothing with the product palette. Rebuilt inside the warm ramp so
       a chart cannot introduce a hue the rest of the page never uses. */
    --bb-data-blue: var(--bb-ink);
    --bb-data-green: var(--bb-moss);
    --bb-data-lime: var(--bb-moss-light);
    --bb-data-yellow: var(--bb-amber);
    --bb-data-orange: var(--bb-amber-dark);
    --bb-data-purple: #6d4a5c;
    --bb-data-neutral: var(--bb-warm-grey-2);
    --bb-data-rose: var(--bb-oxblood);

    /* Typography: Archivo for text, IBM Plex Mono for every figure.
       Both are self-hosted (see class-bodybuilding-template-loader.php) rather
       than pulled from fonts.googleapis.com the way the design prototype does.
       The theme already opens that connection, so this is about weight and
       control, not about adding a third party - same call as the flag images.
       Archivo is the variable cut: display sizes run font-stretch 84-90%. */
    --bb-font-heading: 'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --bb-font-body: 'Archivo', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --bb-font-sans: var(--bb-font-body);
    --bb-font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;

    /* Spacing */
    --bb-space-1: 0.25rem;
    --bb-space-2: 0.5rem;
    --bb-space-3: 0.75rem;
    --bb-space-4: 1rem;
    --bb-space-5: 1.25rem;
    --bb-space-6: 1.5rem;
    --bb-space-8: 2rem;
    --bb-space-10: 2.5rem;
    --bb-space-12: 3rem;
    --bb-space-16: 4rem;
    --bb-space-20: 5rem;
    --bb-space-24: 6rem;
    --bb-space-0-5: 0.125rem;
    --bb-space-1-5: 0.375rem;
    --bb-space-2-5: 0.625rem;
    --bb-space-3-5: 0.875rem;

    /* Font sizes, in px.
     *
     * These were rem, and every value was an exact division of 16: 0.8125rem is
     * 13/16, 0.9375rem is 15/16, 1.3125rem is 21/16. The names encode the same
     * intent (fs-15, fs-21, fs-22). So the scale was computed against a 16px
     * root, but the root here is 15px, which silently rendered the entire scale
     * about 6% under its designed size: fs-15 came out at 14.06px, fs-label at
     * 12.2px, fs-2xs at 10.3px, and the smallest observed text on a page was
     * 10.6px. That is the "some fonts are too small" report, and it was one
     * cause across every route, not a per-component mistake.
     *
     * px restores the designed sizes and makes the token names true. It matches
     * a decision this stylesheet already made: .bb-app pins body copy with
     * `font-size: 15px`, and --bb-fs-page-title is px for the same reason. The
     * trade-off is that a reader's browser default font-size no longer scales
     * this text; browser zoom, which is what people actually use, still does.
     */
    --bb-fs-2xs: 11px;
    --bb-fs-xs: 12px;
    --bb-fs-label: 13px;
    --bb-fs-compact: 13.5px;
    --bb-fs-sm: 14px;
    --bb-fs-15: 15px;
    --bb-fs-base: 16px;
    --bb-fs-md: 18px;
    --bb-fs-lg: 20px;
    --bb-fs-21: 21px;
    --bb-fs-22: 22px;
    --bb-fs-xl: 24px;
    /* 32, not 30. Measured across all 15 claude-design prototypes: their section
       headings sit on 34 / 32 / 26 / 24 / 22 and 30 is not among them. This
       token drove 62 of the plugin's 124 rendered H2s, so a single wrong value
       here was most of the "headings don't match the prototype" complaint. */
    --bb-fs-2xl: 32px;
    /* The prototype's secondary section tier. It had no token, so pages reached
       for 1.6rem (25.6px) or 28px and drifted apart. */
    --bb-fs-26: 26px;
    --bb-fs-3xl: 36px;

    /* Display tier: the page H1 (athlete name, contest name, olympia year, hub
       hero) towers over section H2s. Editorial data-authority = big type, three
       clear steps (display / section / label). */
    --bb-fs-4xl: 3rem;
    --bb-fs-display: clamp(2.75rem, 5vw, 4.5rem);

    /* The page title, one size for every route.
       Thirteen different h1 classes existed and --bb-fs-display was applied by
       four separate selectors, while base .bb-page-title stayed at
       clamp(1.5rem, 5vw, 2rem), so a title's size depended on which ancestor
       happened to match: 32.8px on contest and Olympia, 60.5px on the hub, 72px
       on athlete and division. Same role, three sizes.
       30px floor so a long title does not swallow a 375px viewport, 64px cap so
       the athlete hero stays authoritative without shouting, and about 44px on a
       1050px laptop. One clamp replaces the per-hero media queries that used to
       shrink each title to its own separate mobile size.
       The floor read 38px until 2026-08-06 while this comment claimed 32, which
       is how it drifted unnoticed: on a phone the floor is the only value that
       ever applies, so it was setting a desktop number on every handset. */
    /* px, not rem, deliberately. The rem floor resolved differently between
       routes (30px on most, 31.2px on Arnold and compare) because the root font
       size is not identical everywhere, which defeats the whole point of one
       token. This plugin already pins body text with `font-size: 15px` on
       .bb-app, so px here is consistent with that existing decision. */
    --bb-fs-page-title: clamp(30px, 4.8vw, 64px);
    /* Page-title ladder. claude-design sizes the title by the page's rank and
       measures 74 / 68 / 64 / 62 / 60 / 58 / 52 / 46 across the 13 routes; live
       pinned every one to 64. Five named tiers put every route within 4px of the
       prototype without reopening per-hero sizing - the tier redefines
       --bb-fs-page-title in context, so every h1 rule keeps resolving through
       the one token that test-page-title-scale.mjs guards. */
    /* 2026-08-06: every floor lowered, because on a phone the floor IS the size.
       4.8vw is 18px at 375px, so the preferred value never wins on any handset
       and the min was doing all the work at a desktop-sized number. Measured at
       375px before the change: the hub h1 ran 42px over four lines and 160px
       tall, 12 routes on the 38px tier ran to three and four lines, and the
       longest title on that tier is 43 characters. New floors are set from the
       longest title in each tier, targeting two lines, and three for the hub,
       whose h1 is a marketing sentence rather than an entity name. */
    /*
     * Was clamp(34px, 5.4vw, 72px). 72px is a poster, not a page title: on the hub it
     * pushed the eyebrow, headline, description and stat row far enough down that the
     * hero filled a 1440x900 viewport on its own and the content below it needed a
     * scroll to exist. Dropped to the 54px rung the detail tier already occupies, so
     * this stays ON the established ladder instead of inventing an off-ladder size -
     * which is the drift test-page-title-scale.mjs exists to catch.
     *
     * The floor moves 34px to 30px with it. On a phone the floor is the ONLY value that
     * ever applies (4.1vw is 16px at 390px, so the preferred value never wins), so the
     * floor is the phone size and 34px over four wrapped lines was the worst of it.
     */
    --bb-fs-page-title-hero: clamp(30px, 4.1vw, 54px);
    --bb-fs-page-title-entity: clamp(30px, 4.5vw, 60px);
    --bb-fs-page-title-detail: clamp(28px, 4.1vw, 54px);
    --bb-fs-page-title-compact: clamp(26px, 3.6vw, 46px);

    /* Uppercase is a tier property, not a global. It costs about 12% more width
       and removes word shape, which is invisible on a one-line desktop hero and
       is the single biggest reason a phone title wraps to four lines. Declared
       as a token so the mobile override can narrow it to heroes without adding a
       selector per hero, the same way --bb-fs-page-title works. */
    --bb-page-title-transform: uppercase;

    /* ======================================================================
       Radii.

       This was not a scale. It read 6 -> 10 -> 12 -> 8 -> 10, so `lg` was
       smaller than `md` and `xl` was identical to the base. Names are how
       people choose a token, and the most-used one in the whole stylesheet,
       `--bb-radius-lg` at 99 call sites, was the one whose name lied. That is
       why the rendered site carried eight different corner radii while every
       author believed they were using the design system.

       The values come from measuring claude-design rather than taste: across
       12 prototype pages the button radius is 4px (54 of 111 controls), with
       3px on smaller chips and 0px on deliberately square surfaces. Nothing
       held 4px, so the 25 places that wanted it had to hardcode it.

       `--bb-radius-lg` deliberately keeps its 8px. It is correct where it is
       used, and moving it would silently restyle 99 sites to chase a naming
       problem. Monotonicity is restored by bringing `md` down under it, not by
       pushing `lg` up.
       ====================================================================== */
    --bb-radius-xs: 2px;
    --bb-radius-sm: 3px;
    --bb-radius: 4px;      /* base = the design's button corner */
    --bb-radius-md: 6px;
    --bb-radius-lg: 8px;   /* unchanged: 99 call sites */
    --bb-radius-xl: 12px;
    --bb-radius-2xl: 24px;
    --bb-radius-full: 9999px;

    /* Soft card shadows (warm near-black, consolidated from later layers) */
    --bb-shadow-sm: 0 1px 2px rgba(34, 28, 24, 0.06), 0 1px 1px rgba(34, 28, 24, 0.04);
    --bb-shadow: 0 16px 40px rgba(34, 28, 24, 0.07);
    --bb-shadow-md: 0 18px 46px rgba(34, 28, 24, 0.11);
    --bb-shadow-lg: 0 26px 70px rgba(34, 28, 24, 0.15);

    /* Focus ring */
    --bb-focus-ring-color: var(--bb-primary);
    --bb-focus-ring-width: 2px;
    --bb-focus-ring-offset: 2px;

    /* Transitions */
    --bb-transition-fast: 150ms;
    --bb-transition: 150ms ease;
    --bb-transition-normal: 200ms;
    --bb-transition-slow: 300ms ease;
    --bb-ease-out: cubic-bezier(0.33, 1, 0.68, 1);
    --bb-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

    /* Animation stagger */
    --bb-stagger: 60ms;

    /* Font weights */
    --bb-weight-normal: 400;
    --bb-weight-medium: 500;
    --bb-weight-semibold: 600;
    --bb-weight-bold: 700;
    --bb-weight-extrabold: 800;

    /* Level colors */
    --bb-level-beginner: #8a8076;
    --bb-level-novice: var(--bb-moss);
    --bb-level-intermediate: var(--bb-warm-grey);
    --bb-level-advanced: var(--bb-primary);
    --bb-level-elite: var(--bb-amber);

    /* Championship gold - ONE canonical winner/medal gold token.
       Phase 0: the product previously carried three golds (--bb-accent var(--bb-amber),
       --bb-gold var(--bb-amber), and an inline var(--bb-amber) in the Olympia widget). The inline
       hex is already routed through --bb-accent; this names the remaining medal
       gold as one source so every "winner/champion/medal" gold resolves from it.
       Value stays the bright medal gold: the rank-badge gradient carries dark
       text (--bb-gold-text) that needs the lighter gold to keep AA contrast, and
       "winner gold" reads as bright gold. --bb-accent stays the distinct amber
       UI-accent (warnings/elite), per the token roles. */
    /* Iron & Bone, 2026-07-29: the medal set now resolves to the warm ramp.
       The note above says "value stays the bright medal gold" and reasons
       about AA contrast for the rank badge, which was sound in isolation - but
       var(--bb-amber), #c0c0c0 and #cd7f32 are three saturated hues that appear
       nowhere else in the design, and bright gold on cream is the worst
       contrast pair on the page. The prototype carries rank with an inverted
       ink card and an amber chip, never with a metal colour.

       Kept as tokens rather than deleted because the names are load-bearing in
       ~30 rules (ribbons, rank badges, champion pills). Repointing is what
       makes "gold retired" - claimed in the --bb-accent comment since
       2026-06-20 and not true until now - actually hold. */
    /* Brief §2 splits the champion gold by surface: #8f5a1e on light, #d98b4a
       on dark. It resolves to the ON-LIGHT value because that is what its ~35
       consumers actually are - `color:` on champion names, credentials, table
       rows and era chips, all sitting on bone. The on-dark amber #d98b4a as
       text on #faf6ef is roughly 2.4:1, so pointing this at it would have put
       a contrast failure on every champion label in the plugin.
       On a dark surface, use --bb-amber-on-dark directly. */
    --bb-gold-champion: var(--bb-amber-on-light);

    /* Rank badge colors (medal gradient resolves from the championship gold) */
    --bb-gold: var(--bb-amber-on-light);
    --bb-gold-end: var(--bb-amber-deep);
    --bb-gold-text: var(--bb-bone);
    --bb-silver: #b8ada0;
    --bb-silver-end: #a0958a;
    --bb-silver-text: var(--bb-ink);
    --bb-bronze: var(--bb-amber-dark);
    --bb-bronze-end: var(--bb-amber-deep);
    --bb-bronze-text: var(--bb-bone);

    /* Container */
    --bb-container: 1240px;

    /* Touch-target floor (WCAG 2.5.5). Bake the 44px minimum at the token level
       so interactive controls never re-litigate it per component. Usable in
       min-height / min-width (NOT in @media conditions - custom properties are
       not valid in media-query feature tests). */
    --bb-touch-min: 44px;

    /* ----------------------------------------------------------------------
       BREAKPOINT SCALE (standard, named). CSS custom properties cannot be used
       inside @media conditions, so this is the documented convention every
       component should target rather than inventing new ad-hoc widths:
         --bb-bp-sm : 480px   (phone -> large phone)
         --bb-bp-md : 768px   (tablet portrait; table stacked-card threshold)
         --bb-bp-lg : 1024px  (tablet landscape / small laptop)
         --bb-bp-xl : 1240px  (matches --bb-container; desktop max)
       New media queries MUST use one of these four values. Existing ad-hoc
       breakpoints are left in place (rewriting them blind would shift layout
       behavior); migrate opportunistically when a component is touched.
       ---------------------------------------------------------------------- */

    /* ----------------------------------------------------------------------
       CHART TOKENS (Wave 1 viz foundation, see UI-REVAMP plan 2.2 + 4).
       One visual language for every chart in the .bb-chart kit. The two-series
       comparison contract is A = crimson (series-1), B = navy (series-2),
       enforced both here and in bb-charts.js so a two-athlete chart always
       reads the same way.
       ---------------------------------------------------------------------- */
    --bb-chart-series-1: var(--bb-primary);   /* crimson  - series 1 / athlete A */
    --bb-chart-series-2: var(--bb-navy-mid);  /* navy     - series 2 / athlete B */
    --bb-chart-gold: var(--bb-gold-champion); /* winner / rank-1 emphasis */
    --bb-chart-axis: var(--bb-gray-600);      /* axis tick labels */
    --bb-chart-grid: rgba(34, 28, 24, 0.08);  /* gridlines (warm ink at low alpha) */
    --bb-chart-track: var(--bb-gray-100);     /* inline dominance-bar track */

    /* Merged 2026-06-20 from the two former lower .bb-app token layers, making
       this the single source of truth. The accent is one restrained oxblood;
       --bb-primary (and -hover/-light/-soft) is consumed by --bb-cta,
       --bb-focus-ring-color, --bb-level-advanced and --bb-chart-series-1. */
    --bb-primary: var(--bb-oxblood);
    --bb-primary-hover: var(--bb-oxblood-hover);
    --bb-primary-light: rgba(168, 55, 42, 0.08);
    --bb-primary-soft: rgba(168, 55, 42, 0.13);
    --bb-border-soft: rgba(34, 28, 24, 0.09);
    --bb-control-bg: #ffffff;
    --bb-control-bg-hover: var(--bb-gray-50);
    --bb-text-tertiary: #6e665e;
}

/* ==========================================================================
   2. RESET & BASE
   ========================================================================== */

.bb-app {
    font-family: var(--bb-font-body) !important;
    font-size: 15px !important;
    line-height: 1.5 !important;
    color: var(--bb-text-primary) !important;
    background-color: var(--bb-bg) !important;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.bb-app *,
.bb-app *::before,
.bb-app *::after {
    box-sizing: border-box;
}

/* Control metrics, declared so the host theme cannot supply them.
 *
 * The theme puts line-height:40px on buttons. No control in this plugin declared
 * its own, so every one inherited a 40px line box whatever its font size, and
 * the taller the gap the more the label looked crammed: bb-methodology-toggle at
 * 12px/40px was 51px tall, bb-kit-btn 13px/40px was 56px, bb-filter-btn,
 * bb-filter-tab and bb-fantasy-tab 14px/40px were 60-62px, bb-faq-question
 * 16px/40px was 72px. Seven classes, one cause, and any control added later
 * would inherit it too.
 *
 * Only line-height. A blanket min-height was tried here to also satisfy the
 * audit's undersized-target finding and it broke real layout: the career
 * timeline's dots are <button> elements, so a 40px floor inflated every dot and
 * took the timeline to 2185px tall on a 320px viewport with tooltips clipped out
 * of the scrollport. Target sizing has to be done per component, on the controls
 * that are actually tap targets, not to every button in the plugin. */
.bb-app button,
.bb-app [role="button"],
.bb-app input[type="submit"],
.bb-app input[type="button"] {
    line-height: 1.25;
}

.bb-app img,
.bb-app video {
    max-width: 100%;
}

/* :hover deliberately absent from this list. It used to be here, which is why
   claude-design's "underline on hover" never rendered anywhere: the !important
   beat every contextual rule that tried to add one. See the hover block below. */
.bb-app a,
.bb-app a:focus,
.bb-app a:visited,
.rbct .bb-app a,
.entry-content .bb-app a {
    text-decoration: none !important;
}

.bb-app a,
.rbct .bb-app a,
.entry-content .bb-app a {
    /* One accent: links resolve from the single oxblood --bb-primary so links and
       buttons share the same restrained red.

       The theme wrappers are load-bearing, exactly as on the :hover rule below.
       A bare `.bb-app a` scores (0,1,1) and Foxiz's
       `.rbct a:where(:not(.p-url)...)` scores the same, because :where()
       contributes zero specificity - so it came down to source order and the
       theme sheet loads second. Its `var(--hyperlink-color, inherit)` then falls
       back to `inherit`, landing every unstyled link on the ancestor ink
       rgb(34,28,24) instead of oxblood. Fixing :hover alone left the rest state
       wrong on all 13 routes. */
    color: var(--bb-primary);
    transition: color var(--bb-transition);
}

/* Foxiz ties this on specificity and wins on source order, so the plugin's own
   hover colour never applied. `.rbct a:where(...):hover` looks specific but
   :where() contributes ZERO, leaving the theme at (0,2,1) - exactly what a bare
   `.bb-app a:hover` scores. Its sheet just loads second. Measured 2026-08-02:
   98 of 144 sampled links hovered to Foxiz #ff184e, 1 to the design's #85291f.
   Adding the theme's own wrappers takes this to (0,3,1) and settles it without
   !important, so components can still override with their own hover. */
.bb-app a:hover,
.rbct .bb-app a:hover,
.entry-content .bb-app a:hover {
    color: var(--bb-primary-hover);
    text-decoration-color: currentColor;
}

/* claude-design underlines links on hover at a 2px offset. Buttons, pills and
   nav chips carry their own affordance and are excluded - the prototype makes
   the same exception for its cards ("a card is one link, so the global a:hover
   must not underline every line inside it"). */
.bb-app a:hover:not([class*="bb-btn"]):not([class*="nav"]):not([class*="tab"]):not([class*="chip"]):not([class*="card"]),
.rbct .bb-app a:hover:not([class*="bb-btn"]):not([class*="nav"]):not([class*="tab"]):not([class*="chip"]):not([class*="card"]),
.entry-content .bb-app a:hover:not([class*="bb-btn"]):not([class*="nav"]):not([class*="tab"]):not([class*="chip"]):not([class*="card"]) {
    /* !important is required: the base .bb-app a rule still matches a hovered
       link and carries !important, so specificity alone loses. Same reason
       P2-13 above needed it. */
    text-decoration: underline !important;
    text-underline-offset: 2px;
}

/* P2-13 (WCAG 1.4.1): the base rule above forces text-decoration:none !important on
   every .bb-app link in all states, so the contextual hover-underline rules (which
   lacked !important) never rendered and prose/fact/table/summary links were
   distinguished by color alone (#c81e45 vs body #1a1a2e = 3.03:1). Give those
   contextual link classes a persistent rest-state underline so they are
   distinguishable without color. !important is required to beat the base rule;
   higher specificity alone does not. Nav-chip links (.bb-data-nav-link) keep their
   own pill affordance and are intentionally excluded. */
.bb-app .bb-ssr-fact dd a,
.bb-app .bb-ssr-summary__links a,
.bb-app .bb-dynasty__stat dd a,
.bb-app .bb-dynasty__table td a,
.bb-app .bb-leaderboard__foot {
    text-decoration: underline !important;
}

.bb-app h1, .bb-app h2, .bb-app h3,
.bb-app h4, .bb-app h5, .bb-app h6 {
    font-family: var(--bb-font-heading);
    font-weight: 700;
    line-height: 1.2;
    color: var(--bb-text-primary);
    margin: 0;
}

.bb-app p { margin: 0; }

/*
 * Two paragraphs in a row get air between them. Everything else keeps margin 0.
 *
 * `.bb-app p { margin: 0 }` above outranks every component rule and the
 * .bb-mb-* utilities, so splitting a wall of text into two paragraphs changed
 * the character count and nothing a reader could see: the halves rendered
 * flush and still read as one block. Measured on a live page before this rule:
 * a plain sibling <p> got 0px, a .bb-mb-4 sibling got 0px, and only an inline
 * style got 15px.
 *
 * `p + p` rather than `p` because most paragraphs in here are not prose. Card
 * meta, stat captions and form hints are single paragraphs inside a flex or
 * grid cell, where margin 0 is correct and the parent owns the spacing. The
 * adjacent-sibling form touches only the case this is for, which is a
 * paragraph that follows another paragraph.
 *
 * This replaced 33 inline `style="margin-bottom:1em;"` declarations added
 * across 25 templates when the copy pass could not reach this file.
 */
.bb-app p + p { margin-top: 1em; }

/* ==========================================================================
   3. LAYOUT
   ========================================================================== */

/*
 * The page width, which the plugin now owns.
 *
 * It used to come from the theme. Every route rendered inside
 * `.rb-container.edge-padding` - max-width 1280px, 20px of padding, border-box, so 1240px of
 * content, measured on a live page 2026-08-09 - and `--bb-container: 1240px` was chosen to match
 * it. When the plugin took over the page template (see layouts/page-shell.php) that ancestor went
 * away and `.bb-app` had no width at all: content ran edge to edge and tables stretched to the
 * monitor.
 *
 * These numbers deliberately reproduce the theme's, because a whole run of measured rules further
 * down this file - the gutter pair at the 1240px breakpoint, the nav and footer chrome
 * corrections, `.bb-app .bb-container { max-width: none }` - were all derived on the premise that
 * .bb-app is 1240px of content. Restoring the premise keeps them true. Changing the premise would
 * mean re-deriving all of them.
 *
 * Written as the token plus its gutter rather than a literal 1280, so there is still one owner
 * for the content width.
 */
.bb-app {
    box-sizing: border-box;
    max-width: calc(var(--bb-container) + 40px);
    margin-inline: auto;
    padding-inline: 20px;
}

/*
 * .bb-embed - plugin markup living inside somebody else's page.
 *
 * .bb-app is mandatory on that markup because every design token is declared on it, but .bb-app
 * also assumes it IS the page: it paints a bone canvas, centres itself at 1280px, and carries a
 * ::before that fills the viewport with bone so the gutters either side are not left white on a
 * phone. All three are correct on a plugin route and all three are wrong inside an article.
 *
 * The ::before is the one that actually breaks a page rather than just looking odd. Measured on
 * /2025-mr-olympia-results/ before this rule existed: a fixed, full-viewport bone layer painted
 * over the featured image and the whole article body, so a post whose .entry-content measured
 * 27,317px tall rendered as blank space. The content was never missing; it was covered.
 */
.bb-app.bb-embed::before {
    content: none;
}

.bb-app.bb-embed {
    /* Take the width the host gives us, do not re-box it. */
    max-width: none;
    margin-inline: 0;
    padding-inline: 0;
    /* The host page owns the background. A bone slab behind one table inside an article is wrong. */
    background: transparent !important;
    /* .bb-main's calc(100vh - 200px) floor is meaningless for an embedded fragment. */
    min-height: 0;
}

/*
 * The coverage card: this data page pointing at our own report on the event.
 *
 * The page holds the record and the article tells the story of the night, so the card has to read
 * like a link to something worth reading rather than a related-posts thumbnail. It gets the lead
 * image, the headline, the deck and the byline, and an oxblood left edge so it is legible as
 * editorial rather than as another data panel.
 *
 * The whole card is clickable and the title carries the real anchor, so a keyboard user tabs to a
 * single meaningful target instead of an image and a heading in sequence.
 */
.bb-app .bb-event-coverage-card {
    position: relative;
    display: flex;
    gap: var(--bb-space-4);
    align-items: stretch;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-left: 3px solid var(--bb-accent);
    border-radius: 3px;
    padding: var(--bb-space-4);
    margin: 0 0 var(--bb-space-6);
}

.bb-app .bb-event-coverage-card:hover {
    border-color: var(--bb-border-strong);
    border-left-color: var(--bb-accent);
}

.bb-app .bb-event-coverage-card__media {
    flex: 0 0 132px;
    max-width: 132px;
}

.bb-app .bb-event-coverage-card__img {
    display: block;
    width: 100%;
    height: 96px;
    object-fit: cover;
    border-radius: 2px;
    background: var(--bb-surface-sunken);
}

.bb-app .bb-event-coverage-card__text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    flex: 1 1 auto;
}

.bb-app .bb-event-coverage-card__kicker {
    font-family: var(--bb-font-mono);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--bb-accent);
}

.bb-app .bb-event-coverage-card__title {
    font-size: 17px;
    font-weight: 700;
    line-height: 1.3;
    margin: 0;
}

/*
 * The anchor is stretched over the whole card so any part of it is clickable, while remaining one
 * real focusable element. z-index keeps it above the card's own background but the card is not a
 * stacking context for anything else, so nothing inside it gets trapped underneath.
 */
.bb-app .bb-event-coverage-card__link {
    color: var(--bb-text-primary);
    text-decoration: none;
}

.bb-app .bb-event-coverage-card__link::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
}

.bb-app .bb-event-coverage-card__link:hover,
.bb-app .bb-event-coverage-card__link:focus-visible {
    color: var(--bb-accent);
}

.bb-app .bb-event-coverage-card__deck {
    font-size: 14px;
    line-height: 1.4;
    color: var(--bb-text-muted);
    margin: 0;
}

.bb-app .bb-event-coverage-card__meta,
.bb-app .bb-event-coverage-card__byline,
.bb-app .bb-event-coverage-card__readtime {
    font-size: 12.5px;
    color: var(--bb-text-muted);
}

.bb-app .bb-event-coverage-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-top: 2px;
}

@media (max-width: 640px) {
    .bb-app .bb-event-coverage-card {
        flex-wrap: wrap;
    }

    .bb-app .bb-event-coverage-card__media {
        flex: 1 1 100%;
        max-width: none;
    }

    .bb-app .bb-event-coverage-card__img {
        height: 160px;
    }
}

/*
 * The sidebar module: the plugin's internal links inside the theme's own sidebar.
 *
 * The markup ships with classes and no styles, so on a real post every one of these rendered as
 * run-together text: "2025Derek Lunsford", "RankingsMost wins, most titles", and eleven division
 * names welded into one paragraph. Each block below is a flex or grid layout because the elements
 * are semantic pairs - term and value, year and champion, label and description - and a pair with
 * no gap reads as one word.
 *
 * Deliberately does NOT restyle .widget or the widget title: those come from the theme, and
 * matching every other widget in that column is the point of appending into it rather than
 * building a parallel sidebar.
 */
.bb-app .bb-embed-widget__body {
    font-size: 14px;
    line-height: 1.5;
}

/* Facts: a term and its value on one row, value right-aligned so the numbers line up. */
.bb-app .bb-embed-facts {
    display: grid;
    margin: 0;
}

.bb-app .bb-embed-facts__row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--bb-space-3);
    padding: var(--bb-space-2) 0;
    border-bottom: 1px solid var(--bb-border-soft);
}

.bb-app .bb-embed-facts__row:last-child {
    border-bottom: 0;
}

.bb-app .bb-embed-facts dt {
    color: var(--bb-text-muted);
    font-size: 12px;
    letter-spacing: .04em;
    text-transform: uppercase;
    margin: 0;
}

.bb-app .bb-embed-facts dd {
    margin: 0;
    font-weight: 700;
    text-align: right;
}

/* Chips: eleven division links that must not become one sentence. */
.bb-app .bb-embed-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
}

.bb-app .bb-embed-chip {
    display: inline-block;
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
    color: var(--bb-text-primary);
    background: var(--bb-surface-sunken);
    border: 1px solid var(--bb-border);
    border-radius: 2px;
    padding: 5px 9px;
}

.bb-app .bb-embed-chip:hover,
.bb-app .bb-embed-chip:focus-visible {
    border-color: var(--bb-accent);
    color: var(--bb-accent);
}

/*
 * Champions: a year column and a name. The year is monospaced and fixed-width so the names start on
 * a common left edge down the list instead of stepping in and out with the digits.
 */
.bb-app .bb-embed-champions {
    display: grid;
    margin: 0;
    padding: 0;
    list-style: none;
    max-height: 260px;
    overflow-y: auto;
}

.bb-app .bb-embed-champions__row {
    display: flex;
    gap: var(--bb-space-3);
    padding: var(--bb-space-2) 0;
    border-bottom: 1px solid var(--bb-border-soft);
}

.bb-app .bb-embed-champions__row:last-child {
    border-bottom: 0;
}

.bb-app .bb-embed-champions__year {
    font-family: var(--bb-font-mono);
    font-size: 12.5px;
    color: var(--bb-text-muted);
    flex: 0 0 3.2em;
    font-variant-numeric: tabular-nums;
}

.bb-app .bb-embed-champions__name {
    min-width: 0;
}

.bb-app .bb-embed-champions__name a {
    color: var(--bb-accent);
    font-weight: 600;
    text-decoration: none;
}

.bb-app .bb-embed-champions__name a:hover,
.bb-app .bb-embed-champions__name a:focus-visible {
    text-decoration: underline;
}

/* Explore: a label above its own description, stacked, so the two are never one string. */
.bb-app .bb-embed-links {
    display: grid;
    gap: var(--bb-space-1, 4px);
}

.bb-app .bb-embed-link {
    display: grid;
    gap: 1px;
    padding: var(--bb-space-2) 0;
    text-decoration: none;
    border-bottom: 1px solid var(--bb-border-soft);
}

.bb-app .bb-embed-link:last-child {
    border-bottom: 0;
}

.bb-app .bb-embed-link strong {
    color: var(--bb-accent);
    font-weight: 700;
    font-size: 14px;
}

.bb-app .bb-embed-link span {
    color: var(--bb-text-muted);
    font-size: 12.5px;
    line-height: 1.4;
}

.bb-app .bb-embed-link:hover strong,
.bb-app .bb-embed-link:focus-visible strong {
    text-decoration: underline;
}

.bb-app .bb-embed-more {
    display: inline-block;
    margin-top: var(--bb-space-3);
    font-size: 12.5px;
    font-weight: 700;
    color: var(--bb-accent);
    text-decoration: none;
}

.bb-app .bb-embed-more:hover,
.bb-app .bb-embed-more:focus-visible {
    text-decoration: underline;
}

/*
 * The event strip: the plugin's one line at the top of an editorial article.
 *
 * Not a hero. The article already opens with a headline, a deck and a lead image, and a second
 * banner would repeat the image and push the writing below the fold. This says which event you are
 * reading about and links into the database, in the height of a single line.
 *
 * The markup ships its separators as real <span> elements rather than CSS borders because they are
 * aria-hidden and must not be read out; without these rules they rendered as bare slashes with no
 * spacing, which is how the first pass looked on a real post.
 */
.bb-app.bb-embed--strip {
    margin: 0 0 var(--bb-space-5);
}

.bb-app .bb-embed-strip {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    padding-bottom: var(--bb-space-3);
    border-bottom: 1px solid var(--bb-border-soft);
    font-size: 13px;
    line-height: 1.5;
    color: var(--bb-text-muted);
}

/* The event itself reads as a chip, so the eye finds the database link first. */
.bb-app .bb-embed-strip__event {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bb-accent);
    text-decoration: none;
    border: 1px solid var(--bb-accent-soft);
    border-radius: 2px;
    padding: 4px 9px;
    white-space: nowrap;
}

.bb-app .bb-embed-strip__event:hover,
.bb-app .bb-embed-strip__event:focus-visible {
    background: var(--bb-accent);
    border-color: var(--bb-accent);
    color: var(--bb-bone);
}

/* A hairline, not a glyph: the slash in the markup is decorative and aria-hidden. */
.bb-app .bb-embed-strip__sep {
    width: 1px;
    height: 12px;
    background: var(--bb-border);
    overflow: hidden;
    text-indent: -99em;
    flex: 0 0 1px;
}

.bb-app .bb-embed-strip a:not(.bb-embed-strip__event) {
    color: var(--bb-text-primary);
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid var(--bb-border-soft);
}

.bb-app .bb-embed-strip a:not(.bb-embed-strip__event):hover,
.bb-app .bb-embed-strip a:not(.bb-embed-strip__event):focus-visible {
    color: var(--bb-accent);
    border-bottom-color: var(--bb-accent);
}

/*
 * Full bleed on phones.
 *
 * The 20px above reproduces the theme's desktop gutter, but on a phone it wastes 40px of a
 * 375px screen and boxes every band - nav, hero, tables - inside a margin the design does not
 * want there. Dropping it lets the bands run to the glass. Text does NOT end up on the edge:
 * .bb-container carries its own gutter at these widths (clamp(16px, 4vw, 24px) below 1240, and
 * --bb-space-2 below 768), so the gutter moves from the wrapper to the content, which is where
 * it belongs.
 */
@media (max-width: 768px) {
    .bb-app {
        padding-inline: 0;
    }
}

/*
 * The breadcrumb bar.
 *
 * It had no styling whatsoever: the trail was emitted with zero margin and zero padding, so it
 * sat wedged between the nav and <main> with a measured 0px gap on both sides, at full ink
 * weight. A breadcrumb is orientation, not content - it wants air above it and a lighter voice
 * than the page it introduces.
 *
 * The top space is larger than the bottom on purpose: <main> already contributes 32px of its own
 * padding-top underneath, so matching them would leave the trail floating mid-way between the two
 * bands instead of belonging to the page below it.
 */
.bb-app .bb-breadcrumb-bar {
    padding-top: var(--bb-space-5);
    padding-bottom: var(--bb-space-2);
    font-size: 13px;
    line-height: 1.5;
}

.bb-app .bb-breadcrumb-bar .breadcrumb-inner {
    color: var(--bb-text-muted);
    font-size: 13px;
}

.bb-app .bb-breadcrumb-bar a {
    color: var(--bb-text-muted);
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.bb-app .bb-breadcrumb-bar a:hover,
.bb-app .bb-breadcrumb-bar a:focus-visible {
    color: var(--bb-accent);
    border-bottom-color: var(--bb-accent);
}

/* The current page is the one item that is not a link, so it carries the weight. */
.bb-app .bb-breadcrumb-bar .breadcrumb-inner > :last-child {
    color: var(--bb-text-primary);
}

.bb-container {
    width: 100%;
    max-width: var(--bb-container);
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--bb-space-4);
    padding-right: var(--bb-space-4);
}

@media (min-width: 640px) {
    .bb-container {
        padding-left: var(--bb-space-6);
        padding-right: var(--bb-space-6);
    }
}

.bb-main {
    min-height: calc(100vh - 200px);
    padding-top: var(--bb-space-8);
    padding-bottom: var(--bb-space-16);
}

/* Skip Link */
.bb-skip-link {
    position: absolute;
    top: -9999px;
    left: 16px;
    clip: rect(0, 0, 0, 0);
    overflow: hidden;
    background: var(--bb-gray-800);
    color: white !important;
    padding: var(--bb-space-2) var(--bb-space-4);
    z-index: 100;
    border-radius: var(--bb-radius);
    transition: none;
}

.bb-skip-link:focus {
    top: 16px;
    clip: auto;
    overflow: visible;
}

/* Grid */
.bb-grid   { display: grid; gap: var(--bb-space-4); }
.bb-grid-2 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.bb-grid-3 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.bb-grid-4 { grid-template-columns: repeat(1, minmax(0, 1fr)); }

@media (min-width: 480px) {
    .bb-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .bb-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 768px) {
    .bb-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .bb-grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
    .bb-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .bb-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ==========================================================================
   4. TYPOGRAPHY
   ========================================================================== */

.bb-page-title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-page-title);
    font-weight: var(--bb-weight-extrabold);
    color: var(--bb-text-primary);
    letter-spacing: -0.03em;
    margin-bottom: var(--bb-space-4);
    line-height: 1.15;
}

.bb-page-subtitle {
    font-size: 15px;
    color: var(--bb-text-secondary);
    margin-bottom: var(--bb-space-8);
    max-width: 500px;
}

/* Section tier. .bb-section-heading and .bb-section-title are the same role and
   the .bb-app layer already gives them one size and weight; only the alignment
   had never been reconciled, so a "Frequently Asked Questions" heading centred
   itself while every sibling section heading on the same page sat left. Left is
   the majority and the right default for content and data pages. Deliberate
   centring belongs on the wrapper (.bb-section-header), not on the role. */
.bb-section-heading {
    font-family: var(--bb-font-heading);
    font-size: 20px;
    font-weight: 800;
    color: var(--bb-text-primary);
    letter-spacing: -0.02em;
    margin-bottom: 20px;
}

.bb-seo-heading {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--bb-text-primary);
    letter-spacing: -0.02em;
    margin-bottom: var(--bb-space-4);
}

.bb-seo-content {
    max-width: 800px;
    color: var(--bb-text-secondary);
    line-height: 1.7;
    font-size: var(--bb-fs-base);
}

.bb-seo-content p {
    margin-bottom: var(--bb-space-4);
}

.bb-seo-content p:last-child {
    margin-bottom: 0;
}

.bb-seo-content strong {
    color: var(--bb-text-primary);
    font-weight: 700;
}

.bb-seo-content a {
    color: var(--bb-primary);
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color var(--bb-transition);
}

.bb-seo-content a:hover {
    border-bottom-color: var(--bb-primary);
}

/* ==========================================================================
   5. NAVIGATION
   ========================================================================== */

.bb-nav {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--bb-gray-200);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
    transition: all var(--bb-transition);
}

.bb-nav > .bb-container {
    max-width: 100%;
    padding: 0 var(--bb-space-4);
}

.bb-nav-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 6px 0;
}

.bb-app .bb-nav-logo {
    display: flex;
    align-items: center;
    gap: 4px;
    font-weight: 900;
    font-size: 22px;
    color: var(--bb-text-primary);
    letter-spacing: -0.03em;
    flex-shrink: 0;
    text-decoration: none;
    transition: opacity 0.15s;
}

.bb-app .bb-nav-logo:hover {
    opacity: 0.8;
    color: var(--bb-text-primary);
}

.bb-nav-logo-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    color: var(--bb-primary);
}

.bb-nav-logo-icon svg,
.bb-nav-logo-icon img {
    width: 30px;
    height: 30px;
    object-fit: contain;
}

.bb-nav-logo-text {
    font-weight: 700;
    font-size: 1.1rem;
    letter-spacing: 0.04em;
}

.bb-nav-links {
    display: none;
    align-items: center;
    gap: 2px;
    flex: 1;
    justify-content: center;
}

@media (min-width: 769px) {
    .bb-nav-links {
        display: flex;
    }
}

.bb-nav-link {
    color: var(--bb-text-muted);
    font-weight: 500;
    font-size: 13px;
    padding: 4px 12px;
    border-radius: 6px;
    border: none;
    transition: all 0.15s;
    display: flex;
    align-items: center;
    white-space: nowrap;
}

.bb-nav-link:hover {
    color: var(--bb-text-primary);
    background: var(--bb-gray-50);
}

.bb-nav-dropdown-item.bb-nav-link-active,
.bb-nav-dropdown-item.bb-nav-link-active:hover {
    background: none;
    border: none;
    border-bottom: none;
    color: var(--bb-primary);
    font-weight: 600;
}

.bb-nav-actions {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    flex-shrink: 0;
}

.bb-app .bb-nav-auth-btn {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    background: var(--bb-navy);
    color: #fff;
    border-radius: var(--bb-radius-full);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    transition: all 0.15s;
    white-space: nowrap;
}

.bb-app .bb-nav-auth-btn:hover {
    background: var(--bb-primary);
    color: #fff;
    text-decoration: none;
}

.bb-app .bb-nav-auth-btn svg {
    opacity: 0.85;
}

.bb-nav-mobile-auth {
    display: flex;
    gap: 8px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--bb-gray-100);
}

/* Unit Toggle */
.bb-unit-toggle {
    display: flex;
    align-items: center;
    background: var(--bb-gray-100);
    border-radius: var(--bb-radius-full);
    padding: 3px;
    border: 1px solid var(--bb-gray-200);
}

.bb-unit-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px 30px;
    background: transparent;
    border: none;
    border-radius: var(--bb-radius-full);
    font-size: 12px;
    font-weight: 700;
    color: var(--bb-text-muted);
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    line-height: 1;
}

.bb-unit-btn:hover:not(.bb-unit-btn-active) {
    color: var(--bb-text-primary);
}

.bb-unit-btn-active {
    background: var(--bb-navy);
    color: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}

.bb-unit-toggle-inline {
    display: flex;
    background: var(--bb-gray-100);
    border-radius: var(--bb-radius);
    padding: 3px;
}

.bb-unit-toggle-inline .bb-unit-btn {
    padding: 10px 30px;
    font-size: 13px;
    font-weight: 600;
    border: none;
    background: transparent;
    color: var(--bb-text-muted);
    cursor: pointer;
    border-radius: calc(var(--bb-radius) - 3px);
    transition: all 0.15s;
    font-family: inherit;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.bb-unit-toggle-inline .bb-unit-btn-active {
    background: var(--bb-surface);
    color: var(--bb-primary);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Hamburger */
.bb-nav-hamburger {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0;
    border-radius: var(--bb-radius);
    transition: background var(--bb-transition);
}

.bb-nav-hamburger:hover {
    background: var(--bb-gray-100);
}

.bb-nav-hamburger-icon {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.bb-nav-hamburger-icon span {
    display: block;
    width: 22px;
    height: 2px;
    background: var(--bb-gray-700);
    border-radius: 1px;
    transition: all 0.2s ease;
    transform-origin: center;
}

.bb-nav-hamburger[aria-expanded="true"] .bb-nav-hamburger-icon span:nth-child(1) {
    transform: rotate(45deg) translate(5px, 5px);
}

.bb-nav-hamburger[aria-expanded="true"] .bb-nav-hamburger-icon span:nth-child(2) {
    opacity: 0;
    transform: scaleX(0);
}

.bb-nav-hamburger[aria-expanded="true"] .bb-nav-hamburger-icon span:nth-child(3) {
    transform: rotate(-45deg) translate(5px, -5px);
}

/* Mobile Menu */
.bb-nav-mobile {
    background: var(--bb-surface);
    border-bottom: 1px solid var(--bb-gray-200);
    box-shadow: var(--bb-shadow-md);
    overflow: hidden;
}

@media (min-width: 769px) {
    .bb-nav-mobile { display: none !important; }
    .bb-nav-hamburger { display: none !important; }
}

@media (max-width: 768px) {
    .without-sidebar .s-ct { padding-right: 2px; padding-left: 2px; }
    .bb-nav-hamburger { display: flex !important; }
    .bb-nav-links { display: none !important; }
    .bb-nav-auth-btn { display: none !important; }
    .bb-unit-toggle { padding: 2px; }
    .bb-unit-btn { padding: 6px 12px; font-size: 11px; }
    .bb-nav-actions { gap: var(--bb-space-2); }
    .bb-container { padding-left: var(--bb-space-2); padding-right: var(--bb-space-2); }
    .bb-nav > .bb-container { padding: 0 var(--bb-space-2); }
    .bb-main { padding-top: var(--bb-space-4); }
    .bb-unit-toggle-inline .bb-unit-btn { padding: 8px 16px; }
}

.bb-nav-mobile-inner {
    padding: var(--bb-space-4);
}

.bb-nav-mobile-links {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-1);
}

.bb-app .bb-nav-mobile-link {
    display: block;
    padding: var(--bb-space-3) var(--bb-space-4);
    color: var(--bb-gray-700);
    font-weight: 500;
    font-size: var(--bb-fs-15);
    border-radius: var(--bb-radius);
    transition: background var(--bb-transition);
    text-decoration: none;
}

.bb-app .bb-nav-mobile-link:hover,
.bb-app .bb-nav-mobile-link:focus {
    background: var(--bb-gray-50);
    color: var(--bb-gray-900);
}

.bb-app .bb-nav-mobile-link[aria-current="page"] {
    background: var(--bb-primary-light);
    color: var(--bb-primary);
}

.bb-nav-mobile-group {
    padding: 8px 0;
    border-bottom: 1px solid var(--bb-gray-100);
}

.bb-nav-mobile-group:last-child { border-bottom: none; }

.bb-nav-mobile-group-label {
    padding: 4px 16px;
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    text-transform: uppercase;
    color: var(--bb-gray-400);
    letter-spacing: 0.05em;
}

/* Nav Dropdowns */
.bb-nav-dropdown {
    position: relative;
    display: flex;
    align-items: center;
}

.bb-nav-dropdown-trigger {
    display: flex;
    align-items: center;
    gap: 3px;
    cursor: pointer;
    background: none;
    border: none;
    border-radius: 6px;
    padding: 4px 6px;
    font-family: inherit;
    font-size: inherit;
    transition: all 0.15s;
    color: inherit;
}

.bb-nav-dropdown-trigger svg {
    width: 12px;
    height: 12px;
    opacity: 0.5;
    transition: transform 0.2s ease, opacity 0.2s ease;
}

.bb-nav-dropdown:hover .bb-nav-dropdown-trigger svg,
.bb-nav-dropdown[data-open="true"] .bb-nav-dropdown-trigger svg {
    opacity: 0.8;
}

.bb-nav-dropdown[data-open="true"] .bb-nav-dropdown-trigger svg {
    transform: rotate(180deg);
}

.bb-nav-dropdown-menu {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    min-width: 200px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-lg);
    padding-top: 12px;
    padding-bottom: 8px;
    z-index: 50;
    opacity: 0;
    visibility: hidden;
    transform: translateX(-50%) translateY(-4px);
    transition: all 0.15s ease;
}

.bb-nav-dropdown-menu::before {
    content: "";
    position: absolute;
    top: -12px;
    left: 0;
    right: 0;
    height: 12px;
}

.bb-nav-dropdown[data-open="true"] .bb-nav-dropdown-menu {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

.bb-app .bb-nav-dropdown-item {
    display: block;
    padding: 8px 16px;
    font-size: 0.875rem;
    color: var(--bb-gray-700);
    font-weight: 500;
    text-decoration: none;
    transition: background 0.1s ease, color 0.1s ease;
    white-space: nowrap;
}

.bb-app .bb-nav-dropdown-item:hover {
    background: var(--bb-gray-50);
    color: var(--bb-primary);
}

.bb-nav-dropdown-divider {
    height: 1px;
    background: var(--bb-gray-100);
    margin: 4px 0;
}

.bb-brand-accent { color: var(--bb-primary); }

.bb-app .bb-nav-group-active {
    color: var(--bb-text-primary);
    font-weight: 600;
    background: rgba(178, 58, 53, 0.07);
    border: none;
    border-radius: 6px;
}

/* ==========================================================================
   6. COMPONENTS
   ========================================================================== */

/* --- Cards --- */

.bb-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-4);
    /* Static card: hairline only, no resting shadow (shadow returns on :hover). */
    box-shadow: none;
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-card:hover {
    border-color: var(--bb-gray-300);
    box-shadow: var(--bb-shadow-md);
}

.bb-card--link {
    cursor: pointer;
    text-decoration: none;
    display: block;
    color: inherit;
}

.bb-card--link:hover {
    border-color: var(--bb-primary);
}

.bb-card-hover {
    cursor: pointer;
    transition: border-color var(--bb-transition);
}

.bb-card-hover:hover {
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}

.bb-card-header {
    padding: var(--bb-space-6);
    border-bottom: 1px solid var(--bb-gray-100);
}

.bb-card-body {
    padding: var(--bb-space-6);
}

.bb-card-footer {
    padding: var(--bb-space-4) var(--bb-space-6);
    background: var(--bb-gray-50);
    border-top: 1px solid var(--bb-gray-100);
    border-radius: 0 0 var(--bb-radius-lg) var(--bb-radius-lg);
}

.bb-card-interactive {
    transition: box-shadow 0.2s ease;
    cursor: pointer;
}

.bb-card-interactive:hover {
    box-shadow: var(--bb-shadow-md);
}

.bb-card-interactive:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}

.bb-card-title {
    font-size: var(--bb-fs-md);
    font-weight: 700;
    color: var(--bb-text-primary);
}

.bb-card-heading {
    margin: 0;
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
}

/* Stat card */
.bb-stat-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-stat-card:hover {
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}

.bb-stat-card-label {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
}

.bb-stat-card-value {
    font-size: var(--bb-fs-2xl);
    font-weight: 800;
    color: var(--bb-text-primary);
    letter-spacing: -0.02em;
}

.bb-stat-card-sub {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}

/* --- Tables --- */

.bb-table-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    /* Static table card: hairline only, no resting shadow. */
    box-shadow: none;
}

/* Override theme global thead dark background */
.bb-app thead,
div.bb-app thead,
body .bb-app thead,
body .bb-app table thead {
    background: transparent !important;
    background-color: transparent !important;
    background-image: none !important;
    color: inherit !important;
}

.bb-app th,
.bb-app td,
body .bb-app th,
body .bb-app td {
    border: none !important;
    border-color: transparent !important;
}

.bb-app .bb-table th,
.bb-app .bb-results-table th,
.bb-app thead th,
body .bb-app thead th {
    padding: 12px 18px;
    font-size: 11px;
    font-weight: 700;
    color: var(--bb-text-muted) !important;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-bottom: 2px solid var(--bb-border) !important;
    border-top: none !important;
    border-left: none !important;
    border-right: none !important;
    background: transparent !important;
    background-color: transparent !important;
}

.bb-app tbody td {
    padding: 14px 18px;
    border-bottom: 1px solid var(--bb-border) !important;
    border-top: none !important;
    border-left: none !important;
    border-right: none !important;
    color: var(--bb-text-secondary);
}

.bb-app tbody tr:last-child td {
    border-bottom: none !important;
}

.bb-app tbody tr:hover {
    /* Flat warm-gray row hover, not an accent wash. */
    background: var(--bb-gray-50);
}

.bb-table-wrapper {
    width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    background: var(--bb-surface);
    border-radius: var(--bb-radius-lg);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(0, 0, 0, 0.03);
}

.bb-app .bb-table-scroll-wrapper {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.bb-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.bb-table th {
    text-align: left;
    padding: 12px 18px;
    font-size: 11px;
    font-weight: 700;
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-bottom: 2px solid var(--bb-border);
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
}

.bb-table td {
    padding: 14px 18px;
    border-bottom: 1px solid var(--bb-border);
    color: var(--bb-text-secondary);
}

.bb-table tbody tr:last-child td { border-bottom: none; }
/* Data-authority tables: no zebra striping (rows separate by hairline only),
   flat warm-gray row hover (not a tinted accent wash). */
.bb-app .bb-table tbody tr:hover { background-color: var(--bb-gray-50); }

.bb-td-athlete-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--bb-navy-mid) 0%, var(--bb-navy) 100%);
    color: white;
    font-size: 13px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.bb-td-athlete-name {
    font-weight: 700;
    color: var(--bb-navy);
}

.bb-td-athlete-name a { color: var(--bb-navy); }
.bb-td-athlete-name a:hover { color: var(--bb-primary); }

.bb-table-weight-class {
    font-weight: 500;
    color: var(--bb-gray-800);
}

.bb-results-table-wrapper { overflow-x: auto; }

.bb-results-table {
    width: 100%;
    border-collapse: collapse;
}

.bb-results-table th,
.bb-results-table td { text-align: left; }

.bb-results-table th {
    padding: 12px 18px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-text-muted);
    border-bottom: 2px solid var(--bb-border);
}

.bb-results-table td {
    padding: 14px 18px;
    font-size: 14px;
    color: var(--bb-text-secondary);
    border-bottom: 1px solid var(--bb-border);
}

.bb-results-table tbody tr:last-child td { border-bottom: none; }
.bb-results-table tbody tr:hover { background: var(--bb-gray-50); }
.bb-results-table tr.bb-highlight { background: var(--bb-gray-50); }

/* Placement colors in table rows */
.bb-table tbody tr.placement-1 > td:first-child { color: var(--bb-gold); font-weight: 700; }
.bb-table tbody tr.placement-2 > td:first-child { color: var(--bb-silver); font-weight: 700; }
.bb-table tbody tr.placement-3 > td:first-child { color: var(--bb-bronze); font-weight: 700; }

/* Responsive table */
@media (max-width: 768px) {
    .bb-app .bb-table--responsive { display: block; }
    .bb-app .bb-table--responsive thead { display: none; }
    .bb-app .bb-table--responsive tbody { display: block; }
    .bb-app .bb-table--responsive tbody tr {
        display: block;
        background: var(--bb-surface);
        border: 1px solid var(--bb-gray-200);
        border-radius: var(--bb-radius-md);
        padding: 0.75rem 1rem;
        margin-bottom: 0.5rem;
    }
    .bb-app .bb-table--responsive td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        /*
         * The row is a label from ::before plus the cell's own content. Neither
         * could shrink and the row could not wrap, so on a 120px cell a 89px
         * "Country" label and a 70px value came to 159px and the value hung 39px
         * outside the cell - 45 instances across /athletes/ and /olympia/2022/
         * at 390px. It produced no document overflow, so every responsive sweep
         * called these routes clean at this exact width.
         */
        flex-wrap: wrap;
        gap: 0.25rem 0.75rem;
        min-width: 0;
        padding: 0.25rem 0;
        border: none;
        font-size: 0.9rem;
    }
    /* The label keeps its size; the value takes what is left and truncates
       rather than pushing past the edge. */
    .bb-app .bb-table--responsive td::before { flex: 0 0 auto; }
    .bb-app .bb-table--responsive td > * {
        min-width: 0;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .bb-app .bb-table--responsive td::before {
        content: attr(data-label);
        font-weight: 600;
        color: var(--bb-text-secondary);
        font-size: 0.8rem;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        flex-shrink: 0;
        margin-right: 1rem;
    }
    .bb-app .bb-table--responsive td:first-child {
        font-weight: 700;
        font-size: 1rem;
        padding-bottom: 0.5rem;
        margin-bottom: 0.25rem;
        border-bottom: 1px solid var(--bb-border);
    }
    /* P0-3: only release the scroll wrapper when its table actually stacks into
       cards (.bb-table--responsive). A plain .bb-table (e.g. athlete Career
       Results) must keep overflow-x:auto from .bb-table-scroll-wrapper so its
       columns stay reachable instead of being clipped at <=768px. */
    .bb-app .bb-table-scroll-wrapper:has(.bb-table--responsive) { overflow-x: visible; }

    /*
     * Compact result card.
     *
     * The generic stack above gives every cell its own full-width row with an
     * uppercase label above it. On a results table that is six rows per athlete:
     * measured 341px median per competitor on /olympia/2025/ at 375px, so two
     * athletes filled a phone screen and a 20-competitor division ran to seven
     * thousand pixels. Placing, name and score belong on one card, not six.
     *
     * SCOPED TO .bb-table--results ON PURPOSE. The layout below addresses cells
     * by position - 1 placing, 2 athlete, 3 country, 4+ scores - which is only
     * true for the results tables in partials/event-detail.php. The athlete
     * directory and the schedule carry .bb-table--responsive with entirely
     * different columns and keep the generic stack. A table that wants this
     * treatment has to opt in by carrying the class, not by being narrow.
     *
     * The placing is lifted out of the flow into a gutter instead of sitting in
     * the text column. A first pass kept it inline and every following line
     * hung off a different left edge, with TOTAL wrapping out from under the
     * name entirely. One hanging indent puts name, country and scores on a
     * single edge at any name length.
     */
    .bb-app .bb-table--results.bb-table--responsive tbody tr {
        display: block;
        position: relative;
        padding: 10px 13px 10px 62px;
        margin-bottom: 6px;
    }
    .bb-app .bb-table--results.bb-table--responsive tbody td {
        display: block;
        padding: 0;
        margin: 0;
        font-size: var(--bb-fs-label);
        line-height: 1.45;
        /*
         * !important because it is answering one: `.bb-app tbody td` at :1777
         * declares `border-bottom: 1px solid !important` to hold the row rule
         * against the Foxiz `th, td` border, and a plain `border: 0` here loses
         * to it however specific the selector is. Inside a card the divider is
         * an artifact - it drew a hairline under the name, the country and the
         * scores of every competitor.
         */
        border: 0 !important;
    }
    .bb-app .bb-table--results.bb-table--responsive tbody td::before {
        display: none;
    }
    /* Placing, in the gutter. Fixed width so a 1st and a 12th share an edge. */
    .bb-app .bb-table--results.bb-table--responsive tbody td:nth-child(1) {
        position: absolute;
        left: 12px;
        top: 11px;
        width: 42px;
        text-align: center;
        font-size: var(--bb-fs-label);
        padding-bottom: 0;
        margin-bottom: 0;
        border-bottom: 0;
    }
    .bb-app .bb-table--results.bb-table--responsive tbody td:nth-child(2) {
        font-weight: 700;
        font-size: var(--bb-fs-15);
        line-height: 1.3;
    }
    .bb-app .bb-table--results.bb-table--responsive tbody td:nth-child(3) {
        font-size: var(--bb-fs-xs);
        margin-top: 1px;
    }
    /* The country cell wraps its flag and label in a link that the generic
       stack lays out as a flex row pushed to the far edge. Inline here, so it
       reads as a line of text under the name rather than a floating chip. */
    .bb-app .bb-table--results.bb-table--responsive tbody td:nth-child(3) > * {
        display: inline;
        color: var(--bb-text-secondary);
        font-weight: 500;
    }
    /* Scores run together on one line and wrap as a group, each keeping its
       label so a bare 14.00 never has to be guessed at. */
    .bb-app .bb-table--results.bb-table--responsive tbody td:nth-child(n+4) {
        display: inline-block;
        margin: 3px 12px 0 0;
        font-size: var(--bb-fs-xs);
    }
    .bb-app .bb-table--results.bb-table--responsive tbody td:nth-child(n+4)::before {
        display: inline;
        content: attr(data-label) " ";
        font-size: var(--bb-fs-2xs);
        color: var(--bb-text-muted);
        margin: 0 3px 0 0;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        font-weight: 600;
    }

    /*
     * Compact directory card.
     *
     * The generic stack above gives every cell a full-width row with an
     * uppercase label above the value. On a seven-column table that is seven
     * rows per record: measured 2026-08-06 at 375px, one contest on /schedule/
     * stood 329px and 137 of them made a 50,565px page, while one athlete on
     * /athletes/ stood 372px so a phone screen held two names. Nearly all of
     * that height is label lines above values that already say what they are -
     * "Aug 8, 2026" does not need a DATE above it.
     *
     * So: labels off, the long values on their own line, the short ones sharing
     * a wrapping chip line, and a label kept only where the value is a bare
     * number nobody could guess (Results, Wins, Last winner).
     *
     * TWO COMPACT MECHANISMS NOW EXIST AND THAT IS DELIBERATE. This one keys on
     * data-label; .bb-table--results above keys on cell position. Position is
     * right there because those tables are generated by one partial with fixed
     * columns, and wrong here because /schedule/ and /athletes/ have entirely
     * different column orders. Do not unify them - the results tables would
     * lose the placing gutter, which position is the only way to express.
     *
     * Opt-in by class, never by column name. A table gets this because its
     * template asks for it, so a new table with a column called "Date" does not
     * silently inherit a layout designed for something else.
     *
     * The data-label coupling is checked by tests/test-mobile-table-cards.mjs:
     * rename a header and these selectors stop matching with no error at all,
     * and the card quietly returns to the tall stack.
     */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody tr {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        column-gap: 10px;
        padding: 11px 13px;
        margin-bottom: 6px;
    }
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td {
        display: block;
        flex: 0 0 auto;
        width: auto;
        min-width: 0;
        padding: 0;
        margin: 0;
        font-size: var(--bb-fs-xs);
        font-weight: 500;
        line-height: 1.5;
        color: var(--bb-text-secondary);
        /* Answering `.bb-app tbody td`'s `border-bottom: … !important` at :1777,
           the same rule the results card has to answer. Inside a card the row
           divider draws a hairline through the middle of one record. */
        border: 0 !important;
    }
    /* An empty cell is hidden at :22956, and the reset above is more specific
       than that rule, so it has to be restated or every blank cell comes back
       as a gap in the chip line. */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td.bb-cell-empty {
        display: none;
    }
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td::before {
        display: none;
    }
    /* The headline: contest name, athlete name. Full width, and first. */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Contest"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Name"] {
        flex: 0 0 100%;
        order: 1;
        font-size: var(--bb-fs-15);
        font-weight: 700;
        line-height: 1.3;
        color: var(--bb-text-primary);
        padding-bottom: 0;
        margin-bottom: 1px;
    }
    /* Identity line: when and what, directly under the name. */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Date"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Division"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Country"] {
        order: 2;
    }
    /*
     * Location gets its own line. It is the one value that cannot share: a full
     * "Altamonte Springs, FL, United States" measures 196px of a 296px row, so
     * anything beside it wraps to a second line anyway and the reader loses the
     * left edge. This is the lesson from the /seasons/2024/ attempt, where four
     * wide cells were forced onto shared lines and the card came out at 239px.
     */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Location"] {
        flex: 0 0 100%;
        order: 3;
    }
    /* Everything else runs together on a wrapping meta line at the bottom. */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Federation"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Divisions"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Last winner"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Career"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Results"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Wins"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Tier"],
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Status"] {
        order: 4;
    }
    /*
     * On a schedule, the status IS a date - "Starts in 2 days" belongs beside
     * "Aug 8, 2026", not down with the federation. Left on the meta line it did
     * not fit beside a 141px federation and a 79px tier, so every one of the
     * 137 contests spent a 26px line on a single badge.
     *
     * A modifier rather than a change to the shared rule, because on the
     * athlete directory the same cell says "Retired", which is a career fact
     * and reads correctly next to the career span. Promoting it there would
     * push the division badge off the identity line and cost the height back.
     */
    .bb-app .bb-table--compact-card--event.bb-table--responsive tbody td[data-label="Status"] {
        order: 2;
    }
    /* A bare 31 or a bare name is the one case a label still earns its line. */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Results"]::before,
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Wins"]::before,
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Last winner"]::before {
        display: inline;
        content: attr(data-label) " ";
        font-size: var(--bb-fs-2xs);
        color: var(--bb-text-muted);
        margin: 0 3px 0 0;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        font-weight: 600;
    }
    /* The country cell wraps its flag and label in a link the generic stack
       lays out as a full-width flex row; inline, it reads as part of the line. */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Country"] > * {
        display: inline;
    }
    /*
     * The champion marker is a trophy icon plus a title count, and the icon is
     * a block-level SVG. Inside an inline parent that block opens a line box of
     * its own, so the icon, the count and the athlete's name each took a line
     * and one name cell measured 53px. inline-flex keeps the marker a single
     * inline object that the name sits beside.
     */
    .bb-app .bb-table--compact-card.bb-table--responsive tbody td[data-label="Name"] .bb-champ-marker {
        display: inline-flex;
        align-items: center;
        gap: 2px;
    }
}

/* --- Badges --- */

/*
 * Measured against claude-design: the prototype badge is h=26, radius 3px, 12px,
 * weight 600. This rendered at 6px / 11px / 700, and the 6px was hardcoded rather
 * than taken from a token, so it did not move when the scale was repaired.
 *
 * min-height rather than a fixed height: 141 of 570 badges rendered at 41px
 * instead of 25px because a long division name wraps to a second line, and one
 * class rendering at two heights is most of what makes the page look unsettled.
 * Pinning the height would clip those labels and forcing nowrap would push them
 * out of a 320px column, so the floor holds the common case steady and the long
 * ones still grow rather than break.
 */
.bb-badge {
    display: inline-flex;
    align-items: center;
    min-height: 26px;
    padding: 3px 10px;
    font-size: 12px;
    font-weight: 600;
    border-radius: var(--bb-radius-sm);
    letter-spacing: 0.02em;
}

.bb-badge--default {
    background: var(--bb-gray-100);
    color: var(--bb-gray-600);
}

.bb-badge--primary {
    background: var(--bb-primary-light);
    color: var(--bb-primary);
}

/* P2-11: was used in divisions/detail.php (Olympia "most titles" highlight) but
   never defined, so it rendered as unstyled dark text. This makes the most-titled
   champion badge the visual anchor it was meant to be. */
.bb-badge--accent {
    background: rgba(178, 58, 53, 0.12);
    color: var(--bb-primary);
    border: 1px solid rgba(178, 58, 53, 0.3);
}

/* The old #1a7d45 measured 4.78:1 - but on PAPER. These badges also render on
   bone, where the same pair is 4.21:1, under the floor. --bb-moss-dark gives
   7.34:1 on bone and 7.88:1 on paper, so the surface no longer decides whether it
   passes. */
.bb-badge--success {
    background: var(--bb-success-light);
    color: var(--bb-moss-dark);
}

/* Record badge. A link, so it needs its own colour rather than inheriting the
   page link blue-free ink, and an underline on hover to read as clickable. */
.bb-badge--record {
    background: var(--bb-tint);
    color: var(--bb-amber-on-light);
    text-decoration: none;
}
.bb-badge--record:hover,
.bb-badge--record:focus-visible {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.bb-badge--warning {
    background: rgba(217, 139, 74, 0.12);
    color: #8f6200; /* P1-12: was var(--bb-amber-dark) = 2.44:1 on tint; #8f6200 = 4.93:1 (AA at 11px/700) */
}

/* No template emits this single-dash spelling; kept in step with the real one
   rather than left behind as an emerald rule at ~2:1. */
.bb-badge-success {
    background: var(--bb-success-light);
    color: var(--bb-moss-dark);
}

.bb-badge-neutral {
    background: var(--bb-gray-100);
    color: var(--bb-gray-600);
}

.bb-badge--elite {
    background: rgba(217, 139, 74, 0.12);
    color: var(--bb-amber-dark);
}

/* Was rgba(46,204,113,.1) - EMERALD, not the palette's moss. A cool-cast sweep
   cannot catch it because green is not blue-dominant, so it survived every earlier
   pass while its sibling .bb-badge--success sat on the correct moss tint: two
   badges, same meaning, two different greens. Now both share --bb-success-light,
   and the text is 4.46:1 -> 7.34:1 on bone. */
.bb-badge--active {
    background: var(--bb-success-light);
    color: var(--bb-moss-dark);
}

.bb-badge--info {
    background: rgba(69, 114, 63, 0.1);
    color: var(--bb-moss-dark);
}

.bb-badge--retired {
    /* Oxblood-soft tint + darker oxblood ink (the loud-red tint retired here too). */
    background: var(--bb-primary-light);
    color: var(--bb-primary-hover); /* #8f2e2a, AA on the light tint at 11px/700 */
}

/* Placement badge */
.bb-place-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    padding: 3px 10px;
    font-size: 12px;
    font-weight: 700;
    border-radius: 6px;
    background: var(--bb-gray-100);
    color: var(--bb-text-secondary);
}

.bb-place-1 {
    background: linear-gradient(135deg, rgba(217, 139, 74, 0.18), rgba(217, 139, 74, 0.28));
    color: var(--bb-amber-dark);
}

.bb-place-2 {
    background: var(--bb-gray-100);
    color: var(--bb-gray-500);
}

.bb-place-3 {
    background: #fff7ed;
    color: #9a3412;
}

.bb-tag {
    font-size: 0.625rem;
    font-weight: 600;
    padding: var(--bb-space-1) var(--bb-space-2);
    background: var(--bb-gray-100);
    color: var(--bb-gray-600);
    border-radius: var(--bb-radius-sm);
    text-transform: uppercase;
}

.bb-tag-success {
    background: var(--bb-success-light);
    color: var(--bb-moss-dark);
}

.bb-tag-info {
    background: rgba(178, 58, 53, 0.12);
    color: var(--bb-primary);
}

/* Level badges */
.bb-level-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 10px;
    font-weight: 600;
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* P2-14 (WCAG 1.4.3): the saturated --bb-level-* hues failed 4.5:1 text contrast on
   their own 10% tint at 13px (novice 1.95, elite 1.89, beginner 2.75, advanced 3.36;
   only intermediate passed at 10.43). Text uses a same-hue darkened value (channels
   scaled toward black, so the level color identity is preserved) that clears 4.5:1
   with margin. The tint backgrounds and the canonical --bb-level-* hue tokens are
   left untouched; only the badge text darkens. */
.bb-level-beginner  { background: rgba(138, 128, 118, 0.12); color: #5f574e; } /* 4.81:1 */
.bb-level-novice    { background: rgba(69, 114, 63, 0.1);  color: var(--bb-moss-dark); } /* 4.84:1 */
.bb-level-intermediate { background: rgba(34, 28, 24, 0.1);  color: var(--bb-level-intermediate); } /* 10.43:1 */
.bb-level-advanced  { background: rgba(168, 55, 42, 0.1);   color: var(--bb-oxblood-hover); } /* 4.80:1 */
.bb-level-elite     { background: rgba(217, 139, 74, 0.1);  color: #936415; } /* 4.80:1 */
.bb-level-elite::before { content: '\2605'; font-size: 0.875rem; }

/* --- Buttons --- */

.bb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 20px;
    font-family: var(--bb-font-sans);
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    border-radius: var(--bb-radius);
    border: none;
    cursor: pointer;
    transition: all 0.15s;
    min-height: 44px;
}

.bb-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* P2-29: buttons (Compare, Follow, Share, Load More, dropdown items) previously
   fell back to the thin UA focus ring, easily lost against the crimson/navy
   fills. Use the same 2px design-system ring as cards/tabs/pagination. */
.bb-app .bb-btn:focus-visible {
    outline: var(--bb-focus-ring-width) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset);
}

.bb-btn-primary {
    background: var(--bb-primary);
    color: white !important;
    box-shadow: 0 1px 3px rgba(178, 58, 53, 0.3);
}

.bb-btn-primary:hover:not(:disabled) {
    background: var(--bb-primary-hover);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(178, 58, 53, 0.25);
}

.bb-btn-cta {
    background: var(--bb-cta);
    color: white !important;
    box-shadow: 0 1px 3px rgba(217, 139, 74, 0.3);
}

.bb-btn-cta:hover:not(:disabled) {
    background: var(--bb-cta-hover);
    box-shadow: 0 4px 12px rgba(217, 139, 74, 0.3);
}

.bb-btn-secondary {
    background: var(--bb-surface);
    color: var(--bb-text-primary) !important;
    border: 2px solid var(--bb-border);
    box-shadow: var(--bb-shadow-sm);
}

.bb-btn-secondary:hover:not(:disabled) {
    background: var(--bb-gray-50);
    border-color: var(--bb-border-strong);
}

.bb-btn-outline {
    background: var(--bb-surface);
    color: var(--bb-text-primary) !important;
    border: 2px solid var(--bb-border);
}

.bb-btn-outline:hover:not(:disabled) {
    background: var(--bb-gray-50);
    border-color: var(--bb-border-strong);
}

.bb-btn--ghost {
    background: transparent;
    color: var(--bb-primary);
    border-color: transparent;
}

.bb-btn--ghost:hover:not(:disabled) {
    background: var(--bb-primary-light);
    color: var(--bb-primary-hover);
}

.bb-arrow-slide svg { transition: transform var(--bb-transition); }
.bb-arrow-slide:hover svg { transform: translateX(4px); }

.bb-btn-lg {
    padding: var(--bb-space-4) var(--bb-space-8);
    font-size: 1.0625rem;
    min-height: 52px;
}

.bb-btn-sm {
    padding: var(--bb-space-2) var(--bb-space-3);
    font-size: 0.8125rem;
    min-height: 36px;
}

/* bb-btn-xs appeared in markup (rival Compare, six rendered instances) with no
   rule in either stylesheet, so it silently inherited the 44px base and sat
   TALLER than bb-btn-sm - an inverted size scale. One step below sm. */
.bb-btn-xs {
    padding: var(--bb-space-1) var(--bb-space-2);
    font-size: 0.75rem;
    min-height: 32px;
}

/*
 * 36px is a fine compact control for a pointer, but the unit switchers on every
 * calculator are .bb-btn-sm, and switching units is a one-handed phone action.
 * --bb-touch-min is already declared as the plugin's floor; this is where a
 * touch-primary device actually gets it. Pointer-fine devices keep the compact
 * size, so nothing reflows on desktop.
 */
@media (hover: none) and (pointer: coarse) {
    .bb-app .bb-btn-sm,
    .bb-app .bb-btn-xs { min-height: var(--bb-touch-min); }
}

.bb-w-full { width: 100%; }

.bb-btn-loading {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}

.bb-btn-loading::after {
    content: '';
    position: absolute;
    width: 20px;
    height: 20px;
    top: 50%;
    left: 50%;
    margin-left: -10px;
    margin-top: -10px;
    border: 2px solid transparent;
    border-top-color: currentColor;
    border-radius: 50%;
    animation: bb-spin 0.8s linear infinite;
}

.bb-btn-primary.bb-btn-loading::after { border-top-color: white; }

.bb-btn-icon {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bb-gray-100);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius);
    color: var(--bb-gray-500);
    cursor: pointer;
    transition: all var(--bb-transition);
}

.bb-btn-icon:hover:not(:disabled) {
    background: var(--bb-error-light);
    border-color: var(--bb-error);
    color: var(--bb-error);
}

.bb-btn-icon:disabled { opacity: 0.3; cursor: not-allowed; }

@keyframes bb-spin { to { transform: rotate(360deg); } }

/* --- Forms --- */

.bb-form-group {
    margin-bottom: var(--bb-space-6);
    position: relative;
}

.bb-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--bb-gray-700);
    margin-bottom: var(--bb-space-2);
    letter-spacing: -0.01em;
}

.bb-input,
.bb-select,
.bb-filter-input,
select.bb-filter-select,
.bb-search-input {
    display: block;
    width: 100%;
    padding: 10px 14px;
    font-family: inherit;
    font-size: 14px;
    color: var(--bb-gray-800);
    background: var(--bb-surface);
    border: 2px solid var(--bb-border);
    border-radius: var(--bb-radius);
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
    min-height: 44px;
}

/* Search inputs need left padding for icon */
.bb-search-input {
    padding: 10px 14px 10px 40px;
}

.bb-select,
select.bb-filter-select {
    font-weight: 500;
    padding-right: 36px;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b95a5' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px;
}

/* When .bb-filter-select is a div wrapper (not a select), strip input styling */
div.bb-filter-select {
    height: auto;
    padding: 0;
    border: none;
    background: none;
    background-image: none;
    -webkit-appearance: unset;
    appearance: unset;
    cursor: default;
}

.bb-input:hover:not(:focus):not(:disabled),
.bb-select:hover:not(:focus):not(:disabled),
.bb-filter-input:hover:not(:focus):not(:disabled),
select.bb-filter-select:hover:not(:focus):not(:disabled),
.bb-search-input:hover:not(:focus):not(:disabled) {
    border-color: var(--bb-border-strong);
}

.bb-input:focus,
.bb-select:focus,
.bb-filter-input:focus,
select.bb-filter-select:focus,
.bb-search-input:focus {
    outline: none;
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
    background-color: var(--bb-surface);
}

.bb-input:disabled,
.bb-select:disabled,
.bb-filter-input:disabled,
select.bb-filter-select:disabled,
.bb-search-input:disabled {
    background-color: var(--bb-gray-100);
    color: var(--bb-gray-400);
    cursor: not-allowed;
    border-color: var(--bb-gray-200);
}

.bb-input::placeholder,
.bb-filter-input::placeholder,
.bb-search-input::placeholder { color: var(--bb-gray-400); }

.bb-input-error { border-color: var(--bb-error); }
.bb-input-error:focus { box-shadow: 0 0 0 3px rgba(143, 36, 32, 0.12); }
.bb-input-success { border-color: var(--bb-green-500); }
.bb-input-success:focus { box-shadow: 0 0 0 3px rgba(69, 114, 63, 0.12); }

.bb-error-text {
    display: flex;
    align-items: center;
    gap: var(--bb-space-1);
    font-size: 0.8125rem;
    color: var(--bb-error);
    margin-top: var(--bb-space-2);
}

.bb-help-text {
    font-size: 0.8125rem;
    color: var(--bb-gray-500);
    margin-top: var(--bb-space-2);
}

.bb-input-wrapper { position: relative; }

.bb-input-suffix {
    position: absolute;
    right: var(--bb-space-4);
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.875rem;
    color: var(--bb-gray-500);
    pointer-events: none;
}

.bb-input-wrapper .bb-input { padding-right: 60px; }

.bb-input-icon-wrapper { position: relative; }
.bb-input-icon-wrapper .bb-input { padding-left: 48px; }

.bb-input-icon {
    position: absolute;
    left: var(--bb-space-4);
    top: 50%;
    transform: translateY(-50%);
    color: var(--bb-gray-400);
    pointer-events: none;
    transition: color var(--bb-transition);
}

.bb-input-icon svg { width: 20px; height: 20px; }
.bb-input-icon-wrapper .bb-input:focus ~ .bb-input-icon { color: var(--bb-primary); }

.bb-textarea {
    display: block;
    width: 100%;
    padding: 10px 14px;
    font-family: inherit;
    font-size: 14px;
    color: var(--bb-gray-800);
    background: var(--bb-surface);
    border: 2px solid var(--bb-border);
    border-radius: var(--bb-radius);
    outline: none;
    resize: vertical;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.bb-textarea:focus {
    outline: none;
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
}

.bb-radio-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-4);
}

.bb-radio-label,
.bb-checkbox-label {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: 0.875rem;
    color: var(--bb-gray-600);
    cursor: pointer;
}

.bb-radio-label input,
.bb-checkbox-label input {
    width: 18px;
    height: 18px;
    accent-color: var(--bb-primary);
}

.bb-filter-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--bb-gray-600);
    margin-bottom: var(--bb-space-3);
}

.bb-select-sm,
.bb-input-sm {
    padding: 8px 12px;
    font-size: 13px;
    min-height: 36px;
}

.bb-form-hint {
    display: block;
    margin-top: var(--bb-space-1);
    font-size: var(--bb-fs-xs);
    color: var(--bb-gray-400);
}

/* Search bar */
.bb-search-bar {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    background: var(--bb-surface);
    border: 2px solid var(--bb-border);
    border-radius: var(--bb-radius);
    padding: var(--bb-space-2) var(--bb-space-4);
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-search-bar:focus-within {
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
}

.bb-search-bar-icon {
    color: var(--bb-text-muted);
    flex-shrink: 0;
    width: 16px;
    height: 16px;
}

.bb-search-bar .bb-search-input {
    border: none;
    padding: 0;
    min-height: auto;
    box-shadow: none;
    font-size: var(--bb-fs-sm);
}

.bb-search-bar .bb-search-input:focus { box-shadow: none; }

/* Filters */
.bb-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bb-space-2);
}

.bb-filter-btn {
    padding: 8px 16px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    color: var(--bb-text-muted);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    transition: all 0.15s;
}

.bb-filter-btn:hover {
    color: var(--bb-text-primary);
}
.bb-filter-btn.active,
.bb-filter-btn--active {
    color: var(--bb-primary);
    border-bottom-color: var(--bb-primary);
}

/* --- Tabs --- */

.bb-tabs {
    display: flex;
    gap: 2px;
    margin-bottom: 20px;
    border-bottom: 2px solid var(--bb-border);
}

.bb-tab {
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 600;
    color: var(--bb-text-muted);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
    white-space: nowrap;
}

.bb-tab:hover {
    color: var(--bb-text-primary);
}

.bb-tab.active {
    color: var(--bb-primary);
    border-bottom-color: var(--bb-primary);
}

.bb-tab:focus-visible {
    outline: 2px solid var(--bb-focus-ring-color);
    outline-offset: 2px;
}

.bb-tab-content {
    background: var(--bb-surface);
    border-radius: var(--bb-radius-lg);
    border: 1px solid var(--bb-gray-200);
    padding: var(--bb-space-6);
}

.bb-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    margin-left: var(--bb-space-2);
    font-size: 0.75rem;
    font-weight: 600;
    background: var(--bb-gray-200);
    color: var(--bb-gray-600);
    border-radius: 10px;
}

.bb-tab.active .bb-tab-count {
    background: var(--bb-primary-soft);
    color: var(--bb-primary);
}

/* --- Pagination --- */

.bb-pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 18px;
    border-top: 2px solid var(--bb-border);
    font-size: 13px;
    color: var(--bb-text-muted);
}

.bb-page-btn {
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--bb-text-secondary);
    cursor: pointer;
    background: none;
    font-family: inherit;
    transition: all 0.15s;
}

.bb-page-btn:hover {
    background: var(--bb-bg);
}

.bb-page-btn.active,
.bb-page-btn--active {
    background: var(--bb-primary);
    color: white;
}

.bb-page-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

@media (max-width: 640px) {
    .bb-pagination {
        flex-direction: column;
        gap: 12px;
        text-align: center;
    }
}

.bb-load-more { text-align: center; margin-top: var(--bb-space-8); }
.bb-load-more-btn { min-width: 160px; }

/* --- Loading & Spinner --- */

.bb-loading {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
}

.bb-loading::before {
    content: '';
    width: 16px;
    height: 16px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: bb-spin 0.6s linear infinite;
}

.bb-spinner {
    display: inline-block;
    width: 20px;
    height: 20px;
    border: 2px solid var(--bb-gray-200);
    border-top-color: var(--bb-primary);
    border-radius: 50%;
    animation: bb-spin 0.6s linear infinite;
}

.bb-loading-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--bb-space-4);
    padding: var(--bb-space-16) var(--bb-space-4);
    color: var(--bb-text-muted);
}

/* --- Empty State --- */

.bb-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--bb-space-12) var(--bb-space-6);
    /* --bb-text-muted, not --bb-gray-400. #8a8076 measured 3.79:1 on the bone
       cards these states sit in, and the brief names #6b6259 as the LIGHTEST grey
       permitted on bone - so the empty-state body copy was lighter than the stated
       floor. This block is duplicated verbatim later in the file; both copies carry
       the same value so neither can win with the old one. */
    color: var(--bb-text-muted);
}

.bb-empty-state svg { margin-bottom: var(--bb-space-4); opacity: 0.5; }

/* Empty-state headings sit at whatever level the surrounding document needs, so
   the styling cannot be tied to one tag. Compare and several nested surfaces
   correctly use h3 here; those rendered at browser-default size because only h2
   was covered. */
.bb-empty-state h2,
.bb-empty-state h3,
.bb-empty-state h4 {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
    font-weight: 600;
    color: var(--bb-gray-600);
    margin: 0 0 var(--bb-space-2) 0;
}

.bb-empty-state p { margin: 0 0 var(--bb-space-6) 0; font-size: var(--bb-fs-sm); }

.bb-empty-state-icon { color: var(--bb-gray-300); margin-bottom: var(--bb-space-4); }

/* UX state blocks - partials/state-blocks.php (bb_empty_state / bb_error_state). UX-AUDIT.md themes 1-2. */
.bb-empty-state .bb-state__icon,
.bb-error-state .bb-state__icon { margin-bottom: var(--bb-space-3); opacity: 0.55; color: var(--bb-gray-400); }
.bb-empty-state__title { font-family: var(--bb-font-heading); font-size: var(--bb-fs-lg); font-weight: 600; color: var(--bb-text-secondary); margin: 0 0 var(--bb-space-2); }
.bb-empty-state__desc { margin: 0 0 var(--bb-space-5); font-size: var(--bb-fs-sm); color: var(--bb-text-muted); max-width: 42ch; }
.bb-empty-state__cta { margin-top: var(--bb-space-1); }
.bb-error-state {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: var(--bb-space-3); padding: var(--bb-space-10) var(--bb-space-6);
    border: 1px solid var(--bb-border); border-radius: var(--bb-radius-lg); background: var(--bb-surface);
}
.bb-error-state .bb-state__icon { color: var(--bb-error); opacity: 0.85; margin-bottom: 0; }
.bb-error-state__msg { margin: 0; font-size: var(--bb-fs-sm); color: var(--bb-text-secondary); max-width: 42ch; }
.bb-error-state__retry { margin-top: var(--bb-space-1); }
.bb-error-state--sm { padding: var(--bb-space-6) var(--bb-space-4); }
/* Inline form/field validation message (calculators, forms). */
.bb-form-error { margin: var(--bb-space-3) 0 0; color: var(--bb-error); font-size: var(--bb-fs-sm); font-weight: 500; display: flex; align-items: center; gap: var(--bb-space-2); }

.bb-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-16);
    color: var(--bb-text-secondary);
    text-align: center;
}

.bb-empty-icon  { font-size: 3rem; opacity: 0.3; }
.bb-empty-title { font-size: var(--bb-fs-base); font-weight: 600; color: var(--bb-gray-600); }
.bb-empty-desc  { font-size: var(--bb-fs-sm); color: var(--bb-text-muted); max-width: 360px; }

.bb-error-banner {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-4);
    background: var(--bb-error-light);
    border: 1px solid rgba(143, 36, 32, 0.2);
    border-radius: var(--bb-radius);
    color: var(--bb-error);
    font-size: var(--bb-fs-sm);
}

/* --- Skeleton Loaders --- */

.bb-skeleton {
    background: linear-gradient(90deg, var(--bb-gray-100) 25%, var(--bb-gray-200) 50%, var(--bb-gray-100) 75%);
    background-size: 200% 100%;
    animation: bb-shimmer 1.5s infinite;
    border-radius: var(--bb-radius);
}

@keyframes bb-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.bb-skeleton-text    { height: 1em;      margin-bottom: 0.5em; border-radius: 4px; }
.bb-skeleton-text:last-child { width: 75%; }
.bb-skeleton-text-sm { height: 0.875em; }
.bb-skeleton-text-lg { height: 1.25em; }
.bb-skeleton-title   { height: 1.5em; }

.bb-skeleton-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
}

.bb-skeleton-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
}

.bb-skeleton-stat {
    height: 3em;
    border-radius: 8px;
}

.bb-skeleton-button {
    height: 44px;
    border-radius: var(--bb-radius);
}

.bb-skeleton-image {
    width: 100%;
    border-radius: var(--bb-radius-lg);
}

.bb-skeleton-row {
    display: flex;
    gap: var(--bb-space-4);
    align-items: center;
}

.bb-skeleton-circle {
    border-radius: var(--bb-radius-full);
}

.bb-skeleton-h-60  { height: 60px; }
.bb-skeleton-h-80  { height: 80px; }
.bb-skeleton-h-100 { height: 100px; }
.bb-skeleton-h-120 { height: 120px; }
.bb-skeleton-h-160 { height: 160px; }
.bb-skeleton-h-200 { height: 200px; }
.bb-skeleton-h-300 { height: 300px; }
.bb-skeleton-h-400 { height: 400px; }

/* ==========================================================================
   7. SECTION HEADERS
   ========================================================================== */

.bb-section { padding: var(--bb-space-8) 0; }

.bb-section-header {
    text-align: center;
    margin-bottom: var(--bb-space-10);
}

.bb-section-header p {
    font-size: var(--bb-fs-lg);
    color: var(--bb-gray-400);
    margin: 0;
}

.bb-section-title {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--bb-text-primary);
}

.bb-section-desc {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    margin-top: var(--bb-space-1);
}

.bb-section-link {
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-primary);
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 4px;
}

.bb-section-link:hover { color: var(--bb-primary-hover); }

/* ==========================================================================
   8. PAGE HEADERS
   ========================================================================== */

.bb-app .bb-page-header {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border-radius: var(--bb-radius-lg);
    padding: 32px clamp(18px, 4.4vw, 32px);
    margin-bottom: var(--bb-space-6);
    border-bottom: none;
    position: relative;
    overflow: hidden;
}
.bb-app .bb-page-header::before {
    content: '';
    position: absolute;
    top: -50%; right: -10%;
    width: 300px; height: 300px;
    background: radial-gradient(circle, rgba(178, 58, 53,0.1) 0%, transparent 70%);
    border-radius: 50%;
    pointer-events: none;
}
.bb-app .bb-page-header > .bb-page-title,
.bb-app .bb-page-header .bb-page-title {
    color: #ffffff !important;
    position: relative;
    z-index: 1;
}
.bb-app .bb-page-header > .bb-page-desc,
.bb-app .bb-page-header .bb-page-desc,
.bb-app .bb-page-header > .bb-page-subtitle,
.bb-app .bb-page-header .bb-page-subtitle {
    color: rgba(255,255,255,0.75) !important;
    position: relative;
    z-index: 1;
}

.bb-app .bb-page-header-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    flex-wrap: wrap;
}

.bb-app .bb-page-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    max-width: 56px;
    max-height: 56px;
    flex-shrink: 0;
    color: var(--bb-primary);
}

.bb-app .bb-page-icon svg { width: 56px; height: 56px; }

.bb-app .bb-page-header .bb-page-title {
    font-size: var(--bb-fs-2xl);
    font-weight: 700;
    margin: 0;
    line-height: 1.2;
}

.bb-app .bb-page-header .bb-page-subtitle {
    font-size: var(--bb-fs-sm);
    margin: var(--bb-space-1) 0 0;
}

/* Dark page header */
/* P3-12: background lives on the single route-wide source (section near L11936). */
.bb-app .bb-page-header.bb-page-header-dark,
.bb-app .bb-page-header.bb-page-header--dark {
    border-radius: var(--bb-radius-lg);
    padding: 28px clamp(18px, 4.4vw, 32px);
    margin-bottom: 24px;
    border-bottom: none;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 24px;
}

.bb-app .bb-page-header.bb-page-header-dark::before,
.bb-app .bb-page-header.bb-page-header--dark::before {
    content: '';
    position: absolute;
    top: -50%;
    right: -10%;
    width: 300px;
    height: 300px;
    background: radial-gradient(circle, rgba(178, 58, 53, 0.1) 0%, transparent 70%);
    border-radius: 50%;
    pointer-events: none;
}

.bb-app .bb-page-header-dark .bb-hero-text,
.bb-app .bb-page-header--dark .bb-hero-text {
    flex: 1;
    min-width: 0;
    position: relative;
    z-index: 1;
}

.bb-app .bb-page-header.bb-page-header-dark .bb-page-title,
.bb-app .bb-page-header.bb-page-header--dark .bb-page-title {
    color: #ffffff;
    position: relative;
    z-index: 1;
}

.bb-app .bb-page-header.bb-page-header-dark .bb-page-subtitle,
.bb-app .bb-page-header.bb-page-header--dark .bb-page-subtitle {
    color: rgba(255, 255, 255, 0.75);
    position: relative;
    z-index: 1;
}

.bb-app .bb-page-header-dark > .bb-page-title,
.bb-app .bb-page-header--dark > .bb-page-title  { width: 100%; }
.bb-app .bb-page-header-dark > .bb-page-subtitle,
.bb-app .bb-page-header--dark > .bb-page-subtitle { width: 100%; }

.bb-app .bb-page-header-dark .bb-hero-icon,
.bb-app .bb-page-header--dark .bb-hero-icon {
    width: 160px;
    height: 160px;
    flex-shrink: 0;
    opacity: 0.85;
    position: relative;
    z-index: 1;
    border-radius: var(--bb-radius-lg);
    object-fit: contain;
}

@media (max-width: 640px) {
    .bb-app .bb-page-header-dark .bb-hero-icon,
    .bb-app .bb-page-header--dark .bb-hero-icon { display: none; }
    .bb-app .bb-page-header { padding: 20px 16px; border-radius: var(--bb-radius-md); }
    .bb-app .bb-page-header .bb-page-title { font-size: var(--bb-fs-page-title); }
    .bb-app .bb-page-header .bb-page-desc,
    .bb-app .bb-page-header .bb-page-subtitle { font-size: 0.85rem; }
}

/* ==========================================================================
   9. HERO (Hub)
   ========================================================================== */

.bb-hero {
    /* P3-12: background lives on the single route-wide source (section near L11936). */
    /* 28px on all four sides plus the compacted type; the block was taller than the
       viewport on a laptop and everything below it started off-screen. */
    padding: 20px 24px;
    position: relative;
    /*
     * overflow was hidden, and it CLIPPED THE SEARCH DROPDOWN. No z-index escapes an
     * ancestor's overflow:hidden, so the hero combobox opened, extended past the hero's
     * bottom edge and was cut off mid-list - visible as a stray border under the stat
     * row with the Olympia section slicing through it.
     *
     * It was only ever there to contain the two decorative radial gradients below, which
     * were positioned to bleed (top:-50%, bottom:-30%). Both already fade to transparent
     * at 70% of their radius, so they do not need to bleed to read as soft glows: they
     * are inset within the box now and clip themselves. The hero keeps its rounded
     * corners because the gradients no longer reach them.
     */
    overflow: visible;
    border-radius: var(--bb-radius-lg);
    margin-bottom: 32px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 40px;
    flex-direction: column;
}

/*
 * Both glows are inset inside the hero now rather than bleeding past it, because the
 * hero no longer clips (see overflow above - it was cutting the search dropdown in
 * half). The gradients are transparent from 70% of their radius outward, so their
 * edges were already invisible; containing them changes where the glow sits, not
 * whether it has a visible boundary. max-width keeps them inside a narrow hero too.
 */
.bb-hero::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: min(600px, 70%);
    height: 600px;
    max-height: 100%;
    background: radial-gradient(circle, rgba(178, 58, 53, 0.15) 0%, transparent 70%);
    pointer-events: none;
    border-radius: 50%;
    z-index: 0;
}

.bb-hero::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    width: min(400px, 55%);
    height: 400px;
    max-height: 100%;
    background: radial-gradient(circle, rgba(69, 114, 63, 0.1) 0%, transparent 70%);
    pointer-events: none;
    border-radius: 50%;
    z-index: 0;
}

.bb-hero-inner {
    max-width: var(--bb-container);
    margin: 0 auto;
    padding: 0 var(--bb-space-4);
    position: relative;
    z-index: 1;
}

.bb-hero-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    /* On-dark hero kicker: oxblood cannot clear AA on the near-black hero, so
       this reads as a quiet light-warm label (matches the #fffdf8 hero text). */
    color: rgba(255, 253, 248, 0.72);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-bottom: var(--bb-space-3);
}

.bb-heading-hero {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-page-title);
    font-weight: 800;
    color: white;
    letter-spacing: -0.03em;
    line-height: 1.15;
    margin-bottom: var(--bb-space-3);
}

.bb-heading-hero span { color: var(--bb-primary); }

/*
 * Compacted with the headline. 20px at 1.7 leading over a 550px measure is book
 * typography under a display headline, and it was adding roughly a third of the
 * hero's height on its own. 18px at 1.6 keeps the line length comfortable - still
 * well inside the 65-character target at this measure - and gives back a line.
 */
.bb-hero-description {
    font-size: var(--bb-fs-md);
    color: rgba(255, 255, 255, 0.8);
    max-width: 550px;
    line-height: 1.6;
    margin-bottom: var(--bb-space-5);
}

.bb-stats-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-8);
    background: rgba(255, 255, 255, 0.1);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    margin-top: 24px;
    margin-bottom: 0;
    padding: 10px;
    border: 1px solid rgba(255, 255, 255, 0.1);
}

.bb-stat {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-1);
    flex: 1;
    padding: 16px 20px;
    border-right: 1px solid rgba(255, 255, 255, 0.08);
}

.bb-stat:last-child { border-right: none; }

/*
 * The number has to fit its column, and the longest one is data-driven.
 *
 * At the flat --bb-fs-3xl (36px) the athlete count "110,404" needs 126px, while three
 * stats sharing a row give each cell 86px at 320px wide, 100px at 360 and 110px at
 * 390. So the headline figure on the athletes directory was cut off on every phone
 * width, while "14" and "1934" beside it fitted and looked fine. The count only grows,
 * so a fixed size cannot be right here.
 *
 * The clamp scales the figure down only below roughly 554px, where 6.5vw drops under
 * 36px, so nothing changes on tablet or desktop. The 22px floor is far above the 11px
 * legibility floor and fits "110,404" in 77px, inside even the 320px cell.
 */
.bb-stat-number {
    font-family: var(--bb-font-heading);
    font-size: clamp(22px, 6.5vw, var(--bb-fs-3xl));
    font-weight: 700;
    color: var(--bb-text-primary);
    line-height: 1;
    letter-spacing: -0.02em;
}

.bb-stat-number.highlight { color: var(--bb-primary); }

.bb-stat-label {
    font-size: var(--bb-fs-sm);
    font-weight: 500;
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* White text for stats inside dark containers (hero only, NOT profile stats) */
.bb-hero .bb-stat-number,
.bb-hero > .bb-stats-row .bb-stat-number,
.bb-page-header-dark .bb-stat-number,
.bb-page-header--dark .bb-stat-number { color: white; }
.bb-hero .bb-stat-label,
.bb-hero > .bb-stats-row .bb-stat-label,
.bb-page-header-dark .bb-stat-label,
.bb-page-header--dark .bb-stat-label { color: rgba(255, 255, 255, 0.6); }

/* W3: on the two-column hub hero the stats row lives in the ~600px copy column
   (it is nested in .bb-hero-content, so target it as a descendant, not a direct
   child). The shared 32px gap pushed the 4th stat ("Years of History") past the
   edge and `overflow:hidden` clipped it. Size each stat to its own content
   (so the wide "109,000+" never gets squeezed into its neighbour by an equal
   flex-basis), tighten the inter-stat padding, let the row wrap rather than
   clip, and keep the existing divider borders for separation. Hero only. */
.bb-hero .bb-stats-row {
    flex-wrap: wrap;
    gap: 0;
    overflow: visible;
}
.bb-hero .bb-stats-row .bb-stat {
    flex: 1 1 auto;
    min-width: 0;
    padding: 14px 18px;
}

@media (max-width: 640px) {
    .bb-hero { padding: 28px 0 24px; }
    .bb-heading-hero { font-size: var(--bb-fs-page-title); }
    .bb-hero-description { font-size: var(--bb-fs-sm); }
    .bb-hero::before { width: 300px; height: 300px; }
    .bb-hero::after { display: none; }
    .bb-stats-row { flex-wrap: wrap; }
    .bb-stat { min-width: 50%; border-right: none; border-bottom: 1px solid rgba(255,255,255,0.08); }
    .bb-stat:nth-child(odd) { border-right: 1px solid rgba(255,255,255,0.08); }
}

/* --------------------------------------------------------------------------
   HUB HERO: champions board (live "Most Olympia Titles" leaderboard)
   Replaces the old decorative fake-data radar. Two-column on desktop
   (content + board), stacked on mobile. `.bb-hero-eyebrow--strong` is the
   demoted descriptive line (was the generic h1); the h1 is now "Know Your
   Champions" at full contrast.
   -------------------------------------------------------------------------- */
.bb-hero-eyebrow--strong {
    color: rgba(255, 255, 255, 0.66);
    font-weight: 700;
}

/* Two-column hero once there is room for the board beside the copy. */
@media (min-width: 1024px) {
    .bb-hero {
        flex-direction: row;
        align-items: stretch;
        gap: var(--bb-space-8);
    }
    /*
     * The hero is a single column now. The 56/44 split and the champions-board rule
     * beside it existed to seat the "Most Olympia Titles" leaderboard, which is gone:
     * it duplicated the GOAT section further down the same page. Left as a 56% column
     * the content kept only 600px of a 1144px hero, wasting 487px on the right and
     * wrapping the h1 onto three lines.
     */
    .bb-hero > .bb-hero-content { flex: 1 1 auto; }
}

/* ==========================================================================
   10. ATHLETE CARDS
   ========================================================================== */

.bb-athlete-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    transition: transform var(--bb-transition), border-color var(--bb-transition), box-shadow var(--bb-transition);
    cursor: pointer;
    display: flex;
    flex-direction: column;
}

.bb-athlete-card:hover {
    transform: translateY(-2px);
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}

.bb-athlete-card-img {
    width: 100%;
    aspect-ratio: 3/4;
    object-fit: cover;
    background: var(--bb-gray-100);
    flex-shrink: 0;
}

.bb-athlete-card-img-placeholder {
    width: 100%;
    aspect-ratio: 3/4;
    background: var(--bb-gray-100);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bb-text-muted);
    font-size: 3rem;
    flex-shrink: 0;
}

.bb-athlete-card-body {
    padding: var(--bb-space-4);
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
}

.bb-athlete-card-name {
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
    line-height: 1.3;
}

.bb-athlete-card-division {
    font-size: var(--bb-fs-xs);
    color: var(--bb-primary);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.bb-athlete-card-meta {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: auto;
}

.bb-athlete-card-wins {
    display: flex;
    align-items: center;
    gap: 4px;
    font-weight: 600;
    color: var(--bb-accent);
}

/* Athlete Profile */
.bb-profile-header {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border-radius: var(--bb-radius-lg);
    padding: 28px clamp(18px, 4.4vw, 32px);
    margin-bottom: 24px;
    position: relative;
    /* The hero must not clip its own children: the share dropdown (246px) fits
       neither below (183px) nor above (168px) the trigger inside this box, so a
       blanket overflow:hidden silently cut two menu items off. The two things
       that genuinely need clipping - the corner ribbon and the glow - now
       contain themselves. */
    overflow: visible;
}

.bb-profile-header::before {
    content: '';
    position: absolute;
    inset: 0;
    /* Was a 300px circle at top:-50%/right:-10% that relied on the parent to
       clip it. Same glow, painted as a contained gradient. */
    background: radial-gradient( circle 150px at calc(100% - 21px) -51px, rgba(178, 58, 53, 0.1) 0%, transparent 70% );
    border-radius: inherit;
    pointer-events: none;
}

/* Clipping layer for corner decoration only. Matches the header box exactly, so
   the ribbon's offsets render identically to when the header clipped it. */
.bb-profile-header__clip {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: inherit;
    pointer-events: none;
    z-index: 2;
}

.bb-profile-inner {
    display: flex;
    align-items: flex-start;
    gap: var(--bb-space-6);
    flex-wrap: wrap;
    position: relative;
    z-index: 1;
}

.bb-profile-avatar {
    width: 120px;
    height: 120px;
    border-radius: var(--bb-radius-lg);
    object-fit: cover;
    background: rgba(255, 255, 255, 0.1);
    border: 2px solid rgba(255, 255, 255, 0.2);
    flex-shrink: 0;
}

.bb-profile-avatar-placeholder {
    width: 120px;
    height: 120px;
    border-radius: var(--bb-radius-lg);
    background: rgba(255, 255, 255, 0.1);
    border: 2px solid rgba(255, 255, 255, 0.15);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
    flex-shrink: 0;
}

.bb-profile-info {
    flex: 1;
    min-width: 200px;
}

.bb-profile-name {
    /* Display tier: the athlete name is the page headline. */
    font-size: var(--bb-fs-page-title);
    line-height: 1.05;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: white;
    margin-bottom: var(--bb-space-2);
}
.bb-app .bb-profile-header h1.bb-profile-name,
.bb-app .bb-profile-header .bb-profile-name {
    color: #ffffff !important;
}

.bb-profile-division {
    font-size: var(--bb-fs-sm);
    /* On the navy profile hero: light-warm label (oxblood would be illegible). */
    color: rgba(255, 253, 248, 0.72);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: var(--bb-space-4);
}

.bb-profile-stats {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-6);
}

.bb-profile-stat { display: flex; flex-direction: column; gap: 3px; }

.bb-profile-stat-value {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-text-primary);
}
.bb-page-header-dark .bb-profile-stat-value,
.bb-page-header--dark .bb-profile-stat-value { color: white; }

.bb-profile-stat-label {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* ==========================================================================
   11. CONTEST CARDS
   ========================================================================== */

.bb-contest-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-6);
    transition: all 0.2s ease;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
}

.bb-contest-card:hover {
    transform: translateY(-2px);
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}

.bb-contest-card-title {
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
    line-height: 1.3;
}

.bb-contest-card-date {
    font-size: var(--bb-fs-xs);
    color: var(--bb-primary);
    font-weight: 600;
}

.bb-contest-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: auto;
}

.bb-contest-card-location {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* ==========================================================================
   12. HUB LAYOUT
   ========================================================================== */

.bb-hub-sections { display: flex; flex-direction: column; }

.bb-hub-section {
    padding: var(--bb-space-8) 0;
    border-bottom: 1px solid var(--bb-gray-200);
}

.bb-hub-section:last-child { border-bottom: none; }

.bb-feature-grid {
    display: grid;
    gap: var(--bb-space-4);
    grid-template-columns: repeat(1, minmax(0, 1fr));
}

@media (min-width: 600px)  { .bb-feature-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .bb-feature-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.bb-feature-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
    cursor: pointer;
    text-decoration: none !important;
}

.bb-feature-card:hover {
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}

.bb-feature-icon {
    width: 44px;
    height: 44px;
    background: var(--bb-primary-light);
    border-radius: var(--bb-radius);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
}

.bb-feature-icon svg { color: var(--bb-primary); }

.bb-feature-title {
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
}

.bb-feature-desc {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    line-height: 1.55;
}

/* ==========================================================================
   13. OLYMPIA TIMELINE
   ========================================================================== */

.bb-olympia-year {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    padding: var(--bb-space-4) 0;
    border-bottom: 1px solid var(--bb-gray-200);
}

.bb-olympia-year:last-child { border-bottom: none; }

.bb-olympia-year-num {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-primary);
    min-width: 80px;
}

.bb-olympia-winner {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
}

.bb-olympia-trophy { font-size: 1.25rem; }

/* ==========================================================================
   14. FAQ
   ========================================================================== */

.bb-faq-section {
    text-align: left;
}

.bb-faq-list {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
}

.bb-faq-item {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    margin-bottom: var(--bb-space-3);
}

.bb-faq-item:last-child { margin-bottom: 0; }

.bb-faq-question {
    display: flex;
    width: 100%;
    justify-content: space-between;
    align-items: center;
    padding: var(--bb-space-4) var(--bb-space-5);
    background: transparent;
    border: none;
    font-family: var(--bb-font-sans);
    font-size: var(--bb-fs-base);
    font-weight: 600;
    color: var(--bb-gray-800);
    text-align: left;
    cursor: pointer;
    /* Reassert wrapping against theme-level nowrap button rules. */
    white-space: normal;
    transition: background-color 0.15s ease;
}

.bb-faq-question:hover {
    background: var(--bb-gray-50);
    color: var(--bb-primary-hover);
}

.bb-faq-question[aria-expanded="true"] {
    background: var(--bb-primary);
    color: white;
}

.bb-faq-question svg {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    transition: transform var(--bb-transition);
}

.bb-faq-question[aria-expanded="true"] svg { transform: rotate(180deg); }

.bb-faq-answer {
    padding: var(--bb-space-4) var(--bb-space-5);
    color: var(--bb-gray-600);
    /* Declared, not inherited. Without this the answer picked up whatever the
       host theme passed down (15px against the question's 16px), which read as
       the question being oversized rather than the answer being unstyled. */
    font-size: var(--bb-fs-15);
    line-height: 1.7;
}

/* In-page jump to the judging explainer. This was a bare <p><a> directly under
   the event hero, so it rendered as a small bold orphan line with nothing
   around it and read as a broken heading. Give it the affordance of a link
   people are meant to click. */
.bb-event-jumplink {
    margin: var(--bb-space-4) 0 var(--bb-space-6);
}

.bb-event-jumplink a {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    padding: var(--bb-space-2) var(--bb-space-4);
    min-height: 44px;
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    background: var(--bb-surface);
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    text-decoration: none;
}

.bb-event-jumplink a::before {
    content: "?";
    display: inline-grid;
    place-items: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--bb-gray-100);
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
}

.bb-event-jumplink a:hover,
.bb-event-jumplink a:focus-visible {
    border-color: var(--bb-primary);
    color: var(--bb-primary-hover);
}

/* Division rule Q&A: one tinted section, questions a clear step below the
   section heading and a clear step above the answer. */
.bb-rule-faq__list {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-5);
    margin-top: var(--bb-space-4);
}

.bb-rule-faq__q {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-md);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin: 0 0 var(--bb-space-1-5) 0;
    line-height: 1.35;
}

.bb-rule-faq__a {
    margin: 0;
    font-size: var(--bb-fs-15);
    line-height: 1.7;
    color: var(--bb-gray-600);
    max-width: 72ch;
}

.bb-faq-answer p { margin: 0; }
.bb-faq-answer p + p { margin-top: var(--bb-space-3); }

/* ==========================================================================
   15. RELATED SECTION
   ========================================================================== */

.bb-related-section { margin-top: var(--bb-space-12); }

.bb-related-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--bb-space-4);
}

@media (min-width: 640px)  { .bb-related-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .bb-related-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 400px)  { .bb-related-grid { grid-template-columns: 1fr; } }

.bb-related-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--bb-space-5);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    text-align: center;
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-related-card:hover {
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}

.bb-related-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    background: var(--bb-primary-light);
    border-radius: var(--bb-radius-lg);
    margin-bottom: var(--bb-space-3);
}

.bb-related-icon svg {
    width: 24px;
    height: 24px;
    color: var(--bb-primary);
}

.bb-related-name {
    font-weight: 600;
    color: var(--bb-text-primary);
    margin-bottom: var(--bb-space-1);
}

.bb-related-desc { font-size: 0.75rem; color: var(--bb-text-muted); }

/* Cross CTA */
.bb-cross-cta {
    background: linear-gradient(135deg, var(--bb-navy) 0%, var(--bb-navy-mid) 100%);
    border-radius: var(--bb-radius-xl);
    padding: 48px clamp(18px, 4.4vw, 32px);
    margin: 48px 0;
    text-align: center;
}

.bb-cross-cta-content h3 {
    font-size: 1.5rem;
    font-weight: 700;
    color: white;
    margin-bottom: 12px;
}

.bb-cross-cta-content p {
    font-size: 1rem;
    color: var(--bb-gray-300);
    margin-bottom: 24px;
    max-width: 500px;
    margin-left: auto;
    margin-right: auto;
}

@media (max-width: 640px) {
    .bb-cross-cta { padding: 32px 20px; margin: 32px 0; }
    .bb-cross-cta-content h3 { font-size: 1.25rem; }
}

/* See also */
.bb-see-also {
    margin-top: 48px;
    padding-top: 32px;
    border-top: 1px solid var(--bb-gray-200);
}

.bb-see-also-title {
    font-family: var(--bb-font-heading);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--bb-gray-800);
    margin: 0 0 16px;
}

.bb-see-also-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 0 0 16px;
}

.bb-see-also-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius);
    font-size: 0.875rem;
    color: var(--bb-gray-700);
    text-decoration: none;
    transition: all 0.15s ease;
}

.bb-see-also-link:hover {
    background: var(--bb-primary-light);
    border-color: var(--bb-primary-soft);
    color: var(--bb-primary-hover);
}

/* ==========================================================================
   16. FOOTER
   ========================================================================== */

.bb-footer {
    background: var(--bb-navy);
    padding: 16px 0;
    margin-top: 48px;
    font-size: 13px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.bb-footer-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.bb-app .bb-footer .bb-footer-brand {
    font-weight: 800;
    font-size: 15px;
    color: rgba(255, 255, 255, 0.6);
    text-decoration: none;
    letter-spacing: -0.03em;
    transition: color var(--bb-transition);
    /* WCAG 2.2 target size: measured 241x23 at 390px, one pixel short of the 24px floor. */
    min-height: 24px;
}

.bb-app .bb-footer .bb-footer-brand:hover { color: rgba(255, 255, 255, 0.9); }
.bb-app .bb-footer .bb-brand-accent { color: var(--bb-accent-on-dark); }

.bb-footer-links {
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
}

.bb-app .bb-footer .bb-footer-links a {
    color: rgba(255, 255, 255, 0.5);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    transition: color var(--bb-transition);
    /*
     * WCAG 2.2 target size. These 13 links measured 20px tall on every route, since
     * they are display:block with no padding and a 19.5px line-height, so the whole
     * plugin footer failed the 24px floor everywhere. Padding rather than min-height
     * keeps the text vertically centred in the taller box.
     */
    display: block;
    padding-block: 3px;
    min-width: 24px;
}

.bb-app .bb-footer .bb-footer-links a:hover { color: rgba(255, 255, 255, 0.9); }

@media (max-width: 640px) {
    .bb-footer-inner { flex-direction: column; text-align: center; gap: 10px; }
    .bb-footer-links { justify-content: center; gap: 14px; }
}

/* Breadcrumbs */
.bb-app .bb-breadcrumbs {
    background: transparent;
    padding: 0 0 12px;
    font-size: 13px;
    margin-bottom: 4px;
}

.bb-app .bb-breadcrumb-list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.bb-app .bb-breadcrumb-item {
    display: flex;
    align-items: center;
    gap: 4px;
    color: rgba(255, 255, 255, 0.5);
    font-size: 12px;
}

.bb-app .bb-breadcrumb-item a {
    color: rgba(255, 255, 255, 0.65);
    text-decoration: none;
    transition: color 0.15s;
}

.bb-app .bb-breadcrumb-item a:hover { color: rgba(255, 255, 255, 0.95); }

.bb-app .bb-breadcrumb-sep {
    color: rgba(255, 255, 255, 0.3);
    font-size: 14px;
    line-height: 1;
}

.bb-app .bb-breadcrumb-current span {
    color: rgba(255, 255, 255, 0.85);
    font-weight: 500;
}

.bb-app .bb-breadcrumbs--light {
    margin: 0 0 14px;
    padding: 0;
}

.bb-app .bb-breadcrumbs--light .bb-breadcrumb-item {
    color: var(--bb-text-muted);
}

.bb-app .bb-breadcrumbs--light .bb-breadcrumb-item a {
    color: var(--bb-primary, #b23a35);
}

.bb-app .bb-breadcrumbs--light .bb-breadcrumb-item a:hover {
    color: var(--bb-primary-hover, #8f2d2a);
}

.bb-app .bb-breadcrumbs--light .bb-breadcrumb-sep {
    color: var(--bb-gray-400);
}

.bb-app .bb-breadcrumbs--light .bb-breadcrumb-current span {
    color: var(--bb-text-secondary);
}

/* ==========================================================================
   17. TOAST NOTIFICATIONS
   ========================================================================== */

.bb-toast {
    position: fixed;
    bottom: 24px;
    right: 24px;
    padding: 12px 20px;
    border-radius: var(--bb-radius-lg);
    font-size: 0.875rem;
    font-weight: 500;
    color: #fff;
    background: var(--bb-navy);
    z-index: 10000;
    opacity: 0;
    transform: translateY(12px);
    animation: bbToastIn 0.25s ease forwards;
    max-width: 360px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    pointer-events: none;
}

.bb-toast--success { background: var(--bb-success); }
.bb-toast--error   { background: var(--bb-error); }
.bb-toast--info    { background: var(--bb-navy); }
.bb-toast--out     { animation: bbToastOut 0.2s ease forwards; }

@keyframes bbToastIn  { to { opacity: 1; transform: translateY(0); } }
@keyframes bbToastOut { to { opacity: 0; transform: translateY(12px); } }

/* Toast container variant */
.bb-toast-container {
    position: fixed;
    bottom: var(--bb-space-6);
    right: var(--bb-space-6);
    z-index: 10000;
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
    pointer-events: none;
}

.bb-toast-container .bb-toast {
    position: static;
    pointer-events: all;
    animation: bbToastIn 0.25s ease forwards;
    max-width: 380px;
}

/* ==========================================================================
   18. ICONS & INLINE ELEMENTS
   ========================================================================== */

.bb-app .bb-icon {
    display: inline-block;
    vertical-align: middle;
    flex-shrink: 0;
}

.bb-app .bb-inline-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    vertical-align: middle;
    flex-shrink: 0;
}

.bb-app .bb-inline-icon svg { width: 100%; height: 100%; }

/* ==========================================================================
   19. DIVIDER
   ========================================================================== */

.bb-divider {
    border: none;
    border-top: 1px solid var(--bb-border);
    margin: var(--bb-space-6) 0;
}

/* ==========================================================================
   20. UTILITIES
   ========================================================================== */

.bb-text-center  { text-align: center; }
.bb-text-left    { text-align: left; }
.bb-text-right   { text-align: right; }
.bb-capitalize   { text-transform: capitalize; }
.bb-uppercase    { text-transform: uppercase; }
.bb-font-bold    { font-weight: 700; }
.bb-font-semibold { font-weight: 600; }
.bb-font-medium  { font-weight: 500; }

.bb-text-xs   { font-size: 0.75rem; }
.bb-text-sm   { font-size: 0.875rem; }
.bb-text-base { font-size: 1rem; }
.bb-text-lg   { font-size: 1.125rem; }
.bb-text-xl   { font-size: 1.25rem; }
.bb-text-2xl  { font-size: 1.5rem; }
.bb-text-3xl  { font-size: 1.875rem; }

.bb-text-primary   { color: var(--bb-text-primary); }
.bb-text-secondary { color: var(--bb-text-secondary); }
.bb-text-muted     { color: var(--bb-text-muted); }
.bb-text-accent    { color: var(--bb-primary); }

.bb-mt-2  { margin-top: var(--bb-space-2); }
.bb-mt-4  { margin-top: var(--bb-space-4); }
.bb-mt-6  { margin-top: var(--bb-space-6); }
.bb-mt-8  { margin-top: var(--bb-space-8); }
.bb-mt-12 { margin-top: var(--bb-space-12); }
.bb-mb-2  { margin-bottom: var(--bb-space-2); }
.bb-mb-3  { margin-bottom: var(--bb-space-3); }
.bb-mb-4  { margin-bottom: var(--bb-space-4); }
.bb-mb-6  { margin-bottom: var(--bb-space-6); }
.bb-mb-8  { margin-bottom: var(--bb-space-8); }
.bb-ml-2  { margin-left: var(--bb-space-2); }
.bb-ml-4  { margin-left: var(--bb-space-4); }

.bb-py-4  { padding-top: var(--bb-space-4);  padding-bottom: var(--bb-space-4); }
.bb-py-8  { padding-top: var(--bb-space-8);  padding-bottom: var(--bb-space-8); }
.bb-py-12 { padding-top: var(--bb-space-12); padding-bottom: var(--bb-space-12); }

.bb-hidden          { display: none; }
.bb-block           { display: block; }
.bb-flex            { display: flex; }
.bb-grid-util       { display: grid; }
.bb-items-center    { align-items: center; }
.bb-justify-center  { justify-content: center; }
.bb-justify-between { justify-content: space-between; }
.bb-gap-2           { gap: var(--bb-space-2); }
.bb-gap-3           { gap: var(--bb-space-3); }
.bb-gap-4           { gap: var(--bb-space-4); }
.bb-gap-6           { gap: var(--bb-space-6); }
.bb-w-full          { width: 100%; }
.bb-flex-col        { flex-direction: column; }
.bb-flex-wrap       { flex-wrap: wrap; }

/* ds-refactor 2026-06-20: utilities added to absorb the template inline-style
   migration. Token-driven where a token exists; a few primitives (circle,
   overflow) have no token by nature. See DESIGN-SYSTEM.md. */
.bb-inline-flex     { display: inline-flex; }
.bb-relative        { position: relative; }
.bb-items-start     { align-items: flex-start; }
.bb-items-end       { align-items: flex-end; }
.bb-items-baseline  { align-items: baseline; }
.bb-justify-end     { justify-content: flex-end; }
.bb-justify-start   { justify-content: flex-start; }
.bb-justify-around  { justify-content: space-around; }
.bb-flex-1          { flex: 1; }
.bb-shrink-0        { flex-shrink: 0; }
.bb-gap-1           { gap: var(--bb-space-1); }
.bb-gap-5           { gap: var(--bb-space-5); }
.bb-font-extrabold  { font-weight: 800; }
.bb-m-0             { margin: 0; }
.bb-mx-auto         { margin-left: auto; margin-right: auto; }
.bb-mt-1            { margin-top: var(--bb-space-1); }
.bb-mt-3            { margin-top: var(--bb-space-3); }
.bb-mb-1            { margin-bottom: var(--bb-space-1); }
.bb-mb-5            { margin-bottom: var(--bb-space-5); }
.bb-mr-1            { margin-right: var(--bb-space-1); }
.bb-mr-2            { margin-right: var(--bb-space-2); }
.bb-p-2             { padding: var(--bb-space-2); }
.bb-p-3             { padding: var(--bb-space-3); }
.bb-p-4             { padding: var(--bb-space-4); }
.bb-p-5             { padding: var(--bb-space-5); }
.bb-p-6             { padding: var(--bb-space-6); }
.bb-overflow-x-auto { overflow-x: auto; }
.bb-rounded-circle  { border-radius: 50%; }

.bb-touch-target { min-height: var(--bb-touch-min); min-width: var(--bb-touch-min); }
.bb-no-select    { -webkit-user-select: none; user-select: none; }

.bb-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}

/* ==========================================================================
   21. RESPONSIVE HELPERS
   ========================================================================== */

@media (max-width: 640px) {
    .bb-hide-mobile { display: none !important; }
}

@media (min-width: 641px) {
    .bb-hide-desktop { display: none !important; }
}

/* ==========================================================================
   21b. ANIMATIONS
   ========================================================================== */

/* Page fade-in */
@keyframes bb-fade-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.bb-fade-in {
    animation: bb-fade-in 0.3s ease-out both;
}

/* Staggered fade-in for lists/grids (apply bb-stagger-item class to children) */
.bb-stagger-item {
    opacity: 0;
    animation: bb-fade-in 0.3s ease-out both;
}
.bb-stagger-item:nth-child(1)  { animation-delay: 0ms; }
.bb-stagger-item:nth-child(2)  { animation-delay: 60ms; }
.bb-stagger-item:nth-child(3)  { animation-delay: 120ms; }
.bb-stagger-item:nth-child(4)  { animation-delay: 180ms; }
.bb-stagger-item:nth-child(5)  { animation-delay: 240ms; }
.bb-stagger-item:nth-child(6)  { animation-delay: 300ms; }
.bb-stagger-item:nth-child(7)  { animation-delay: 360ms; }
.bb-stagger-item:nth-child(8)  { animation-delay: 420ms; }
.bb-stagger-item:nth-child(n+9) { animation-delay: 480ms; }

/* Slide-down for dropdowns/menus */
@keyframes bb-slide-down {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.bb-slide-down {
    animation: bb-slide-down 0.2s ease-out both;
}

/* Tab content transition */
.bb-tab-content {
    animation: bb-fade-in 0.2s ease-out;
}

/* Search autocomplete dropdown animation */
.bb-autocomplete-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 50;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
    box-shadow: var(--bb-shadow-lg);
    margin-top: 4px;
    max-height: 320px;
    overflow-y: auto;
    animation: bb-slide-down 0.15s ease-out;
}

.bb-autocomplete-item {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-3) var(--bb-space-4);
    cursor: pointer;
    transition: background var(--bb-transition);
    font-size: var(--bb-fs-sm);
}

.bb-autocomplete-item:hover,
.bb-autocomplete-item--active {
    background: var(--bb-gray-50);
}

.bb-autocomplete-item--active {
    color: var(--bb-primary);
    font-weight: 600;
}

/* ==========================================================================
   22. PRINT
   ========================================================================== */

@media print {
    .bb-nav,
    .bb-footer,
    .bb-toast,
    .bb-toast-container { display: none !important; }
}

/* ==========================================================================
   23. SHARED MICRO-COMPONENTS (used across many pages)
   ========================================================================== */

/* Back link */
.bb-back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-primary);
    margin-bottom: var(--bb-space-4);
}
.bb-back-link:hover { color: var(--bb-primary-hover); }

.bb-back-nav { margin-bottom: var(--bb-space-4); }

/* Separator dot */
.bb-sep { margin: 0 6px; opacity: 0.5; }

/* Link utility */
.bb-link { color: inherit; font-weight: 500; }
.bb-link:hover { color: var(--bb-primary-hover); }

/* Live region (screen-reader announcements) */
.bb-live-region {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
}

/* Loading skeleton container */
.bb-loading-skeleton { padding: 20px; }

/* Loading overlay */
.bb-loading-overlay {
    position: absolute;
    inset: 0;
    background: rgba(255,255,255,0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
    border-radius: var(--bb-radius-lg);
}

/* Spin animation (keyframe already defined, this is the utility class) */
.bb-spin { animation: bb-spin 0.6s linear infinite; }

/* Additional skeleton sizes */
.bb-skeleton-h-20  { height: 20px; }
.bb-skeleton-h-24  { height: 24px; }
.bb-skeleton-h-40  { height: 40px; }
.bb-skeleton-h-500 { height: 500px; }
.bb-skeleton-w-160 { width: 160px; }
.bb-skeleton-w-200 { width: 200px; }
.bb-skeleton-w-300 { width: 300px; }

.bb-skeleton--line   { border-radius: 4px; }
.bb-skeleton--sm     { max-width: 120px; }
.bb-skeleton--md     { max-width: 200px; }
.bb-skeleton--lg     { max-width: 300px; }
.bb-skeleton--xl     { max-width: 400px; }
.bb-skeleton--full   { width: 100%; }
.bb-skeleton--title  { height: 1.5em; max-width: 280px; border-radius: 4px; }
.bb-skeleton--icon   { width: 44px; height: 44px; border-radius: var(--bb-radius); }
.bb-skeleton--avatar { width: 48px; height: 48px; border-radius: 50%; }
.bb-skeleton--avatar-lg { width: 120px; height: 120px; border-radius: 50%; }
.bb-skeleton--flag   { width: 24px; height: 18px; border-radius: 2px; }
.bb-skeleton--row {
    height: 48px;
    border-radius: var(--bb-radius);
    margin-bottom: var(--bb-space-2);
}

.bb-skeleton-table { border-radius: var(--bb-radius-lg); }
.bb-skeleton-label { height: 14px; width: 80px; border-radius: 4px; }
.bb-skeleton-list {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
    padding: var(--bb-space-4) 0;
}

/* Flag images */
.bb-flag-img {
    width: 20px;
    /*
     * height:auto, not a fixed 15px. Flag aspect ratios are not uniform: Nepal is
     * taller than it is wide, Switzerland and the Vatican are square, Qatar is very
     * wide. A fixed 20x15 box with object-fit:cover CROPPED all of those, cutting
     * part of the flag off. The real dimensions are emitted on the tag by
     * Bodybuilding_Flags::img(), so the natural ratio is preserved and nothing shifts.
     */
    height: auto;
    border-radius: 2px;
    vertical-align: middle;
    flex-shrink: 0;
}
.bb-flag-icon {
    width: 24px;
    height: 18px;
    border-radius: 2px;
    display: inline-block;
    vertical-align: middle;
}

/* Country cell (flag + name inline) */
.bb-country-cell {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* Badge modifiers */
.bb-badge--gold     { background: linear-gradient(135deg, rgba(217, 139, 74, 0.18), rgba(217, 139, 74, 0.28)); color: var(--bb-amber-dark); }
.bb-badge--silver   { background: var(--bb-gray-100); color: var(--bb-gray-500); }
.bb-badge--bronze   { background: #fff7ed; color: #9a3412; }
.bb-badge--male     { background: rgba(34, 28, 24, 0.1); color: var(--bb-navy-mid); }
.bb-badge--female   { background: rgba(178, 58, 53, 0.08); color: var(--bb-primary); }
.bb-badge--division {
    background: var(--bb-gray-100);
    color: var(--bb-gray-600);
    border-radius: var(--bb-radius-full);
    padding: 2px 10px;
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
}
.bb-badge--lg       { padding: 5px 14px; font-size: 13px; }

/* Button modifiers (double-dash variants used in templates) */
.bb-btn--primary    { background: var(--bb-primary); color: #fff !important; box-shadow: 0 1px 3px rgba(178, 58, 53,0.3); }
.bb-btn--primary:hover:not(:disabled) { background: var(--bb-primary-hover); }
.bb-btn--secondary  { background: var(--bb-surface); color: var(--bb-text-primary) !important; border: 2px solid var(--bb-border); }
.bb-btn--secondary:hover:not(:disabled) { background: var(--bb-gray-50); border-color: var(--bb-border-strong); }
.bb-btn--sm         { padding: var(--bb-space-2) var(--bb-space-3); font-size: 0.8125rem; min-height: 36px; }
.bb-btn-compare {
    margin-top: var(--bb-space-3);
    font-size: var(--bb-fs-sm);
}

/* Placement badges */
.bb-placement {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    padding: 3px 10px;
    font-size: 12px;
    font-weight: 700;
    border-radius: 6px;
    background: var(--bb-gray-100);
    color: var(--bb-text-secondary);
}
.bb-placement--gold,
.bb-place-badge--gold   { background: linear-gradient(135deg, rgba(217, 139, 74, 0.18), rgba(217, 139, 74, 0.28)); color: var(--bb-amber-dark); }
.bb-placement--silver,
.bb-place-badge--silver { background: var(--bb-gray-100); color: var(--bb-gray-500); }
.bb-placement--bronze,
.bb-place-badge--bronze { background: #fff7ed; color: #9a3412; }

/* Rank badges */
.bb-rank-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    font-size: 13px;
    font-weight: 800;
    border-radius: 8px;
    background: var(--bb-gray-100);
    color: var(--bb-gray-600);
}
.bb-rank-badge--gold   { background: linear-gradient(135deg, var(--bb-gold), var(--bb-gold-end)); color: var(--bb-gold-text); }
.bb-rank-badge--silver { background: linear-gradient(135deg, var(--bb-silver), var(--bb-silver-end)); color: var(--bb-silver-text); }
.bb-rank-badge--bronze { background: linear-gradient(135deg, var(--bb-bronze), var(--bb-bronze-end)); color: var(--bb-bronze-text); }

/* Share buttons */
.bb-share-wrap { position: relative; display: inline-flex; }
.bb-share-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    font-size: 13px;
    font-weight: 600;
    border-radius: var(--bb-radius-full, 9999px);
    border: 1px solid var(--bb-gray-200);
    background: transparent;
    color: var(--bb-text-secondary);
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
}
.bb-share-btn:hover { border-color: var(--bb-primary); color: var(--bb-primary); }
.bb-share-btn-light {
    background: rgba(255,255,255,0.15);
    border-color: rgba(255, 255, 255, 0.3);
    color: rgba(255, 255, 255, 0.7);
}
.bb-share-btn-light:hover { background: rgba(255,255,255,0.25); color: #fff; }

/* Share panel, one component for two markup shapes.
 *
 * This was a dark panel built from hardcoded literals: background #252538,
 * text #e8ecf2, white-alpha borders and a heavy black shadow. This product is
 * light only, and none of those values are in the token set, so it read as a
 * foreign element and forced a workaround: a comment here recorded that anchors
 * inside it were inheriting the theme's dark link colour and rendering
 * effectively invisible against the dark fill. On the light palette that whole
 * problem disappears, because the theme's dark link colour is now correct.
 *
 * partials/share-menu.php carries a second, older markup shape
 * (.bb-share-menu > .bb-share-actions / .bb-share-cards > .bb-share-action-btn /
 * .bb-share-card-link) which had no rule in any stylesheet at all. On the five
 * routes that include it (on-this-day, rankings, goat, era-goat,
 * prime-vs-prime), opening Share dumped bare inline text links into the page
 * flow: the panel measured position:static with no background, border, shadow or
 * padding, and its items rendered display:inline at 20px tall. Rather than write
 * a second panel, both shapes share these rules.
 */
/*
 * right: 0 is correct only when the trigger's wrapper is itself at the right of
 * the content column, which is how compare uses it (justify-content: flex-end).
 * The odds board wraps its trigger in a left-aligned block, so the same rule hung
 * the menu off the left edge of the screen: measured at 390px, left -98 of a
 * 210px menu, so 98px of it was unreachable. There is no single anchor that is
 * right for both, so the consumer states which edge it hangs from and the default
 * stays as it was.
 */
.bb-share-dropdown,
.bb-share-menu {
    position: absolute;
    top: calc(100% + 4px);
    min-width: 210px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-lg);
    padding: var(--bb-space-1) 0;
    z-index: 100;
    max-width: calc(100vw - var(--bb-space-6));
}
/*
 * Which edge the menu hangs from is a property of the trigger, so each class says.
 *
 * .bb-share-dropdown belongs to the bespoke menus, whose wrappers are placed at
 * the right of the content column (compare sets justify-content: flex-end), so
 * right: 0 is correct there.
 *
 * .bb-share-menu comes from partials/share-menu.php, whose .bb-share-wrap is an
 * inline-flex box sized to its trigger and sitting wherever it lands in normal
 * flow - which is near the LEFT on every route that uses it. Sharing right: 0 with
 * the other class hung it off the left edge of the screen. Measured at 390px
 * before this split: rankings left -117, on-this-day left -134, rankings/goat
 * left -10, all of a 210px menu, while every .bb-share-dropdown consumer was fine.
 */
.bb-share-dropdown {
    right: 0;
}
.bb-share-menu {
    left: 0;
}
/* Set by bbMenuPlace() when the anchored edge would put the menu off screen.
   Widening the content column to 1240 moved /rankings/'s trigger to x=1243, so
   its 210px menu ran to 1453 against a 1440 viewport; right-anchoring everything
   instead pushed /on-this-day/'s left-aligned trigger to x=-30. The edge is
   therefore measured per open rather than guessed per consumer. */
.bb-app [data-bb-flip="end"] {
    right: 0;
    left: auto;
}
.bb-app [data-bb-flip="start"] {
    left: 0;
    right: auto;
}
/* For a .bb-share-dropdown whose trigger is NOT right-aligned: the odds board
   wraps its trigger in a left-aligned block, where right: 0 put 98px of the menu
   off screen at 390px. */
.bb-share-dropdown--start {
    right: auto;
    left: 0;
}

.bb-share-menu .bb-share-actions,
.bb-share-menu .bb-share-cards {
    display: flex;
    flex-direction: column;
}

/* The cards group is a second tier: the generated PNG links, not a share target. */
.bb-share-menu .bb-share-cards {
    border-top: 1px solid var(--bb-gray-100);
    margin-top: var(--bb-space-1);
    padding-top: var(--bb-space-1);
}

.bb-share-dropdown-item,
.bb-share-action-btn,
.bb-share-card-link {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    width: 100%;
    min-height: 40px;
    padding: var(--bb-space-2) var(--bb-space-4);
    font-family: inherit;
    font-size: var(--bb-fs-label);
    font-weight: 600;
    line-height: 1.25;
    text-align: left;
    text-decoration: none;
    color: var(--bb-text-primary);
    background: none;
    border: none;
    cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.bb-share-dropdown-item:hover,
.bb-share-dropdown-item:focus-visible,
.bb-share-action-btn:hover,
.bb-share-action-btn:focus-visible,
.bb-share-card-link:hover,
.bb-share-card-link:focus-visible {
    background: var(--bb-gray-50);
    color: var(--bb-primary-hover);
}

.bb-share-dropdown-divider {
    height: 1px;
    background: var(--bb-gray-100);
    margin: var(--bb-space-1) var(--bb-space-3);
}

.bb-share-dropdown-item svg,
.bb-share-action-btn svg,
.bb-share-card-link svg {
    flex: 0 0 auto;
}
.bb-share-board { z-index: 20; }
.bb-share-board .bb-share-dropdown { min-width: 210px; }

/* Chevron toggle */
.bb-chevron {
    transition: transform 0.2s ease;
    flex-shrink: 0;
}
.bb-chevron--open { transform: rotate(180deg); }
.bb-chevron-transition { transition: transform var(--bb-transition-slow); }

/* Error states */
.bb-error-card {
    background: var(--bb-error-light);
    border: 1px solid var(--bb-error);
    border-radius: 6px;
    padding: 30px;
    text-align: center;
}
.bb-error-heading {
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin-bottom: var(--bb-space-2);
}
.bb-error-body {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
    margin-bottom: var(--bb-space-6);
}
.bb-error-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 3rem 1.5rem;
    color: var(--bb-text-muted);
}
.bb-empty-state--sm { padding: var(--bb-space-6) var(--bb-space-4); }

/*
 * The --sm variant is the one that sits INSIDE a box that already has its own
 * title, and the shared empty-state heading size is --bb-fs-lg (20px) against a
 * .bb-stats-box-title of --bb-fs-base (16px). So a nested empty state was
 * shouting over the heading above it. Every one of these was hidden on the
 * routes measured until the compare board got a visible one, at which point
 * test-type-scale-floor.mjs reported "H3 20px inside bb-stats-box-title 16px".
 * 15 of these across 6 templates, so it is fixed on the variant.
 */
.bb-empty-state--sm h2,
.bb-empty-state--sm h3,
.bb-empty-state--sm h4 {
    font-size: var(--bb-fs-sm);
}

/* SEO / About section: hub-overrides handles padding/bg on hub pages */
.bb-seo-section {
    padding: var(--bb-space-8);
}

/* Prose lists. The theme's `.rbct ul { list-style: circle }` sits at (0,1,1) and the
   plugin nests inside `.entry-content.rbct`, so an undeclared prose list renders the
   theme's hollow circle. These selectors are (0,2,1) and declare the marker outright. */
.bb-app .bb-seo-section ul {
    list-style: disc;
    padding-left: var(--bb-space-5);
}
.bb-app .bb-seo-section ol {
    list-style: decimal;
    padding-left: var(--bb-space-5);
}
.bb-app .bb-seo-section li {
    margin: 0 0 var(--bb-space-2);
}

/* Methodology / expandable info */
.bb-methodology {
    margin-top: var(--bb-space-8);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
}
.bb-methodology-toggle {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    padding: var(--bb-space-4) var(--bb-space-5);
    background: none;
    border: none;
    cursor: pointer;
    font-family: inherit;
}
.bb-methodology-title {
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin: 0;
}
.bb-methodology-content {
    padding: 0 var(--bb-space-5) var(--bb-space-5);
    color: var(--bb-text-secondary);
    line-height: 1.7;
    font-size: var(--bb-fs-sm);
}
.bb-methodology-table {
    font-size: var(--bb-fs-sm);
    margin-top: var(--bb-space-4);
}

/* FAQ icon (used in base layout) */
.bb-faq-icon { flex-shrink: 0; transition: transform 0.2s ease; }
.bb-faq-icon-open { transform: rotate(180deg); }

/* Input with icon variant */
.bb-input--search { padding-left: 40px; }
.bb-input-with-icon { padding-left: 40px; }

/* Search box */
.bb-search-box { position: relative; }

/* Single-athlete tool search bar (peak-window, division-migration) */
.bb-app .bb-tool-search-bar {
    display: flex;
    gap: 12px;
    align-items: center;
    flex-wrap: wrap;
    margin: 0 0 20px;
}
.bb-app .bb-tool-search {
    flex: 1 1 360px;
    min-width: 240px;
    max-width: 520px;
}
/* The dropdown rows are <button>s; reset the theme button chrome (red bg,
   radius, shadow, auto width) so they render as clean full-width result rows. */
/* Autocomplete options, every dropdown in the plugin.
 *
 * Each one is a <button role="option">, and the host theme styles buttons: a
 * pink fill, centred text and content-sized width. The result was a ragged
 * staircase of magenta blocks with dark-red subtext inside an otherwise clean
 * panel.
 *
 * A reset existed but only as `.bb-app .bb-tool-search .bb-compare-dropdown-item`,
 * and the compare page's chain is
 * .bb-search-box > .bb-compare-dropdown > button, with no .bb-tool-search
 * anywhere, so it never applied and the theme won on every surface.
 *
 * Bound to the role, not to each component's class. bb-ui.js, compare-vanilla.js,
 * game.js and widget-configurator.js all set role="option", so this covers the
 * global search, compare, the athlete pickers, the game and the widget builder
 * at once, and any dropdown added later inherits it. Layout per component is
 * below; this block only neutralises the theme and sets the shared shell.
 */
.bb-app [role="option"] {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    width: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: var(--bb-space-3) var(--bb-space-4);
    min-height: 44px;
    text-align: left;
    background: transparent;
    color: var(--bb-text-primary);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    -webkit-appearance: none;
    appearance: none;
    font: inherit;
    font-size: var(--bb-fs-15);
    line-height: 1.35;
    cursor: pointer;
}

.bb-app [role="option"] + [role="option"] {
    border-top: 1px solid var(--bb-gray-100);
}

/* Hover, keyboard focus and the active-descendant state all read the same, so
   arrowing through the list looks identical to moving the mouse. */
.bb-app [role="option"]:hover,
.bb-app [role="option"]:focus-visible,
.bb-app [role="option"][aria-selected="true"],
.bb-app [role="option"].is-active {
    background: var(--bb-gray-50);
    color: var(--bb-primary-hover);
}

.bb-app [role="option"] img {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.bb-app [role="option"] strong {
    font-weight: 650;
}

.bb-app [role="option"] small,
.bb-app [role="option"] .bb-compare-dropdown-meta {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
}

/* Compare: name on the first line, country and division under it. */
.bb-app .bb-compare-dropdown-item {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
}

/* Game: avatar on the left, name and meta stacked beside it. */
.bb-app .bb-game-suggestion__body {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.bb-app .bb-game-suggestion__avatar {
    display: flex;
    flex-shrink: 0;
}

/* The "no matches" row is a message, not a choice. */
.bb-app .bb-compare-dropdown-item--empty,
.bb-app .bb-game-suggestion--empty {
    color: var(--bb-text-muted);
    cursor: default;
}

/* Make filter children flex-friendly when inside a filter bar */
.bb-filter-bar > .bb-search-box,
.bb-toolbar > .bb-search-box {
    flex: 1;
    min-width: 200px;
    width: auto;
}
.bb-filter-bar > .bb-filter-select,
.bb-toolbar > .bb-filter-select,
.bb-filter-bar > .bb-toolbar-filter,
.bb-toolbar > .bb-toolbar-filter {
    width: auto;
    min-width: 160px;
    max-width: 220px;
    flex: 0 1 auto;
}
.bb-filter-bar > .bb-filter-select select,
.bb-toolbar > .bb-filter-select select {
    width: 100%;
}
.bb-filter-bar > .bb-per-page-select,
.bb-toolbar > .bb-per-page-select {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    white-space: nowrap;
}
.bb-filter-bar > .bb-per-page-select select,
.bb-toolbar > .bb-per-page-select select {
    width: auto;
    min-width: 60px;
}
.bb-search-icon {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bb-text-muted);
    pointer-events: none;
    z-index: 1;
}
.bb-search-clear {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    background: transparent;
    border: none;
    border-radius: 50%;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 18px;
    color: var(--bb-text-muted);
    transition: background 0.15s;
}
.bb-search-clear:hover { background: var(--bb-gray-300); }
/* The ring's track was --bb-gray-200 on a near-white input, which is almost
   invisible - so what you saw was a lone red fragment rotating at the edge of
   the field, reading as a stray mark rather than as a spinner. The track is now
   the border hairline, which is visible against paper, and the arc is oxblood.
   Slightly larger and slower for the same reason: at 16px/0.6s the coloured
   segment moves too fast to resolve as a circle. */
.bb-search-spinner {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 18px;
    height: 18px;
    border: 2px solid var(--bb-border);
    border-top-color: var(--bb-accent);
    border-radius: 50%;
    animation: bb-spin 0.8s linear infinite;
    pointer-events: none;
}
/* Fixed at source on .bb-app .bb-nav-search-input instead; a lower-specificity
   rule here lost silently and the query still ran under the spinner. */
.bb-app .bb-search-wrap input[type="search"],
.bb-app .bb-search-wrap input[type="text"] {
    padding-right: 38px;
}
/* The global reduced-motion block freezes every animation, which would leave a
   static ring meaning nothing. Fade it instead: aria-busy already carries the
   state, and this gives the eye a change without spinning anything. */
@media (prefers-reduced-motion: reduce) {
    .bb-search-spinner {
        animation: bb-search-pulse 1.2s ease-in-out infinite !important;
        animation-duration: 1.2s !important;
        animation-iteration-count: infinite !important;
        border-top-color: var(--bb-accent);
    }
    @keyframes bb-search-pulse {
        0%, 100% { opacity: 0.35; }
        50%      { opacity: 1; }
    }
}

/* Global search dropdown (base layout) */
.bb-search-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-lg);
    max-height: 400px;
    overflow-y: auto;
    z-index: 100;
}
.bb-search-group { padding: var(--bb-space-2) 0; }
.bb-search-group-label {
    padding: 6px 16px;
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-gray-400);
}
.bb-search-result,
.bb-combobox__result {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 16px;
    font-size: var(--bb-fs-sm);
    color: var(--bb-gray-700);
    cursor: pointer;
    transition: background 0.1s;
}
.bb-search-result:hover,
.bb-search-result-active,
.bb-combobox__result:hover,
.bb-combobox__result--active {
    background: var(--bb-gray-50);
    color: var(--bb-primary);
}
.bb-search-empty,
.bb-combobox__no-results,
.bb-combobox__error {
    padding: var(--bb-space-6);
    text-align: center;
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-sm);
}

.bb-combobox__error {
    color: var(--bb-error);
}
.bb-search-listbox {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Mobile search */
.bb-mobile-search { padding: var(--bb-space-3) var(--bb-space-4); }
.bb-mobile-menu { display: flex; flex-direction: column; }

/* Nav search inline */
.bb-nav-search-inline {
    position: relative;
    display: flex;
    flex: 1;
    align-items: center;
    max-width: 280px;
}
.bb-nav-search-input {
    width: 100%;
    padding: 7px 14px 7px 36px;
    font-size: 13px;
    border: 2px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-full);
    background: var(--bb-gray-50);
    color: var(--bb-gray-800);
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
    font-family: inherit;
}
.bb-nav-search-input:focus {
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
    background: var(--bb-surface);
}
.bb-nav-search-icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bb-gray-400);
    pointer-events: none;
}

@media (max-width: 768px) {
    .bb-app .bb-nav-search-inline {
        display: none;
    }
}

/* Breadcrumb (template variant) */
.bb-breadcrumb {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 13px;
    color: var(--bb-text-muted);
    margin-bottom: var(--bb-space-4);
}
.bb-breadcrumb a { color: var(--bb-primary); }
.bb-breadcrumb a:hover { color: var(--bb-primary-hover); }
.bb-breadcrumb__sep { color: var(--bb-gray-400); margin: 0 2px; }

/* Section header action link */
.bb-section-header-action {
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-primary);
    white-space: nowrap;
}
.bb-section-header-action:hover { color: var(--bb-primary-hover); }

/* Section label - badge style */
.bb-section-label {
    display: inline-block;
    padding: var(--bb-space-1) var(--bb-space-3);
    background: var(--bb-primary-light);
    color: var(--bb-primary-hover);
    border-radius: var(--bb-radius-full);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    margin-bottom: var(--bb-space-3);
}

/* Heading variants */
.bb-heading-section {
    font-family: var(--bb-font-heading);
    font-size: clamp(var(--bb-fs-2xl), 4vw, 2.5rem);
    font-weight: 700;
    line-height: 1.15;
    color: var(--bb-gray-800);
    letter-spacing: -0.02em;
    margin: 0 0 var(--bb-space-3);
}
.bb-heading-hero-sub {
    font-family: var(--bb-font-heading);
    font-size: clamp(var(--bb-fs-lg), 4vw, var(--bb-fs-3xl));
    font-weight: 600;
    line-height: 1.2;
    color: var(--bb-primary);
    margin: 0 0 var(--bb-space-6);
}

/* Page description */
.bb-page-desc {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
    margin-bottom: var(--bb-space-6);
    max-width: 600px;
    line-height: 1.6;
}

/* Results count / meta */
.bb-results-count,
.bb-results-meta {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    padding: var(--bb-space-2) 0;
}
.bb-results-heading {
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin-bottom: var(--bb-space-4);
}

/* Meta item */
.bb-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
}

/* Per-page selector */
.bb-per-page-label {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    font-weight: 500;
}
.bb-per-page-select {
    padding: 4px 8px;
    font-size: var(--bb-fs-xs);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface);
    font-family: inherit;
}

/* Filter bar: all filter containers unified */
.bb-filter-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}
.bb-filter-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 140px;
}
.bb-filter-group--count {
    margin-left: auto;
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    align-self: center;
    min-width: auto;
}
.bb-filter-group--search { flex: 1; min-width: 200px; }
.bb-filter-search {
    display: flex;
    gap: var(--bb-space-2);
    flex: 1;
    min-width: 200px;
}

/* Filter tabs */
.bb-filter-tabs {
    display: flex;
    gap: 0;
    flex-wrap: wrap;
}
.bb-filter-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    padding: 10px 16px;
    font-size: 14px;
    font-weight: 600;
    color: var(--bb-text-muted);
    background: transparent;
    border: none;
    border-radius: var(--bb-radius-full);
    cursor: pointer;
    transition: all 0.15s ease;
    font-family: inherit;
    white-space: nowrap;
    min-height: 36px;
}
.bb-filter-tab:hover { color: var(--bb-text-primary); }
.bb-filter-tab--active,
.bb-filter-btn-active {
    color: var(--bb-primary);
    border-bottom-color: var(--bb-primary);
}

/* Tab active (double-dash variant) */
.bb-tab--active {
    color: var(--bb-primary);
    border-bottom-color: var(--bb-primary);
}

/* Tabs scroll */
.bb-tabs--scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.bb-tabs--scroll::-webkit-scrollbar { display: none; }

/* Tab bar (contest detail variant) */
.bb-tab-bar {
    display: flex;
    gap: 2px;
    margin-bottom: 20px;
    border-bottom: 2px solid var(--bb-border);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Sort icons */
.bb-sortable { cursor: pointer; user-select: none; }
.bb-sortable:hover { color: var(--bb-primary); }
.bb-th-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.bb-th-sortable:hover { color: var(--bb-primary); }
.bb-app th.bb-th-sortable:focus-visible { outline: 2px solid var(--bb-primary); outline-offset: -2px; }
.bb-th-sorted { color: var(--bb-primary); }
.bb-sort-icon { margin-left: 4px; opacity: 0.4; font-size: 10px; }
.bb-sort-icon::after { content: '\25B2\25BC'; font-size: 8px; letter-spacing: -2px; }
.bb-sort-asc .bb-sort-icon,
.bb-sort-desc .bb-sort-icon { opacity: 1; color: var(--bb-primary); }
.bb-sort-asc .bb-sort-icon::after { content: '\25B2'; }
.bb-sort-desc .bb-sort-icon::after { content: '\25BC'; }

/* Pagination variants */
.bb-pagination-info {
    font-size: 13px;
    color: var(--bb-text-muted);
}
.bb-pagination-pages {
    display: flex;
    align-items: center;
    gap: 4px;
}
/* duplicate .bb-pagination__btn removed; canonical version in UDS section below */
.bb-pagination__btn--num { font-variant-numeric: tabular-nums; }
.bb-pagination__ellipsis,
.bb-page-ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    color: var(--bb-text-muted);
    font-size: 13px;
}
.bb-page-btn--active { background: var(--bb-primary); color: white; }

/* Table sub-components */
.bb-table-container {
    width: 100%;
    background: var(--bb-surface);
    border-radius: var(--bb-radius-lg);
    /* P0-3: was overflow:hidden, which clipped wide SSR tables (contest results,
       divisions Top Athletes) on mobile with no way to reach right-hand columns.
       overflow-x:auto lets them scroll; overflow-y:hidden keeps rounded corners. */
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--bb-gray-200);
    /* Wave-1 white-bg: this wrapper sits near-cream on the pure-white canvas with
       only a faint hairline, so it read as a white-on-white box. A subtle resting
       shadow gives the table a defined edge. */
    box-shadow: var(--bb-shadow-sm);
}
.bb-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.bb-table-row {}
.bb-table-row--gold   td:first-child { color: var(--bb-amber-dark); font-weight: 700; }
.bb-table-row--silver td:first-child { color: var(--bb-gray-500); font-weight: 700; }
.bb-table-row--bronze td:first-child { color: #9a3412; font-weight: 700; }
.bb-table-th { text-align: left; white-space: nowrap; }
.bb-table-th--place,
.bb-table-td--place { width: 70px; text-align: center; }
.bb-table-th--country,
.bb-table-td--country { width: 120px; }
.bb-table-td { vertical-align: middle; }
.bb-table-skeleton {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
    padding: var(--bb-space-4);
}
.bb-table-athlete-link { color: var(--bb-navy); font-weight: 600; }
.bb-table-athlete-link:hover { color: var(--bb-primary); }
.bb-table--results { font-size: 14px; }

/* Table column utilities */
.bb-table__col-place,
.bb-table__col--placement { width: 70px; text-align: center; }
.bb-table__col-athlete { min-width: 200px; }
.bb-table__col-country { width: 120px; }
.bb-table__link { color: var(--bb-navy); font-weight: 600; }
.bb-table__link:hover { color: var(--bb-primary); }

/* Column helpers */
.bb-col-name    { min-width: 180px; }
.bb-col-country { width: 120px; }
.bb-col-years   { width: 100px; }
.bb-col-numeric { text-align: right; font-variant-numeric: tabular-nums; }

/* Table cell type helpers (rankings/goat/top-lists) */
.bb-th-rank  { width: 60px; text-align: center; }
.bb-th-num   { width: 80px; text-align: right; font-variant-numeric: tabular-nums; }
.bb-td-rank  { text-align: center; font-variant-numeric: tabular-nums; }
.bb-td-num   { text-align: right; font-variant-numeric: tabular-nums; }
.bb-td-score { font-weight: 700; color: var(--bb-primary); font-variant-numeric: tabular-nums; }
.bb-td-athlete { font-weight: 600; }
.bb-td-country { }
.bb-td-division { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

/* Stat sub-components */
.bb-stat-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-align: center;
}
.bb-stat-number-sm { font-size: 20px; }
.bb-stat-text { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); text-transform: uppercase; letter-spacing: 0.05em; }
.bb-stat-wins { color: var(--bb-accent); }
.bb-stat-gold { color: #92600a; }
.bb-stat-card__label {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
}
.bb-stat-card__value {
    font-size: var(--bb-fs-2xl);
    font-weight: 800;
    color: var(--bb-text-primary);
}
.bb-stat-card__value--accent { color: var(--bb-primary); }

/* Stats box */
.bb-stats-box {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
    margin-bottom: var(--bb-space-6);
}
.bb-stats-box-title {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin-bottom: var(--bb-space-4);
}
.bb-stats-career-summary {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-6);
    padding-bottom: var(--bb-space-4);
    border-bottom: 1px solid var(--bb-gray-100);
    margin-bottom: var(--bb-space-4);
}
.bb-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: var(--bb-space-4);
}
.bb-stats-category {
    padding: var(--bb-space-4);
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius);
}
.bb-stats-category-title {
    font-size: var(--bb-fs-sm);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin-bottom: var(--bb-space-3);
}
.bb-stats-wsm {
    border: 1px solid rgba(143, 90, 30, 0.38);
    background: rgba(143, 90, 30, 0.06);
}
.bb-stats-strip {
    display: flex;
    flex-wrap: wrap;
    /* P2-22: gap:1px fused adjacent labels into "DIVISIONSCOUNTRIES". A real
       horizontal gap plus per-item padding separates them; flex-wrap keeps the
       2-column stack on mobile. */
    gap: 0 32px;
    padding: var(--bb-space-4) 0;
    border-bottom: 1px solid var(--bb-gray-200);
    margin-bottom: 28px;
}
.bb-stats-strip .bb-stat-item {
    padding-left: 16px;
    padding-right: 16px;
}
.bb-stats-bar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-4);
}
.bb-career-stats-heading { font-size: 0; }

/* ==========================================================================
   24. PAGE HERO (Rankings, Top Lists, GOAT)
   ========================================================================== */

.bb-page-hero {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    padding: 48px 0 40px;
    position: relative;
    overflow: hidden;
    margin-bottom: var(--bb-space-6);
    border-radius: var(--bb-radius-lg);
}
.bb-page-hero::before {
    content: '';
    position: absolute;
    top: -50%; right: -20%;
    width: 600px; height: 600px;
    background: radial-gradient(circle, rgba(178, 58, 53,0.1) 0%, transparent 70%);
    pointer-events: none;
}
.bb-page-hero--goat::after {
    content: '';
    position: absolute;
    bottom: -30%; left: -10%;
    width: 400px; height: 400px;
    background: radial-gradient(circle, rgba(217, 139, 74,0.06) 0%, transparent 70%);
    pointer-events: none;
}
.bb-page-hero__silhouette {
    position: absolute;
    right: clamp(8px, 3vw, 56px);
    top: 50%;
    transform: translateY(-50%);
    height: 88%;
    width: auto;
    max-width: 30%;
    object-fit: contain;
    object-position: center;
    opacity: 0.14;
    z-index: 0;
    pointer-events: none;
    user-select: none;
    filter: brightness(0) invert(1);
}
@media (max-width: 720px) {
    .bb-page-hero__silhouette { display: none; }
}
.bb-page-hero-content {
    max-width: var(--bb-container);
    margin: 0 auto;
    padding: 0 var(--bb-space-6);
    position: relative;
    z-index: 1;
}

/* Champions band hero: real champion portraits instead of the abstract
   silhouette watermark. Two-column flex (copy + faces) so there is no overlap
   math; on narrow screens it stacks and the band drops out. */
.bb-app .bb-page-hero--champs .bb-page-hero-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: clamp(24px, 4vw, 56px);
}
.bb-app .bb-page-hero--champs .bb-page-hero__text { flex: 1 1 auto; min-width: 0; }
.bb-app .bb-page-hero--champs .bb-page-hero-subtitle { max-width: 560px; }
.bb-page-hero__champs {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    z-index: 1;
}
.bb-page-hero__champ {
    display: block;
    width: clamp(72px, 7vw, 108px);
    height: clamp(72px, 7vw, 108px);
    border-radius: 50%;
    overflow: hidden;
    margin-left: -20px;
    border: 3px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.38);
    background: var(--bb-navy);
    transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}
.bb-page-hero__champ:first-child { margin-left: 0; }
.bb-page-hero__champ:hover,
.bb-page-hero__champ:focus-visible {
    transform: translateY(-5px) scale(1.05);
    border-color: var(--bb-gold, var(--bb-amber));
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.48);
    z-index: 2;
    position: relative;
}
.bb-page-hero__champ img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center top; /* show the FACE, never the torso/feet */
    display: block;
}
@media (max-width: 860px) {
    .bb-app .bb-page-hero--champs .bb-page-hero-content { display: block; }
    .bb-page-hero__champs { display: none; }
}
.bb-page-hero-title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-page-title);
    font-weight: 900;
    color: #fff !important;
    letter-spacing: -0.03em;
    line-height: 1.1;
    margin-bottom: var(--bb-space-3);
}
.bb-page-hero-subtitle {
    font-size: var(--bb-fs-md);
    color: rgba(255,255,255,0.75) !important;
    max-width: 600px;
    line-height: 1.6;
}

/* P3-12: removed the unscoped duplicate .bb-page-header--dark block here.
   Every usage pairs it with .bb-page-header inside .bb-app, so the scoped
   definition at section 8 (.bb-app .bb-page-header.bb-page-header--dark) and
   the route-wide layer always win on specificity. The unscoped copy was dead. */

/* Hero badge */
.bb-hero-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    /* On-dark hero kicker: light-warm label (oxblood would be illegible). */
    color: rgba(255, 253, 248, 0.72);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-bottom: var(--bb-space-6);
}
.bb-hero-badge-dot {
    width: 8px;
    height: 8px;
    background: var(--bb-primary);
    border-radius: 50%;
    animation: pulse 2s ease-in-out infinite;
}
.bb-hero-badge-text {
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: white;
}

/* Hero content / illustration */
/*
 * No cap. 600px was sized to sit beside the champions board; with the board gone it
 * only starved the headline, leaving 487px of dead space at 1440 and wrapping the h1
 * onto three lines. Measured every value from 820px up: the headline needs 1234px to
 * sit on one line, so nothing short of the full width helps it, and the dead space
 * shrank from 267px at 820 to 1px uncapped with no change to hero height. The outer
 * container already caps this at --bb-container (1240px), so the measure stays sane
 * on a wide screen. Used by hub.php only.
 */
.bb-hero-content {
    max-width: none;
    position: relative;
    z-index: 1;
    flex-shrink: 0;
}
.bb-hero-illustration {
    position: relative;
    z-index: 1;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 0;
}
.bb-hero-subtitle {
    font-size: var(--bb-fs-md);
    color: rgba(255,255,255,0.75);
    max-width: 600px;
    line-height: 1.6;
    margin-bottom: var(--bb-space-6);
}
.bb-hero-tagline { margin-bottom: var(--bb-space-2); }

@media (max-width: 640px) {
    .bb-page-hero { padding: 28px 0 24px; border-radius: 0; }
    .bb-page-hero-title { font-size: var(--bb-fs-page-title); }
    .bb-page-header--dark { padding: 20px 16px; }
}

/* ==========================================================================
   25. ARNOLD CLASSIC PAGES
   ========================================================================== */

/* --- Arnold Index --- */
.bb-arnold-page { margin-top: var(--bb-space-4); }
.bb-arnold-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-4);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    margin-bottom: var(--bb-space-6);
}

.bb-arnold-timeline {
    display: flex;
    flex-direction: column;
}

.bb-arnold-year-row {
    padding: var(--bb-space-4) 0;
    border-bottom: 1px solid var(--bb-gray-200);
}
.bb-arnold-year-row:last-child { border-bottom: none; }

.bb-arnold-year-header {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
    margin-bottom: var(--bb-space-2);
}

.bb-arnold-year-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 800;
    color: var(--bb-primary);
    transition: opacity 0.15s;
}
.bb-arnold-year-badge:hover { opacity: 0.8; }

.bb-arnold-year-num {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-primary);
}

.bb-arnold-year-location {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}

.bb-arnold-year-open-winner {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    margin-left: auto;
    font-size: var(--bb-fs-sm);
}
.bb-arnold-year-open-label {
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-muted);
    background: var(--bb-gray-100);
    padding: 2px 8px;
    border-radius: 4px;
}
.bb-arnold-year-winner-name {
    font-weight: 700;
    color: var(--bb-navy);
}
.bb-arnold-year-winner-name:hover { color: var(--bb-primary); }
.bb-arnold-year-winner-country {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}

.bb-arnold-year-divisions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-top: var(--bb-space-2);
}

.bb-arnold-division-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-full);
    font-size: var(--bb-fs-xs);
}
.bb-arnold-division-chip-name {
    font-weight: 600;
    color: var(--bb-text-secondary);
}
.bb-arnold-division-chip-winner {
    color: var(--bb-primary);
    font-weight: 600;
}
.bb-arnold-division-chip-winner:hover { color: var(--bb-primary-hover); }

/* --- Arnold Detail --- */
.bb-arnold-detail-page { margin-top: var(--bb-space-2); }

.bb-arnold-detail-hero {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
}
.bb-arnold-detail-hero-icon {
    width: 56px; height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Championship trophy icon on the dark hero: medal gold (legible + on-theme). */
    color: var(--bb-gold-champion);
    flex-shrink: 0;
}

.bb-arnold-detail-section {
    margin-bottom: var(--bb-space-8);
}

.bb-arnold-detail-champion {
    display: flex;
    align-items: center;
    gap: var(--bb-space-5);
    padding: var(--bb-space-5);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    margin-top: var(--bb-space-4);
}
.bb-arnold-detail-champion-avatar { flex-shrink: 0; }
.bb-arnold-detail-champion-img {
    width: 100px; height: 100px;
    border-radius: var(--bb-radius-lg);
    object-fit: cover;
    background: var(--bb-gray-100);
}
.bb-arnold-detail-champion-placeholder {
    width: 100px; height: 100px;
    border-radius: var(--bb-radius-lg);
    background: var(--bb-gray-100);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bb-gray-400);
}
.bb-arnold-detail-champion-info { flex: 1; min-width: 0; }
.bb-arnold-detail-champion-name {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-navy);
    display: block;
    margin-bottom: var(--bb-space-2);
}
.bb-arnold-detail-champion-name:hover { color: var(--bb-primary); }
.bb-arnold-detail-champion-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-bottom: var(--bb-space-2);
}
.bb-arnold-detail-champion-wins {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
    margin-top: var(--bb-space-2);
}

.bb-arnold-detail-division {
    margin-bottom: var(--bb-space-6);
    padding-bottom: var(--bb-space-6);
    border-bottom: 1px solid var(--bb-gray-100);
}
.bb-arnold-detail-division:last-child { border-bottom: none; padding-bottom: 0; }

.bb-arnold-detail-division-header {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-4);
}
.bb-arnold-detail-division-name {
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin: 0;
}

.bb-arnold-detail-year-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--bb-space-4);
    padding: var(--bb-space-8) 0;
    margin-top: var(--bb-space-4);
    border-top: 1px solid var(--bb-gray-200);
}

@media (max-width: 640px) {
    .bb-arnold-detail-champion { flex-direction: column; text-align: center; }
    .bb-arnold-detail-champion-meta { justify-content: center; }
    .bb-arnold-year-open-winner { margin-left: 0; width: 100%; margin-top: var(--bb-space-2); }
}

/* ==========================================================================
   26. OLYMPIA PAGES
   ========================================================================== */

/* --- Olympia Index Timeline --- */
.bb-olympia-timeline { display: flex; flex-direction: column; }

.bb-olympia-year-row {
    padding: var(--bb-space-4) 0;
    border-bottom: 1px solid var(--bb-gray-200);
}
.bb-olympia-year-row:last-child { border-bottom: none; }

.bb-olympia-year-header {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
    margin-bottom: var(--bb-space-2);
}
.bb-olympia-year-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 800;
    color: var(--bb-primary);
    transition: opacity 0.15s;
}
.bb-olympia-year-badge:hover { opacity: 0.8; }
.bb-olympia-year-num {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-primary);
    min-width: 60px;
}

.bb-olympia-year-open-winner {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    margin-left: auto;
    font-size: var(--bb-fs-sm);
}
.bb-olympia-year-open-label {
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-muted);
    background: var(--bb-gray-100);
    padding: 2px 8px;
    border-radius: 4px;
}
.bb-olympia-year-winner-name { font-weight: 700; color: var(--bb-navy); }
.bb-olympia-year-winner-name:hover { color: var(--bb-primary); }
.bb-olympia-year-winner-country { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

.bb-olympia-year-divisions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-top: var(--bb-space-2);
}
.bb-olympia-division-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-full);
    font-size: var(--bb-fs-xs);
}
.bb-olympia-division-chip-name { font-weight: 600; color: var(--bb-text-secondary); }
.bb-olympia-division-chip-winner { color: var(--bb-primary); font-weight: 600; }
.bb-olympia-division-chip-winner:hover { color: var(--bb-primary-hover); }

.bb-olympia-decade {
    font-size: var(--bb-fs-lg);
    font-weight: 800;
    color: var(--bb-text-primary);
    margin: var(--bb-space-6) 0 var(--bb-space-3);
    padding-bottom: var(--bb-space-2);
    border-bottom: 2px solid var(--bb-primary);
    display: inline-block;
}
.bb-olympia-division { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

/* Hub widget */
.bb-olympia-hub-widget {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
}

/* --- Olympia Detail --- */
.bb-olympia-detail-hero {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
}
.bb-olympia-detail-hero-icon {
    width: 56px; height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Championship trophy icon on the dark hero: medal gold (legible + on-theme). */
    color: var(--bb-gold-champion);
    flex-shrink: 0;
}
.bb-olympia-detail-section { margin-bottom: var(--bb-space-8); }
.bb-olympia-detail-loading {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-4);
    padding: var(--bb-space-4) 0;
}
.bb-olympia-detail-winner-skeleton {
    display: flex;
    gap: var(--bb-space-4);
    padding: var(--bb-space-5);
}

.bb-olympia-detail-champion {
    display: flex;
    align-items: center;
    gap: var(--bb-space-5);
    padding: var(--bb-space-5);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    margin-top: var(--bb-space-4);
}
.bb-olympia-detail-champion-avatar { flex-shrink: 0; }
.bb-olympia-detail-champion-img {
    width: 100px; height: 100px;
    border-radius: var(--bb-radius-lg);
    object-fit: cover;
    background: var(--bb-gray-100);
}
.bb-olympia-detail-champion-placeholder {
    width: 100px; height: 100px;
    border-radius: var(--bb-radius-lg);
    background: var(--bb-gray-100);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bb-gray-400);
}
.bb-olympia-detail-champion-info { flex: 1; min-width: 0; }
.bb-olympia-detail-champion-name {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-navy);
    display: block;
    margin-bottom: var(--bb-space-2);
}
.bb-olympia-detail-champion-name:hover { color: var(--bb-primary); }
.bb-olympia-detail-champion-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-bottom: var(--bb-space-2);
}
.bb-olympia-detail-champion-wins {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
    margin-top: var(--bb-space-2);
}
.bb-olympia-detail-placements { margin-top: var(--bb-space-4); }

.bb-olympia-detail-division {
    margin-bottom: var(--bb-space-6);
    padding-bottom: var(--bb-space-6);
    border-bottom: 1px solid var(--bb-gray-100);
}
.bb-olympia-detail-division:last-child { border-bottom: none; padding-bottom: 0; }
.bb-olympia-detail-division-header {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-4);
}
.bb-olympia-detail-division-name {
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin: 0;
}

.bb-olympia-detail-year-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--bb-space-4);
    padding: var(--bb-space-8) 0;
    margin-top: var(--bb-space-4);
    border-top: 1px solid var(--bb-gray-200);
}

/* Olympia results list (division detail page) */
.bb-olympia-results-list {
    display: flex;
    flex-direction: column;
}
.bb-olympia-result-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    padding: var(--bb-space-3) 0;
    border-bottom: 1px solid var(--bb-gray-100);
}
.bb-olympia-result-row:last-child { border-bottom: none; }
.bb-olympia-result-year {
    font-weight: 800;
    color: var(--bb-primary);
    min-width: 50px;
    font-size: var(--bb-fs-sm);
}
.bb-olympia-result-winner { font-weight: 600; color: var(--bb-navy); flex: 1; }
.bb-olympia-result-winner:hover { color: var(--bb-primary); }
.bb-olympia-result-country { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

@media (max-width: 640px) {
    .bb-olympia-detail-champion { flex-direction: column; text-align: center; }
    .bb-olympia-detail-champion-meta { justify-content: center; }
    .bb-olympia-year-open-winner { margin-left: 0; width: 100%; }
}

/* ==========================================================================
   27. RANKINGS & GOAT PAGES
   ========================================================================== */

.bb-rankings-page { margin-top: var(--bb-space-4); }

.bb-rankings-table { font-size: 14px; }
.bb-rankings-table-wrap {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    /* Wave-1 white-bg: subtle resting shadow so the rankings table reads as a
       defined surface on the pure-white canvas instead of a white-on-white box. */
    box-shadow: var(--bb-shadow-sm);
}
.bb-rankings-table-wrap .bb-table { margin-bottom: 0; }
/* P3-3: .bb-rankings-table-wrap keeps overflow:hidden so the rounded corners clip
   cleanly, but that also clips a wide table on a 390px viewport. Per owner decision
   the outer rule stays as-is; horizontal scroll lives on an INNER wrapper nested
   inside the radius container. Templates that render a wide table directly inside
   .bb-rankings-table-wrap (stats, top-lists, best, olympia-winners, rankings) should
   wrap the <table> in <div class="bb-rankings-table-scroll"> so it scrolls instead of
   clipping. (rankings/goat.php already nests .bb-table-scroll-wrapper, which carries
   its own overflow-x:auto.) */
.bb-rankings-table-wrap .bb-rankings-table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.bb-rankings-goat-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-4);
    margin-bottom: var(--bb-space-6);
    background: linear-gradient(135deg, rgba(217, 139, 74,0.08), rgba(178, 58, 53,0.06));
    border: 1px solid rgba(217, 139, 74,0.2);
    border-radius: var(--bb-radius-lg);
}
.bb-rankings-goat-link {
    font-weight: 700;
    color: var(--bb-primary);
}
.bb-rankings-goat-link:hover { color: var(--bb-primary-hover); }

.bb-rank-division {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}

/* --- GOAT Page --- */
.bb-goat-page { margin-top: var(--bb-space-4); }

.bb-goat-podium {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-8);
}

/*
 * The three rows the podium is already showing.
 *
 * They stay in the table markup so the client-side search can find them, sorted
 * views keep every row, and a crawler reads one complete list. This only hides
 * them while the podium is on screen, which the server decides: the class is
 * emitted solely when $bb_show_podium is true, and the filter script drops it
 * the moment a search query makes the podium hide.
 */
.bb-app .bb-goat-row--in-podium { display: none; }

.bb-goat-podium-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--bb-space-6) var(--bb-space-4);
    background: var(--bb-surface);
    border: 2px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-xl);
    transition: border-color 0.2s, box-shadow 0.2s;
}
.bb-goat-podium-card:hover { box-shadow: var(--bb-shadow-md); }
.bb-goat-podium-card--gold   { border-color: var(--bb-gold); background: linear-gradient(180deg, rgba(217, 139, 74,0.04) 0%, var(--bb-surface) 40%); }
.bb-goat-podium-card--silver { border-color: var(--bb-silver); background: linear-gradient(180deg, rgba(192,192,192,0.06) 0%, var(--bb-surface) 40%); }
.bb-goat-podium-card--bronze { border-color: var(--bb-bronze); background: linear-gradient(180deg, rgba(205,127,50,0.04) 0%, var(--bb-surface) 40%); }

.bb-goat-podium-rank {
    font-size: var(--bb-fs-2xl);
    font-weight: 900;
    color: var(--bb-primary);
    margin-bottom: var(--bb-space-3);
}
.bb-goat-podium-card--gold .bb-goat-podium-rank { color: var(--bb-amber); }
.bb-goat-podium-card--silver .bb-goat-podium-rank { color: var(--bb-gray-400); }
.bb-goat-podium-card--bronze .bb-goat-podium-rank { color: var(--bb-bronze); }

.bb-goat-podium-avatar {
    width: 80px; height: 80px;
    border-radius: 50%;
    overflow: hidden;
    margin-bottom: var(--bb-space-3);
    background: var(--bb-gray-100);
}
.bb-goat-avatar-img { width: 100%; height: 100%; object-fit: cover; }
.bb-goat-avatar-fallback {
    width: 100%; height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--bb-navy-mid), var(--bb-navy));
    color: white;
    font-size: 1.5rem;
    font-weight: 700;
}

.bb-goat-podium-name {
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-navy);
    margin-bottom: var(--bb-space-1);
}
.bb-goat-podium-name:hover { color: var(--bb-primary); }

.bb-goat-podium-division {
    font-size: var(--bb-fs-2xs);
    margin-bottom: var(--bb-space-3);
}

.bb-goat-podium-stats {
    display: flex;
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-3);
}
.bb-goat-stat { display: flex; flex-direction: column; align-items: center; gap: 1px; }
.bb-goat-stat-value { font-size: var(--bb-fs-lg); font-weight: 800; color: var(--bb-text-primary); }
.bb-goat-stat-label { font-size: var(--bb-fs-2xs); color: var(--bb-text-muted); text-transform: uppercase; letter-spacing: 0.05em; }

.bb-goat-podium-score { margin-top: auto; }
.bb-goat-score-num {
    font-size: var(--bb-fs-2xl);
    font-weight: 900;
    color: var(--bb-primary);
    line-height: 1;
}
.bb-goat-score-label {
    font-size: var(--bb-fs-2xs);
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.bb-goat-division {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}

/* Athlete cell (used in rankings/goat/top-lists tables) */
.bb-athlete-cell {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
}
.bb-athlete-avatar-sm {
    width: 36px; height: 36px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--bb-gray-100);
}
/*
 * Two things this selector has to survive, both measured on /predictions/:
 *
 * 1. display:block. An img is inline-level by default, so it sits on the text
 *    baseline and leaves a few px of descender gap inside the round mask. One
 *    template carried this as an inline style and the other three did not, so the
 *    same avatar was subtly off-centre on three pages out of four.
 * 2. The descendant selector, which is why this is (0,2,0) and not a flat class.
 *    Foxiz ships `.rbct img { height: auto }` at (0,1,1), and any avatar that lands
 *    inside the theme's `.entry-content.rbct` therefore ignored `height: 100%` and
 *    grew to its natural aspect: one card measured 36x54 inside a 36x36 mask while
 *    the twenty-nine outside .rbct were correct.
 *
 * The img only ever exists inside .bb-athlete-avatar-sm (Bodybuilding_Avatar::img
 * emits both), so scoping costs nothing and does not depend on a page wrapper.
 */
.bb-athlete-avatar-sm .bb-avatar-img-sm { display: block; width: 100%; height: 100%; object-fit: cover; }
.bb-avatar-fallback-sm {
    width: 100%; height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--bb-navy-mid), var(--bb-navy));
    color: white;
    font-size: 12px;
    font-weight: 700;
}
/*
 * min-height, not padding: these are flex items (the parent row blockifies them), so
 * the box grows within the row without shifting the row's own alignment. They
 * measured 21px, and they are standalone name links in a list row rather than links
 * inline in a sentence, so WCAG 2.2's inline exception does not cover them.
 */
.bb-athlete-name-link { font-weight: 700; color: var(--bb-navy); min-height: 24px; }
.bb-athlete-name-link:hover { color: var(--bb-primary); }

@media (max-width: 640px) {
    .bb-goat-podium { grid-template-columns: 1fr; }
    .bb-goat-podium-card { padding: var(--bb-space-4); }
}

/* GOAT gender sections */
.bb-goat-gender-section {
    margin-bottom: var(--bb-space-8);
}
.bb-goat-gender-section + .bb-goat-gender-section {
    padding-top: var(--bb-space-6);
    border-top: 2px solid var(--bb-gray-200);
}
.bb-goat-section-heading {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-navy);
    margin: 0 0 var(--bb-space-5) 0;
}
.bb-goat-section-heading svg {
    color: var(--bb-gold);
    flex-shrink: 0;
}

/* Score breakdown chips on podium cards */
.bb-goat-breakdown-mini {
    display: flex;
    gap: 4px;
    margin-top: var(--bb-space-2);
    flex-wrap: wrap;
    justify-content: center;
}
.bb-goat-breakdown-chip {
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    padding: 2px 6px;
    border-radius: 4px;
    background: var(--bb-gray-100);
    color: var(--bb-text-secondary);
    letter-spacing: 0.02em;
    cursor: help;
}

/* Breakdown columns in table */
.bb-th-breakdown,
.bb-td-breakdown {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    white-space: nowrap;
}
.bb-th-breakdown {
    font-size: 11px;
    letter-spacing: 0.02em;
}

/* Methodology intro paragraph */
.bb-methodology-intro {
    margin: 0 0 var(--bb-space-5) 0;
    line-height: 1.7;
}

/* Methodology components (reuses bb-faq-item styling) */
.bb-methodology-components {
    margin-top: var(--bb-space-4);
}
.bb-methodology-components .bb-faq-answer ul {
    margin: var(--bb-space-2) 0;
    padding-left: var(--bb-space-5);
}
.bb-methodology-components .bb-faq-answer li {
    margin-bottom: var(--bb-space-1);
}
.bb-methodology-components .bb-faq-answer code {
    background: var(--bb-gray-100);
    padding: 2px 6px;
    border-radius: 4px;
    font-size: var(--bb-fs-xs);
}
.bb-goat-methodology {
    margin-top: var(--bb-space-10);
}

/* Hide breakdown columns on small screens for readability */
@media (max-width: 900px) {
    .bb-th-breakdown,
    .bb-td-breakdown {
        display: none;
    }
}

/* ==========================================================================
   28. TOP LISTS PAGE
   ========================================================================== */

.bb-top-lists-page { margin-top: var(--bb-space-4); }

.bb-top-lists-overview { margin-bottom: var(--bb-space-8); }

.bb-top-lists-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-6);
}
@media (min-width: 768px) { .bb-top-lists-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.bb-top-list-nav-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--bb-space-2);
    padding: var(--bb-space-4);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    cursor: pointer;
    text-align: center;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.bb-top-list-nav-card:hover { border-color: var(--bb-primary); box-shadow: var(--bb-shadow-md); }
.bb-top-list-nav-card--active {
    border-color: var(--bb-primary);
    background: var(--bb-primary-light);
}
.bb-top-list-nav-title {
    font-size: var(--bb-fs-sm);
    font-weight: 700;
    color: var(--bb-text-primary);
}
.bb-top-list-nav-desc {
    font-size: var(--bb-fs-2xs);
    color: var(--bb-text-muted);
    line-height: 1.4;
}

.bb-top-list-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-4);
    flex-wrap: wrap;
}
.bb-top-list-title {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-text-primary);
}
.bb-top-list-desc {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    margin-bottom: var(--bb-space-4);
    max-width: 600px;
}
.bb-tl-division { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

.bb-top-athletes-section { margin-bottom: var(--bb-space-8); }
.bb-top-athletes-grid {
    display: grid;
    /*
     * 340, not 220. At 220 this laid out five 226px columns, and the card is a
     * horizontal row - rank, then a 60px avatar, then the text - so the text
     * column came out at 84px. A division badge is 162px and does not wrap, so
     * it hung 79px outside the card and over its neighbour. Truncating it fixed
     * the overflow and produced "Men's O...", which is not a label.
     *
     * At 340 the grid resolves to three columns on a 1192px page, giving the
     * text roughly 270px - enough for the longest division name. Six athletes
     * then fill two complete rows instead of leaving a single orphan on a third.
     */
    grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
    gap: var(--bb-space-4);
}

/* Hub top-athletes card: horizontal row layout (rank + avatar + info) */
.bb-top-athletes-section .bb-athlete-card {
    flex-direction: row;
    align-items: center;
    gap: var(--bb-space-3);
    padding: 16px 20px;
    overflow: visible;
    text-decoration: none;
    color: inherit;
}
.bb-top-athletes-section .bb-athlete-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
    border-color: var(--bb-primary);
}

/* ==========================================================================
   29. COMPARE PAGE
   ========================================================================== */

.bb-compare-selectors {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: var(--bb-space-4);
    align-items: start;
    margin-bottom: var(--bb-space-8);
}
@media (max-width: 768px) {
    .bb-compare-selectors { grid-template-columns: 1fr; }
}

.bb-compare-selector-card {
    background: var(--bb-surface);
    border: 2px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
    min-height: 200px;
    transition: border-color 0.2s;
}
.bb-compare-selector-card--loaded { border-color: var(--bb-primary); }

.bb-compare-selector-label {
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-text-muted);
    margin-bottom: var(--bb-space-3);
}

.bb-compare-search { margin-bottom: var(--bb-space-3); }

.bb-compare-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0; right: 0;
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-lg);
    max-height: 300px;
    overflow-y: auto;
    z-index: 50;
}
.bb-compare-dropdown-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 16px;
    cursor: pointer;
    transition: background 0.1s;
    font-weight: 600;
    color: var(--bb-navy);
}
.bb-compare-dropdown-item:hover { background: var(--bb-gray-50); color: var(--bb-primary); }
.bb-compare-dropdown-meta {
    font-size: var(--bb-fs-xs);
    font-weight: 400;
    color: var(--bb-text-muted);
}

.bb-compare-selected {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-3);
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius);
}
.bb-compare-selected-avatar {
    width: 48px; height: 48px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--bb-gray-200);
}
.bb-compare-selected-info { flex: 1; min-width: 0; }
.bb-compare-selected-meta {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: 2px;
}

/* Remove-athlete control.
   It rendered as an 80x28 grey pill with a 16px glyph adrift inside it - the
   "looks broken" report. The width here was 28px the whole time; the parent
   theme sets `padding: 0 40px` on every <button>, and with border-box that
   padding beats a smaller declared width, so the box was forced to 80. Resetting
   the theme's padding is the fix; the size was never wrong.

   claude-design draws no remove control on the Compare page, so this is built
   from the same vocabulary as the rest: hairline border, tint on hover, oxblood
   for the destructive read, filled oxblood while pressed. */
.bb-app .bb-compare-clear {
    position: relative;
    width: 36px;
    height: 36px;
    min-width: 0;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
    color: var(--bb-warm-grey);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
/* 36px reads correctly beside a 60px avatar; the tap target still has to be 44.
   An overlay gives the finger the full area without making the box heavier. */
.bb-app .bb-compare-clear::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--bb-touch-min);
    height: var(--bb-touch-min);
    transform: translate(-50%, -50%);
}
.bb-app .bb-compare-clear .bb-icon {
    width: 16px;
    height: 16px;
}
.bb-app .bb-compare-clear:hover {
    background: var(--bb-tint);
    border-color: var(--bb-accent);
    color: var(--bb-accent);
}
.bb-app .bb-compare-clear:focus-visible {
    border-color: var(--bb-accent);
    color: var(--bb-accent);
    outline: 2px solid var(--bb-accent);
    outline-offset: 2px;
}
/* Pressed state. There was none anywhere in the plugin, so a click gave no
   confirmation that anything had been registered. */
.bb-app .bb-compare-clear:active {
    background: var(--bb-accent);
    border-color: var(--bb-accent);
    color: var(--bb-on-dark);
}

.bb-compare-vs {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--bb-fs-2xl);
    font-weight: 900;
    /* Bone, was --bb-primary. Oxblood is the accent for LIGHT surfaces; this "VS"
       sits in the dark compare hero, where it measured 2.47:1 against the 3:1 floor
       for text this size. Bone rather than the on-dark amber on purpose - "VS" is
       structural punctuation between two names, and amber carries medal meaning
       everywhere else in this design. */
    color: var(--bb-bone);
    padding-top: var(--bb-space-10);
}
/* Was a style attribute on the element, so it could not respond to anything. */
.bb-compare-controls {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--bb-space-2);
    margin: var(--bb-space-1) 0 var(--bb-space-2);
}
/*
 * The server-rendered head-to-head summary had no rule of its own, so it ended
 * flush against whatever followed it: measured 0px between its bottom edge and
 * the next sibling on both pairs at both widths.
 */
.bb-h2h-summary {
    margin-bottom: var(--bb-space-6);
}

.bb-compare-results { margin-top: var(--bb-space-2); }
.bb-compare-prompt {
    text-align: center;
    padding: var(--bb-space-12);
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-sm);
}

/* Head-to-Head */
.bb-compare-h2h-box { margin-bottom: var(--bb-space-6); }
.bb-compare-h2h-grid {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: var(--bb-space-4);
    align-items: center;
    text-align: center;
}
.bb-compare-h2h-side { display: flex; flex-direction: column; align-items: center; gap: var(--bb-space-1); }
.bb-compare-h2h-side--b {}
.bb-compare-h2h-name { font-weight: 700; color: var(--bb-navy); font-size: var(--bb-fs-sm); }
.bb-compare-h2h-wins { font-size: var(--bb-fs-3xl); font-weight: 900; color: var(--bb-primary); }
/* P2-19: distinguish the two athletes (A=primary / B=navy), matching the
   timeline/radar legend. Previously both win counts were the same red. */
.bb-compare-h2h-side--b .bb-compare-h2h-wins { color: var(--bb-navy); }
.bb-compare-h2h-label { font-size: var(--bb-fs-2xs); color: var(--bb-text-muted); text-transform: uppercase; }

.bb-compare-h2h-center { display: flex; flex-direction: column; align-items: center; gap: var(--bb-space-2); }
.bb-compare-h2h-contests { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
.bb-compare-h2h-bar {
    /* P2-19: flex row so bar-a (left) and bar-b (right) meet in the middle. */
    display: flex;
    width: 100%;
    height: 8px;
    background: var(--bb-gray-200);
    border-radius: 4px;
    overflow: hidden;
    min-width: 80px;
}
.bb-compare-h2h-bar-a {
    height: 100%;
    background: var(--bb-primary);
    border-radius: 4px 0 0 4px;
    transition: width 0.4s ease;
}
/* P2-19: athlete B fill, navy, anchored to the right edge (A=primary / B=navy
   matches the timeline/radar). margin-left:auto pushes it against the right side
   so the two fills read as a split bar meeting in the middle. */
.bb-compare-h2h-bar-b {
    height: 100%;
    margin-left: auto;
    background: var(--bb-navy);
    border-radius: 0 4px 4px 0;
    transition: width 0.4s ease;
}

/* Stats comparison grid */
.bb-compare-stats-grid { margin-top: var(--bb-space-4); }
.bb-compare-stats-header {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: var(--bb-space-2);
    padding: var(--bb-space-3) var(--bb-space-4);
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius) var(--bb-radius) 0 0;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-muted);
}
.bb-compare-stats-row {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: var(--bb-space-2);
    padding: var(--bb-space-3) var(--bb-space-4);
    border-bottom: 1px solid var(--bb-gray-100);
    align-items: center;
}
.bb-compare-stats-row:last-child { border-bottom: none; }
.bb-compare-stats-row-- {}
.bb-compare-stats-label { font-size: var(--bb-fs-sm); font-weight: 600; color: var(--bb-text-secondary); }
.bb-compare-stats-val { font-size: var(--bb-fs-sm); font-weight: 700; color: var(--bb-text-primary); text-align: center; }
.bb-compare-stats-val--a { text-align: center; }
.bb-compare-stats-val--b { text-align: center; }
.bb-compare-val--winner { color: var(--bb-primary); font-weight: 800; }

@media (max-width: 600px) {
    .bb-compare-stats-header,
    .bb-compare-stats-row { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
    .bb-compare-h2h-grid { grid-template-columns: 1fr; gap: var(--bb-space-3); }
    .bb-compare-h2h-center { order: -1; }
}

/* Career Overlap Timeline */
.bb-compare-timeline-box { margin-bottom: var(--bb-space-6); }
.bb-compare-timeline-wrap {
    position: relative;
    padding: var(--bb-space-6) 0 var(--bb-space-2);
    overflow-x: auto;
}
/*
 * Every offset below is measured from the top of the plot, and the two rows are
 * 34px apart. The band that used to sit above axis A held the per-row name
 * labels; those are gone (the legend owns that mapping now, outside the plot),
 * so the whole plot moved up by 14px and the box lost the same amount.
 */
.bb-timeline {
    position: relative;
    min-height: 106px;
    padding: 0 var(--bb-space-4);
}
.bb-timeline-axis {
    position: absolute;
    left: var(--bb-space-4);
    right: var(--bb-space-4);
    height: 2px;
    background: var(--bb-gray-200);
}
.bb-timeline-axis--a { top: 20px; }
.bb-timeline-axis--b { top: 54px; }
.bb-timeline-labels {
    display: flex;
    justify-content: space-between;
    padding: 0 var(--bb-space-4);
    margin-top: var(--bb-space-3);
}
.bb-timeline-year {
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    color: var(--bb-text-muted);
}
.bb-timeline-bar {
    position: absolute;
    height: 6px;
    border-radius: 3px;
    transition: width 0.4s ease, left 0.4s ease;
}
.bb-timeline-bar--a {
    top: 17px;
    background: var(--bb-primary);
}
.bb-timeline-bar--b {
    top: 51px;
    background: var(--bb-navy);
}
.bb-timeline-overlap {
    position: absolute;
    top: 26px;
    height: 24px;
    background: linear-gradient(180deg, rgba(178, 58, 53, 0.08) 0%, rgba(34, 28, 24, 0.08) 100%);
    border: 1px dashed rgba(178, 58, 53, 0.58);
    border-radius: 2px;
}
.bb-timeline-marker {
    position: absolute;
    top: 26px;
    width: 3px;
    height: 24px;
    background: var(--bb-accent);
    border-radius: 2px;
    opacity: 0.7;
}
.bb-timeline-marker:hover {
    opacity: 1;
    transform: scaleY(1.3);
    transform-origin: center;
}
.bb-timeline-legend {
    display: flex;
    gap: var(--bb-space-5);
    justify-content: center;
    margin-top: var(--bb-space-3);
    padding-top: var(--bb-space-2);
    border-top: 1px solid var(--bb-gray-100);
}
.bb-timeline-legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    font-weight: 500;
}
.bb-timeline-legend-dot {
    width: 10px;
    height: 10px;
    border-radius: 2px;
}

/* Shareable Stats Card */
.bb-compare-sharecard-box { margin-bottom: var(--bb-space-6); }
.bb-compare-sharecard-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--bb-space-4);
}
/*
 * The card is a generated PNG, so this styles a frame around an image rather
 * than painting a card in CSS. Aspect ratio is declared so the box holds its
 * height before the file arrives and nothing below it shifts.
 */
.bb-sharecard-figure {
    width: 100%;
    /* Portrait now: the preview is the 1080x1350 poster, not the landscape OG
       render. At the old 720px cap a 4:5 card renders 900px tall and swallows
       the page, so the frame is sized off the card's own ratio instead. */
    max-width: 400px;
    margin: 0;
    aspect-ratio: 1080 / 1350;
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    /* Matches the paper the card itself is drawn on, so no seam shows while it loads. */
    background: var(--bb-surface);
    overflow: hidden;
    box-shadow: var(--bb-shadow-sm);
}
.bb-sharecard-link {
    display: block;
    width: 100%;
    height: 100%;
}
.bb-sharecard-link:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}
.bb-sharecard-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
}
.bb-sharecard-actions {
    display: flex;
    gap: var(--bb-space-3);
    flex-wrap: wrap;
    justify-content: center;
}

/* ==========================================================================
   30. COUNTRIES PAGES
   ========================================================================== */

.bb-countries-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: var(--bb-space-4);
}

.bb-country-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-6);
    transition: all 0.2s ease;
}
.bb-country-card:hover { transform: translateY(-2px); border-color: var(--bb-primary); box-shadow: var(--bb-shadow-md); }
.bb-country-card--link { cursor: pointer; display: block; text-decoration: none; color: inherit; }

.bb-country-card__header {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-3);
}
.bb-country-card__flag {
    width: 36px; height: 27px;
    border-radius: 3px;
    object-fit: cover;
    flex-shrink: 0;
    background: var(--bb-gray-100);
}
/* .bb-app-scoped, and that is load-bearing rather than housekeeping. This is now
   an h2 carrying a card title, and the plugin's own `.bb-app h2` section rule is
   (0,1,1) while a bare `.bb-country-card__name` is (0,1,0), so unscoped the card
   title rendered at the 26px section size and every card on /countries/ grew.
   margin:0 for the same reason: it was a span and had none. */
.bb-app .bb-country-card__name {
    display: block;
    margin: 0;
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
}
.bb-country-card__stats {
    display: flex;
    gap: var(--bb-space-4);
}
.bb-country-card__stat {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
}
.bb-country-card__stat-accent {
    font-weight: 700;
    color: var(--bb-primary);
}

/*
 * 147 countries, one per row, 110px each: 16,176px of a 20,422px page, and the
 * card only ever holds a name and a count. Measured 2026-08-06 at 375px the
 * content came to 40px and the padding to 45px, so more than half of every card
 * was air, in a single 324px column carrying a 15px word.
 *
 * Two columns and tighter padding. 600px rather than 768: at 640 the single
 * column is already narrow enough that a second one would put the longest names
 * over two lines, and a grid row sizes to its tallest card, so one wrapped name
 * pads its neighbour as well.
 *
 * Five of the 147 names still wrap at this width ("Bosnia and Herzegovina" is
 * the longest at 163px against ~110px of room). That is five rows 18px taller,
 * which is a rounding error against halving the row count, and the alternative
 * is dropping the flag - which is the one thing on the card that makes it
 * scannable at a glance.
 */
@media (max-width: 600px) {
    .bb-app .bb-countries-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px;
    }
    .bb-app .bb-country-card {
        padding: 10px 11px;
        border-radius: var(--bb-radius-md);
    }
    .bb-app .bb-country-card__header {
        gap: 7px;
        margin-bottom: 3px;
    }
    .bb-app .bb-country-card__flag {
        width: 20px;
        height: 15px;
    }
    .bb-app .bb-country-card__name {
        font-size: var(--bb-fs-sm);
        line-height: 1.25;
    }
    .bb-app .bb-country-card__stats {
        gap: 8px;
        flex-wrap: wrap;
    }
    .bb-app .bb-country-card__stat {
        font-size: var(--bb-fs-xs);
    }
}

/* Country detail */
.bb-country-detail-hero {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-2);
}
.bb-country-detail-flag {
    width: 56px; height: 42px;
    border-radius: 4px;
    object-fit: cover;
    flex-shrink: 0;
}
.bb-country-search { flex: 1; min-width: 200px; }
.bb-country-sort { min-width: 160px; }

/* ==========================================================================
   31. DIVISIONS PAGES
   ========================================================================== */

.bb-divisions-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: var(--bb-space-4);
}
.bb-divisions-section { padding: var(--bb-space-16) 0; }
.bb-divisions-heading {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-text-primary);
    margin-bottom: var(--bb-space-4);
}

.bb-division-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-6);
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
    transition: all 0.2s ease;
}
.bb-division-card:hover {
    transform: translateY(-2px);
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}
.bb-division-card--link { cursor: pointer; text-decoration: none; color: inherit; display: flex; }

.bb-division-card__icon {
    width: 44px; height: 44px;
    background: var(--bb-gray-100);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    flex-shrink: 0;
}
.bb-division-card__icon--male { background: rgba(34, 28, 24, 0.1); color: var(--bb-navy-mid); }
.bb-division-card__icon--female { background: rgba(178, 58, 53,0.08); color: var(--bb-primary); }
.bb-division-card__name { font-size: var(--bb-fs-base); font-weight: 700; color: var(--bb-text-primary); }
.bb-division-card__desc { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); line-height: 1.5; }
.bb-division-card__stats { display: flex; gap: var(--bb-space-4); margin-top: auto; }
.bb-division-card__stat { font-size: var(--bb-fs-sm); color: var(--bb-text-muted); }

/* Division detail */
.bb-division-detail-hero {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-2);
}
.bb-division-detail-icon {
    width: 56px; height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--bb-radius-lg);
    font-size: 1.5rem;
    background: var(--bb-gray-100);
}
.bb-division-detail-icon--male { background: rgba(34, 28, 24, 0.1); color: var(--bb-navy-mid); }
.bb-division-detail-icon--female { background: rgba(178, 58, 53,0.08); color: var(--bb-primary); }
.bb-division-detail-badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-bottom: var(--bb-space-4);
}
.bb-division-detail-section { margin-bottom: var(--bb-space-8); }

/* Division breakdown bars (profile/detail) */
.bb-division-breakdown {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-4);
}
.bb-division-bar { display: flex; flex-direction: column; gap: var(--bb-space-2); }
.bb-division-bar__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--bb-space-2);
}
.bb-division-bar__name { font-size: var(--bb-fs-sm); font-weight: 600; color: var(--bb-text-primary); }
.bb-division-bar__counts { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
.bb-division-bar__wins { color: var(--bb-accent); font-weight: 600; }
.bb-division-bar__track {
    height: 8px;
    background: var(--bb-gray-100);
    border-radius: 4px;
    overflow: hidden;
}
.bb-division-bar__fill {
    height: 100%;
    background: var(--bb-primary);
    border-radius: 4px;
    transition: width 0.4s ease;
}

/* Hub division list */
.bb-division-header {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-2);
}
.bb-division-name { font-weight: 700; color: var(--bb-text-primary); flex: 1; }
.bb-division-count { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
.bb-division-gender-icon {
    width: 32px; height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--bb-radius);
    font-size: 1rem;
    flex-shrink: 0;
    color: var(--bb-text-muted);
}
.bb-division-gender-icon svg { width: 16px; height: 16px; }
.bb-division-gender-icon--male   { background: rgba(34, 28, 24, 0.1);  color: var(--bb-navy-mid); }
.bb-division-gender-icon--female { background: rgba(178, 58, 53, 0.08); color: var(--bb-primary); }
.bb-division-filter { min-width: 160px; }

/* Division index - section labels */
.bb-divisions-section-label { margin-bottom: var(--bb-space-6); }
.bb-divisions-section-title {
    font-size: var(--bb-fs-2xl);
    font-weight: 800;
    color: var(--bb-text-primary);
    margin: var(--bb-space-1) 0 var(--bb-space-2);
}
.bb-divisions-section-subtitle { font-size: var(--bb-fs-sm); color: var(--bb-text-muted); }

/* Division cards grid - 4 cols desktop, 2 tablet, 1 mobile */
.bb-divisions-grid--cards {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--bb-space-4);
}
@media (max-width: 1024px) { .bb-divisions-grid--cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 768px) { .bb-divisions-grid--cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .bb-divisions-grid--cards { grid-template-columns: 1fr; } }

/* Full-card variant (column layout) */
.bb-division-card--full {
    flex-direction: column;
    gap: var(--bb-space-2);
    padding: var(--bb-space-5);
}
.bb-division-card--full .bb-division-card__icon { margin-bottom: var(--bb-space-2); }
.bb-division-card--full .bb-division-card__stats { margin-top: var(--bb-space-3); }

/* Year introduced inline label inside card */
.bb-division-card__year {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: var(--bb-space-1);
}

/* Year badge variant */
.bb-badge--year {
    background: var(--bb-gray-100);
    color: var(--bb-text-secondary);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* Division detail hero info block */
.bb-division-detail-hero__info { flex: 1; }

/* Historical division notice */
.bb-division-detail-history {
    display: flex;
    align-items: flex-start;
    gap: var(--bb-space-3);
    background: var(--bb-accent-light);
    border: 1px solid var(--bb-accent-soft);
    border-radius: var(--bb-radius);
    padding: var(--bb-space-4);
    margin-bottom: var(--bb-space-6);
    font-size: var(--bb-fs-sm);
}
.bb-division-detail-history__text { color: var(--bb-text-secondary); margin: var(--bb-space-1) 0 0; }

/* Other divisions collapsible section */
.bb-divisions-other {
    margin-top: var(--bb-space-8);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius);
    overflow: hidden;
}
.bb-divisions-other__toggle {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--bb-space-4) var(--bb-space-5);
    background: var(--bb-gray-50);
    border: none;
    cursor: pointer;
    text-align: left;
    font-size: var(--bb-fs-base);
    font-weight: 600;
    color: var(--bb-text-primary);
    transition: background 0.15s;
}
.bb-divisions-other__toggle:hover { background: var(--bb-gray-100); }
.bb-divisions-other__label {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
}
/* The summary is display:flex, which suppresses the native disclosure marker,
   so the chevron is the only affordance. Rotation is driven by [open], not a JS class. */
.bb-divisions-other__chevron { color: var(--bb-text-muted); transition: transform 0.2s; flex-shrink: 0; }
.bb-divisions-other[open] .bb-divisions-other__chevron { transform: rotate(180deg); }
.bb-divisions-other__toggle::-webkit-details-marker { display: none; }
.bb-divisions-other__body {
    padding: var(--bb-space-5);
    border-top: 1px solid var(--bb-gray-200);
    background: var(--bb-surface);
}
.bb-divisions-other__desc {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
    margin-bottom: var(--bb-space-4);
    line-height: 1.6;
}
.bb-divisions-other__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr));
    gap: var(--bb-space-2);
}
.bb-divisions-other__item { display: flex; }
.bb-divisions-other__link {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-primary);
    text-decoration: none;
    padding: var(--bb-space-2) var(--bb-space-3);
    border-radius: var(--bb-radius-sm);
    transition: background 0.15s, color 0.15s;
    width: 100%;
}
.bb-divisions-other__link:hover { background: var(--bb-primary-light); color: var(--bb-primary); }
.bb-divisions-other__count { color: var(--bb-text-muted); font-size: var(--bb-fs-xs); }

/* ==========================================================================
   32. CONTESTS PAGES
   ========================================================================== */

.bb-contests-page { margin-top: var(--bb-space-4); }
.bb-contests-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-4);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    margin-bottom: var(--bb-space-6);
}

.bb-contest-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: var(--bb-space-4);
}

/* Contest card sub-components */
.bb-contest-card__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--bb-space-2);
    margin-bottom: var(--bb-space-2);
}
.bb-contest-card__name { font-size: var(--bb-fs-base); font-weight: 700; color: var(--bb-text-primary); line-height: 1.3; }
/* margin-left:auto keeps the year pinned right when the tier badge is absent
   (event_tier is NULL on most rows, so most cards have no badge). */
.bb-contest-card__year { font-size: var(--bb-fs-sm); font-weight: 800; color: var(--bb-primary); flex-shrink: 0; margin-left: auto; }
.bb-contest-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: auto;
}
.bb-contest-card__location { display: flex; align-items: center; gap: 4px; }
.bb-contest-card__arrow {
    color: var(--bb-gray-400);
    margin-left: auto;
    transition: transform 0.15s;
}

.bb-contests-list { display: flex; flex-direction: column; }

/* Contest detail */
.bb-contest-detail-page { margin-top: var(--bb-space-2); }
.bb-contest-detail__title-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    flex-wrap: wrap;
}
.bb-contest-detail__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-4);
    margin-top: var(--bb-space-3);
    font-size: var(--bb-fs-sm);
    color: rgba(255,255,255,0.7);
}
.bb-contest-results { margin-top: var(--bb-space-2); }
.bb-data-nav-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-bottom: var(--bb-space-6);
}
.bb-data-nav-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    color: var(--bb-primary);
    text-decoration: none;
    transition: color 0.15s;
}
.bb-data-nav-link:hover { color: var(--bb-primary-hover); text-decoration: underline; }

/* Contest row (hub + seasons) */
.bb-contest-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    padding: 16px 24px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
    cursor: pointer;
    margin-bottom: var(--bb-space-3);
    text-decoration: none;
    color: inherit;
}
.bb-contest-row:hover {
    transform: translateY(-2px);
    border-color: var(--bb-primary);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.07);
}
.bb-contest-row__info { flex: 1; min-width: 0; }
.bb-contest-row__name { font-weight: 700; color: var(--bb-text-primary); }
.bb-contest-row__meta { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); margin-top: 2px; }
.bb-contest-row__right { display: flex; align-items: center; gap: var(--bb-space-3); flex-shrink: 0; }
.bb-contest-row__sep { color: var(--bb-gray-300); }
.bb-contest-row__arrow { color: var(--bb-gray-400); flex-shrink: 0; }

/* Hub contest components */
.bb-contest-info { flex: 1; min-width: 0; }
.bb-contest-name {
    font-weight: 600;
    color: var(--bb-text-primary);
    font-size: 1rem;
}
.bb-contest-meta {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    margin-top: 3px;
}
.bb-contest-right { display: flex; align-items: center; gap: var(--bb-space-3); flex-shrink: 0; }
.bb-contest-sep { color: var(--bb-gray-300); }
.bb-contest-arrow {
    color: var(--bb-gray-400);
    flex-shrink: 0;
    transition: color 0.2s ease;
}
.bb-contest-row:hover .bb-contest-arrow { color: var(--bb-primary); }

/* Contest results (division detail) */
.bb-contest-results-list { display: flex; flex-direction: column; }
.bb-contest-result-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    padding: var(--bb-space-3) 0;
    border-bottom: 1px solid var(--bb-gray-100);
}
.bb-contest-result-row:last-child { border-bottom: none; }
.bb-contest-result-year { font-weight: 800; color: var(--bb-primary); min-width: 50px; font-size: var(--bb-fs-sm); }
.bb-contest-result-name { font-weight: 600; color: var(--bb-text-primary); }
.bb-contest-result-info { flex: 1; min-width: 0; }
.bb-contest-result-winner { font-weight: 600; color: var(--bb-navy); }
.bb-contest-result-winner:hover { color: var(--bb-primary); }

.bb-recent-contests-section { }
.bb-recent-contests-section .bb-contests-list {
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* ==========================================================================
   33. SEASONS PAGE
   ========================================================================== */

.bb-seasons-list {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
}

.bb-season-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    padding: var(--bb-space-4);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    cursor: pointer;
    transition: border-color 0.15s;
}
.bb-season-row:hover { border-color: var(--bb-primary); }
.bb-season-row__left { flex: 1; min-width: 0; }
.bb-season-row__right { display: flex; align-items: center; gap: var(--bb-space-3); flex-shrink: 0; }

/* Same as .bb-country-card__name: an h2 card title that used to be a span, so it
   needs .bb-app scope to outrank `.bb-app h2` and keeps the span's zero margin
   and its place in the flex row. */
.bb-app .bb-season-year {
    margin: 0;
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-primary);
    min-width: 60px;
}
.bb-season-stats {
    display: flex;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
}
.bb-season-stat {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
}
.bb-season-arrow { color: var(--bb-gray-400); flex-shrink: 0; }
.bb-season-division { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

/*
 * 93 season rows at 124px each: 13,116px of a 15,231px page, for a year and
 * three counts.
 *
 * The row was written as a flex ROW - year and stats on the left, chevron on
 * the right - but it also carries .bb-content-card, which declares
 * flex-direction: column, so it has been a column at every width since. The
 * chevron therefore sat on a line of its own under the stats, 16px of arrow
 * costing a full row, and the stats had the whole 277px to themselves and
 * still wrapped to two lines at 14px.
 *
 * Not unpicking the class collision here: .bb-content-card is used across the
 * plugin and flipping it back would move desktop layouts this pass is not
 * measuring. The column is made deliberate instead, with the chevron lifted
 * out of the flow into the right margin where the row layout meant to put it.
 */
@media (max-width: 600px) {
    .bb-app .bb-season-row {
        position: relative;
        align-items: stretch;
        gap: 3px;
        padding: 11px 32px 11px 13px;
    }
    .bb-app .bb-season-row__right {
        position: absolute;
        right: 11px;
        top: 50%;
        transform: translateY(-50%);
    }
    .bb-app .bb-season-year { font-size: var(--bb-fs-lg); }
    .bb-app .bb-season-stats { gap: 2px 11px; }
    .bb-app .bb-season-stat { font-size: var(--bb-fs-xs); }
}

/* Season detail */
.bb-season-detail-header {
    margin-bottom: var(--bb-space-6);
}
.bb-season-detail-year-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
}
.bb-season-detail-year {
    font-size: var(--bb-fs-3xl);
    font-weight: 900;
    color: var(--bb-primary);
}
.bb-season-detail-stats {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-6);
    margin-top: var(--bb-space-4);
}
.bb-season-detail-stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Season Olympia card */
.bb-season-olympia-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    margin-bottom: var(--bb-space-6);
}
.bb-season-olympia-card__badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
}
.bb-season-olympia-card__body { padding: var(--bb-space-5); }
.bb-season-olympia-card__division {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-3) 0;
    border-bottom: 1px solid var(--bb-gray-100);
}
.bb-season-olympia-card__division:last-child { border-bottom: none; }
.bb-season-olympia-card__div-name {
    font-weight: 600;
    color: var(--bb-text-primary);
    min-width: 140px;
}
.bb-season-olympia-card__winner {
    font-weight: 700;
    color: var(--bb-navy);
}
.bb-season-olympia-card__winner:hover { color: var(--bb-primary); }
.bb-season-olympia-card__location {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-left: auto;
}

.bb-season-olympia-label {
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-muted);
}
.bb-season-olympia-name { font-weight: 700; color: var(--bb-text-primary); }
.bb-season-olympia-winner { font-weight: 600; color: var(--bb-navy); }
.bb-season-olympia-winner:hover { color: var(--bb-primary); }

/* ==========================================================================
   34. ROAD TO OLYMPIA PAGE
   ========================================================================== */

.bb-rto-summary {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-6);
}
.bb-rto-summary-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-full);
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    transition: all 0.15s;
    cursor: pointer;
}
.bb-rto-summary-chip:hover { border-color: var(--bb-primary); }
.bb-rto-summary-chip--full { border-color: var(--bb-success); background: var(--bb-success-light); }
.bb-rto-summary-div { font-weight: 700; color: var(--bb-text-primary); }
.bb-rto-summary-slots { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

.bb-rto-division-block {
    margin-bottom: var(--bb-space-8);
}
.bb-rto-division-header {
    margin-bottom: var(--bb-space-4);
}
.bb-rto-division-title-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    flex-wrap: wrap;
}
.bb-rto-division-name {
    font-size: var(--bb-fs-lg);
    font-weight: 800;
    color: var(--bb-text-primary);
}
.bb-rto-division-meta {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: var(--bb-space-1);
}
.bb-rto-division { font-size: var(--bb-fs-sm); color: var(--bb-text-muted); }
.bb-rto-slots-label { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
.bb-rto-year {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-primary);
}

/* Progress bar */
.bb-rto-progress-bar {
    height: 8px;
    background: var(--bb-gray-100);
    border-radius: 4px;
    overflow: hidden;
    margin-top: var(--bb-space-2);
}
.bb-rto-progress-fill {
    height: 100%;
    background: var(--bb-primary);
    border-radius: 4px;
    transition: width 0.4s ease;
}
.bb-rto-progress-fill--full { background: var(--bb-success); }

/* Table */
.bb-rto-table-wrap {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* Wave-1 white-bg: subtle resting shadow for definition on the white canvas. */
    box-shadow: var(--bb-shadow-sm);
}
.bb-rto-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}
.bb-rto-th {
    text-align: left;
    padding: 12px 16px;
    font-size: 11px;
    font-weight: 700;
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-bottom: 2px solid var(--bb-border);
    white-space: nowrap;
}
.bb-rto-th--rank   { width: 60px; text-align: center; }
.bb-rto-th--country { width: 100px; }
.bb-rto-th--points  { width: 80px; text-align: right; }
.bb-rto-th--wins    { width: 80px; text-align: right; }
.bb-rto-th--status  { width: 100px; text-align: center; }

.bb-rto-td {
    padding: 12px 16px;
    border-bottom: 1px solid var(--bb-border);
    color: var(--bb-text-secondary);
}
.bb-rto-td--rank   { text-align: center; font-weight: 700; }
.bb-rto-td--athlete { font-weight: 600; }
.bb-rto-td--country { white-space: nowrap; }
.bb-flag-img { display: inline-block; vertical-align: middle; margin-right: 4px; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0,0,0,.08); width: 20px; height: auto; } /* height:auto so odd ratios (np, ch, qa) are not cropped */
.bb-rto-td--points  { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
.bb-rto-td--wins    { text-align: right; font-variant-numeric: tabular-nums; }
.bb-rto-td--status  { text-align: center; }

.bb-rto-row {}
.bb-rto-row--qualified { background: rgba(69, 114, 63,0.04); }
.bb-rto-row--borderline { background: rgba(217, 139, 74,0.04); }
.bb-rto-rank { font-weight: 700; }
.bb-rto-rank--qualified { color: var(--bb-success); }
.bb-rto-athlete-link { color: var(--bb-navy); font-weight: 600; }
.bb-rto-athlete-link:hover { color: var(--bb-primary); }

.bb-rto-cutline-row {
    border-top: 2px dashed var(--bb-error);
    position: relative;
}
.bb-rto-cutline-label {
    position: absolute;
    top: -10px;
    left: 16px;
    background: var(--bb-surface);
    padding: 0 8px;
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    color: var(--bb-error);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* View tabs (Qualified / Season / Rules) */
.bb-view-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: var(--bb-space-4);
    border-bottom: 2px solid var(--bb-gray-100);
    padding-bottom: 0;
}
.bb-view-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    border: none;
    background: none;
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-text-secondary);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    transition: all 0.2s ease;
}
.bb-view-tab:hover { color: var(--bb-navy); }
.bb-view-tab--active {
    color: var(--bb-navy);
    border-bottom-color: var(--bb-navy);
}
.bb-view-tab svg { opacity: 0.6; }
.bb-view-tab--active svg { opacity: 1; }

/* Period badge */
.bb-rto-period-badge {
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-gray-100);
    border-radius: var(--bb-radius-md);
    padding: 10px 16px;
    margin-bottom: var(--bb-space-4);
    font-size: var(--bb-fs-sm);
}
.bb-rto-period-badge a { color: var(--bb-primary); }

/* Rules section */
.bb-rto-rules .bb-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-100);
    border-radius: var(--bb-radius-lg);
    padding: 24px;
}
.bb-rto-rules .bb-card-title {
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    color: var(--bb-navy);
    margin: 0 0 8px 0;
}
.bb-rto-rules h4 { font-size: var(--bb-fs-sm); font-weight: 700; color: var(--bb-navy); }
.bb-rto-rules-list {
    list-style: none;
    padding: 0;
    margin: 8px 0 0 0;
}
.bb-rto-rules-list li {
    padding: 6px 0 6px 20px;
    position: relative;
    font-size: var(--bb-fs-sm);
    line-height: 1.5;
}
.bb-rto-rules-list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 12px;
    width: 8px;
    height: 8px;
    background: var(--bb-primary);
    border-radius: 50%;
}
.bb-rto-table--compact th,
.bb-rto-table--compact td {
    padding: 6px 12px;
    font-size: var(--bb-fs-sm);
}

@media (max-width: 640px) {
    .bb-view-tabs { gap: 0; overflow-x: auto; }
    .bb-view-tab { padding: 8px 12px; font-size: 0.8rem; white-space: nowrap; }
    .bb-view-tab svg { display: none; }
    .bb-rto-rules .bb-card { padding: 16px; }
}

/* RTO CTA section (hub) */
.bb-rto-cta-section { }
.bb-rto-cta-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 32px;
    padding: 32px clamp(18px, 4.4vw, 36px);
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border-radius: var(--bb-radius-xl);
    border: 1px solid rgba(178, 58, 53, 0.2);
    color: white;
    text-decoration: none;
    transition: all var(--bb-transition-slow);
    position: relative;
    overflow: hidden;
}
.bb-rto-cta-card::before {
    content: '';
    position: absolute;
    top: -60%;
    right: -10%;
    width: 50%;
    height: 220%;
    background: rgba(255, 255, 255, 0.04);
    transform: rotate(-15deg);
    pointer-events: none;
}
.bb-rto-cta-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 32px rgba(178, 58, 53, 0.15);
    text-decoration: none;
    color: white;
}
.bb-rto-cta-content { flex: 1; }
.bb-rto-cta-title {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: white;
    margin-bottom: var(--bb-space-2);
}
.bb-rto-cta-description {
    font-size: var(--bb-fs-sm);
    color: rgba(255, 255, 255, 0.8);
    margin-bottom: var(--bb-space-4);
    line-height: 1.6;
}
.bb-rto-cta-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    color: white;
    background: rgba(178, 58, 53, 0.4);
    border: 1px solid rgba(178, 58, 53, 0.6);
    border-radius: var(--bb-radius-full);
    padding: 3px 10px;
    margin-bottom: var(--bb-space-3);
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.bb-rto-cta-badge::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    background: var(--bb-primary);
    border-radius: 50%;
    animation: bb-live-pulse 1.4s ease-in-out infinite;
}
@keyframes bb-live-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50% { opacity: 0.4; transform: scale(0.75); }
}
.bb-rto-cta-view-link {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    padding: 8px 18px;
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: var(--bb-radius-full);
    color: white;
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    transition: background var(--bb-transition), color var(--bb-transition), border-color var(--bb-transition);
    white-space: nowrap;
}
.bb-rto-cta-card:hover .bb-rto-cta-view-link {
    background: white;
    color: var(--bb-navy);
    border-color: white;
}
.bb-rto-cta-view-link svg {
    transition: transform var(--bb-transition);
}
.bb-rto-cta-card:hover .bb-rto-cta-view-link svg {
    transform: translateX(3px);
}
.bb-rto-cta-divisions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-top: var(--bb-space-3);
}
.bb-rto-cta-division {
    padding: 3px 10px;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: var(--bb-radius-full);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: rgba(255, 255, 255, 0.9);
}

/* ==========================================================================
   34b. HUB SECTION SEPARATION
   ========================================================================== */

/* All hub sections get consistent generous padding, no border-top dividers */
.bb-news-section,
.bb-rto-cta-section,
.bb-featured-section,
.bb-data-section,
.bb-divisions-section,
.bb-howit-section,
.bb-top-athletes-section,
.bb-recent-contests-section,
.bb-about-section,
.bb-seo-section,
.bb-faq-section {
    /*
     * Vertical padding is FLUID, was a flat var(--bb-space-16) = 60px at every
     * viewport. Two adjacent sections each contributed 60px, so every section
     * boundary was a 120px band of nothing - on a 390px screen that is a third of
     * the viewport height between one block of content and the next, and
     * test-workstream-z3-layout.mjs caught it as a 122px dead band.
     *
     * Same shape as the Phase 1 gutter rule, so DESKTOP IS UNCHANGED: at 1000px
     * and up 6vw already exceeds 60px and clamps to the original value. Only
     * narrow viewports move, down to 32px, which puts a section boundary at 64px.
     */
    /*
     * TOP ONLY, which is how claude-design does it: every prototype section is
     * `padding: clamp(...) 0 0`. Padding on both sides means each boundary is
     * the sum of two sections' padding, so the earlier fix could only ever halve
     * the symptom - at desktop this was still 60 + 60 = 120px of nothing between
     * one block and the next. One section owns one gap; the boundary is now the
     * value, not twice it.
     */
    padding: clamp(32px, 6vw, var(--bb-space-16)) 0 0;
    margin-bottom: 0;
    border-top: none;
}
/* The last section has no successor to provide the closing gap, so it keeps its
   own - otherwise the page ends flush against the footer. */
.bb-data-section:last-child,
.bb-divisions-section:last-child,
.bb-howit-section:last-child,
.bb-top-athletes-section:last-child,
.bb-recent-contests-section:last-child,
.bb-about-section:last-child,
.bb-seo-section:last-child,
.bb-faq-section:last-child {
    padding-bottom: clamp(32px, 6vw, var(--bb-space-16));
}

/* ==========================================================================
   QUALIFICATION METHOD BADGES (Road to Olympia)
   ========================================================================== */

/* Auto-Win: green - contest winner during qualifying period */
.bb-qual-badge--auto-win {
    background: rgba(69, 114, 63, 0.12);
    color: var(--bb-moss-dark);
    border: 1px solid rgba(69, 114, 63, 0.3);
}

/* Olympia Top 3: gold - top 3 at previous Olympia */
.bb-qual-badge--olympia-top3 {
    background: linear-gradient(135deg, rgba(217, 139, 74, 0.15), rgba(217, 139, 74, 0.08));
    color: var(--bb-amber-dark);
    border: 1px solid rgba(217, 139, 74, 0.4);
}

/* Points: blue - qualified via points standings */
.bb-qual-badge--points {
    background: rgba(69, 114, 63, 0.1);
    color: var(--bb-moss-dark);
    border: 1px solid rgba(69, 114, 63, 0.3);
}

/* 2+ Wins: green (stronger than auto-win) */
.bb-qual-badge--two-wins {
    background: rgba(69, 114, 63, 0.15);
    color: var(--bb-moss-dark);
    border: 1px solid rgba(69, 114, 63, 0.4);
}

/* Engine source indicator */
.bb-rto-engine-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(69, 114, 63, 0.07);
    border: 1px solid rgba(69, 114, 63, 0.2);
    border-radius: var(--bb-radius-full);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: var(--bb-moss-dark);
    margin-bottom: var(--bb-space-4);
}

/* Validation accuracy badge (page header) */
.bb-page-header-inner {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
}

.bb-rto-validation-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 12px;
    background: rgba(69, 114, 63, 0.08);
    border: 1px solid rgba(69, 114, 63, 0.25);
    border-radius: var(--bb-radius-full);
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    color: var(--bb-moss-dark);
    white-space: nowrap;
    flex-shrink: 0;
}

/* In-standings row highlight */
.bb-rto-row--in-standings {
    background: rgba(69, 114, 63, 0.03);
}

/* Alternating gray backgrounds create natural visual rhythm without borders */
.bb-data-section,
.bb-howit-section,
.bb-about-section,
.bb-seo-section {
    /*background: var(--bb-gray-50);*/
    /* Full-width bleed, matches container padding at each breakpoint */
    margin-left: calc(var(--bb-space-4) * -1);
    margin-right: calc(var(--bb-space-4) * -1);
    padding-left: var(--bb-space-4);
    padding-right: var(--bb-space-4);
}

@media (min-width: 640px) {
    .bb-data-section,
    .bb-howit-section,
    .bb-about-section,
    .bb-seo-section {
        margin-left: calc(var(--bb-space-6) * -1);
        margin-right: calc(var(--bb-space-6) * -1);
        padding-left: var(--bb-space-6);
        padding-right: var(--bb-space-6);
    }
}

/* First section after hero gets extra top breathing room */
.bb-news-section { padding-top: 3rem; }

/* ==========================================================================
   35. HUB PAGE COMPONENTS
   ========================================================================== */

/* Featured section */
.bb-featured-section {
    margin-top: calc(var(--bb-space-8) * -1);
    padding-top: 0 !important;
}
.bb-featured-card {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--bb-space-6);
    padding: var(--bb-space-8) var(--bb-space-10);
    background: linear-gradient(135deg, var(--bb-primary) 0%, var(--bb-primary-hover) 100%);
    border-radius: var(--bb-radius-2xl);
    box-shadow: var(--bb-shadow-lg), 0 0 0 1px rgba(0, 0, 0, 0.02);
    color: white;
    text-decoration: none;
    position: relative;
    overflow: hidden;
    transition: box-shadow var(--bb-transition-slow);
}
.bb-featured-card::before {
    content: '';
    position: absolute;
    top: -50%;
    right: -20%;
    width: 60%;
    height: 200%;
    background: rgba(255, 255, 255, 0.08);
    transform: rotate(-15deg);
    pointer-events: none;
}
.bb-featured-card:hover {
    box-shadow: var(--bb-shadow-lg);
}
.bb-featured-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: 16px;
    flex-shrink: 0;
    transition: transform 250ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.bb-featured-icon svg,
.bb-featured-icon img {
    width: 32px;
    height: 32px;
    color: white;
    stroke-width: 1.5;
}
.bb-featured-card:hover .bb-featured-icon {
    transform: scale(1.1) rotate(-5deg);
}
.bb-featured-badge {
    display: inline-block;
    padding: var(--bb-space-1) var(--bb-space-3);
    background: rgba(255, 255, 255, 0.25);
    border-radius: var(--bb-radius-sm);
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    margin-bottom: var(--bb-space-3);
    color: white;
}
.bb-featured-content { flex: 1; position: relative; z-index: 1; }
.bb-featured-title {
    font-family: var(--bb-font-heading);
    font-size: clamp(var(--bb-fs-lg), 3vw, var(--bb-fs-3xl));
    font-weight: 700;
    letter-spacing: -0.02em;
    margin: 0 0 var(--bb-space-2);
    line-height: 1.15;
    color: white;
}
.bb-featured-description {
    font-size: var(--bb-fs-base);
    line-height: 1.6;
    margin: 0 0 var(--bb-space-5);
    max-width: 400px;
    color: rgba(255, 255, 255, 0.9);
}
.bb-featured-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    padding: var(--bb-space-3) var(--bb-space-5);
    background: var(--bb-surface);
    color: var(--bb-primary-hover);
    border-radius: var(--bb-radius-lg);
    font-weight: 600;
    font-size: var(--bb-fs-sm);
    transition: all var(--bb-transition);
}
.bb-featured-card:hover .bb-featured-cta {
    background: var(--bb-gray-50);
    gap: var(--bb-space-3);
}
.bb-featured-cta svg {
    transition: transform var(--bb-transition);
}
.bb-featured-card:hover .bb-featured-cta svg {
    transform: translateX(3px);
}

@media (max-width: 768px) {
    .bb-rto-cta-card {
        flex-direction: column;
        align-items: flex-start;
        padding: 24px;
        gap: 16px;
    }
    .bb-rto-cta-divisions { display: none; }
}
@media (max-width: 768px) {
    .bb-featured-card {
        grid-template-columns: 1fr;
        text-align: center;
        padding: var(--bb-space-6);
    }
    .bb-featured-icon { margin: 0 auto var(--bb-space-3); }
    .bb-featured-title { font-size: var(--bb-fs-xl); }
}

/* Data grid (hub explore section) */
.bb-data-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--bb-space-4);
}
.bb-data-card {
    display: flex;
    flex-direction: column;
    padding: var(--bb-space-6);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    /* Static data card: hairline only, shadow returns on :hover below. */
    box-shadow: none;
    transition: all 0.2s ease;
}
.bb-data-card:hover {
    transform: translateY(-2px);
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
}
.bb-data-title {
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin-top: var(--bb-space-3);
}
.bb-data-description {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    line-height: 1.5;
    margin-top: var(--bb-space-2);
}
.bb-data-link {
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-primary);
    /*
     * auto, not a fixed space-8, so every "Explore" in a row sits on the same line.
     * The cards are equal-height flex columns, but a fixed top margin measures from the
     * end of the description, so a one-line card floated its link up: "Divisions" sat
     * 21px above Contests, Rankings and Competition Schedule, whose descriptions wrap to
     * two lines. auto pushes the link to the bottom of the column instead, and
     * padding-top keeps a minimum gap when the description is tall. Used only inside
     * .bb-data-card, which is always display:flex/column.
     */
    margin-top: auto;
    padding-top: var(--bb-space-3);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: gap 0.2s ease;
}
.bb-data-card:hover .bb-data-link { gap: 8px; }
@media (max-width: 768px) {
    .bb-data-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
    .bb-data-grid { grid-template-columns: 1fr; }
}

/* Weighted feature grid: flagship surfaces (Athlete Directory + Mr. Olympia)
   span two columns and carry a heavier surface so the front door stops rendering
   the flagship and a minor tool as identical squares. */
.bb-data-grid--weighted .bb-data-card--large {
    grid-column: span 2;
    background: linear-gradient(180deg, var(--bb-primary-light) 0%, var(--bb-surface) 55%);
    border-color: var(--bb-gray-300, var(--bb-gray-200));
}
.bb-data-grid--weighted .bb-data-card--large .bb-data-title { font-size: var(--bb-fs-lg); }
.bb-data-grid--weighted .bb-data-card--large .bb-data-description { font-size: var(--bb-fs-base); }
@media (max-width: 768px) {
    /* On the 2-col grid the large tiles already fill the row; keep them full-width. */
    .bb-data-grid--weighted .bb-data-card--large { grid-column: span 2; }
}
@media (max-width: 480px) {
    .bb-data-grid--weighted .bb-data-card--large { grid-column: span 1; }
}

/* Hub section empty / error states (greatest + recent contests bands) so the
   landing page can never render a silent void. */
.bb-hub-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-6);
    text-align: center;
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-border, var(--bb-gray-200));
    border-radius: var(--bb-radius-lg);
    color: var(--bb-text-secondary, var(--bb-text-muted));
}
.bb-hub-state p { margin: 0; font-size: var(--bb-fs-sm); }
.bb-hub-state--error { border-color: var(--bb-gray-300, var(--bb-gray-200)); }

/* CTA row */
.bb-cta-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-4);
}

/* Steps grid (how it works) */
.bb-howit-section { padding: var(--bb-space-20) 0; }
.bb-steps-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--bb-space-6);
    max-width: 900px;
    margin: 0 auto;
    position: relative;
}
@media (max-width: 768px) { .bb-steps-grid { grid-template-columns: 1fr; } }
.bb-step {
    text-align: center;
    position: relative;
    z-index: 1;
}

.bb-step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 88px;
    height: 88px;
    background: var(--bb-gray-50);
    border: 2px solid var(--bb-primary);
    border-radius: var(--bb-radius-xl);
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-2xl);
    font-weight: 700;
    color: var(--bb-primary-hover);
    margin-bottom: var(--bb-space-5);
    transition: all var(--bb-transition-slow);
}
.bb-step-title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
    font-weight: 600;
    color: var(--bb-gray-800);
    margin: 0 0 var(--bb-space-2);
}
.bb-step-description {
    font-size: var(--bb-fs-sm);
    color: var(--bb-gray-400);
    line-height: 1.6;
    margin: 0;
    max-width: 240px;
    margin-left: auto;
    margin-right: auto;
}

/* News section (hub) */
.bb-news-section { }
.bb-news-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
    gap: 1.5rem;
}
.bb-news-grid-more { margin-top: var(--bb-space-4); }

.bb-news-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md, 10px);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: transform 0.2s, box-shadow 0.2s;
}
.bb-news-card:hover {
    border-color: var(--bb-primary);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
    transform: translateY(-2px);
}

.bb-news-thumb {
    width: 100%;
    aspect-ratio: 16/9;
    background: var(--bb-gray-100);
    overflow: hidden;
}

/*
 * The image, not the box. object-fit was declared on .bb-news-thumb, which is a div -
 * the property only applies to REPLACED elements, so it did nothing there and no rule
 * targeted the <img> at all. The image therefore rendered at its natural size inside
 * the slot: measured on the live hub, a 300x169 thumbnail in a 395x222 box, leaving a
 * 95px gap down the right of every card. It read like the images had failed to load.
 */
.bb-news-thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.bb-news-thumb-fallback {
    width: 100%;
    aspect-ratio: 16/9;
    background: var(--bb-gray-100);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bb-gray-400);
    font-size: 2rem;
}
.bb-news-body { padding: var(--bb-space-4) var(--bb-space-5) var(--bb-space-5); flex: 1; display: flex; flex-direction: column; gap: var(--bb-space-2); }
.bb-news-title { font-size: var(--bb-fs-base); font-weight: 700; color: var(--bb-text-primary); line-height: 1.35; }
.bb-news-excerpt { font-size: var(--bb-fs-sm); color: var(--bb-text-secondary); line-height: 1.5; }
.bb-news-date { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
.bb-news-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: var(--bb-space-8);
    padding-top: var(--bb-space-3);
}
.bb-news-source-link { font-size: var(--bb-fs-sm); font-weight: 600; color: var(--bb-primary); text-decoration: none; transition: color var(--bb-transition); }
.bb-news-source-link:hover { color: var(--bb-text-secondary); }

/* Welcome back / personal hub */
.bb-hub-personal { margin-bottom: 32px; }
.bb-welcome-back {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    margin-bottom: var(--bb-space-6);
}
.bb-hub-welcome {
    /* POLISH PASS 3: warm ink/espresso band (was navy->electric), matching the
       visitor hero and Olympia widget band family. */
    background: linear-gradient(135deg, #1d1916 0%, #2b211a 62%, #3c2c21 100%);
    border-radius: var(--bb-radius-xl, 16px);
    padding: 24px clamp(18px, 4.4vw, 32px);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 20px;
    position: relative;
    overflow: hidden;
}
.bb-hub-welcome-left {
    min-width: 0;
    position: relative;
    z-index: 1;
}
.bb-hub-welcome-title {
    font-family: var(--bb-font-heading, 'Archivo', sans-serif);
    font-size: 1.5rem;
    font-weight: 700;
    /* !important defeats the theme's `h1 { color: ... !important }` rule which
       otherwise forces a dark heading colour onto this navy panel (dark-on-dark).
       Same pattern as .bb-profile-name at the top of this file. */
    color: #ffffff !important;
    margin: 0 0 4px;
    line-height: 1.3;
}
.bb-hub-welcome-sub {
    font-size: 0.875rem;
    /* Raised from 0.6 to 0.85 alpha for WCAG AA contrast on the navy panel. */
    color: rgba(255, 255, 255, 0.85);
    margin: 0;
    max-width: 420px;
    line-height: 1.4;
}
.bb-hub-welcome-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.7);
    letter-spacing: 0.3px;
    margin-bottom: 8px;
}
.bb-hub-welcome-actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
    position: relative;
    z-index: 1;
}

/* Hub feed */
.bb-hub-feed {
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg, 12px);
    padding: 20px 24px;
}
.bb-hub-feed-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
}
.bb-hub-feed-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--bb-font-heading, 'Archivo', sans-serif);
    font-size: 1rem;
    font-weight: 700;
    color: var(--bb-text-primary);
    margin: 0;
}
.bb-hub-feed-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--bb-primary, #b23a35);
    padding: 6px 12px;
    border-radius: var(--bb-radius-sm, 4px);
    transition: background 0.15s ease;
}
.bb-hub-feed-dashboard {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--bb-primary, #b23a35);
    text-decoration: none;
    margin-left: auto;
}
.bb-hub-feed-following {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-top: 14px;
    margin-top: 4px;
    border-top: 1px solid var(--bb-gray-200);
    flex-wrap: wrap;
}
.bb-hub-feed-following-count {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.8125rem;
    color: var(--bb-text-secondary);
}
.bb-hub-feed-following-label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--bb-text-secondary);
}
.bb-hub-feed-manage {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--bb-text-secondary);
    text-decoration: none;
}
.bb-hub-feed-list { }
.bb-hub-feed-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--bb-gray-100, #f3f4f6);
}
.bb-hub-feed-item:last-child { border-bottom: none; }
.bb-hub-feed-item:hover { background: var(--bb-gray-50); }
.bb-hub-feed-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    margin-top: 2px;
}
.bb-hub-feed-content { flex: 1; min-width: 0; }
.bb-hub-feed-msg {
    font-size: 0.875rem;
    color: var(--bb-text-primary);
    line-height: 1.4;
    text-decoration: none;
    display: block;
}
.bb-hub-feed-date {
    font-size: 0.75rem;
    color: var(--bb-text-muted);
    margin-top: 2px;
    display: block;
}
.bb-hub-feed-badge { margin-left: var(--bb-space-2); }
.bb-hub-feed-actions {
    padding-top: 8px;
    text-align: center;
}
.bb-hub-feed-empty {
    text-align: center;
    padding: 24px 16px;
}
.bb-hub-feed-empty-text {
    font-size: 0.875rem;
    color: var(--bb-text-secondary);
    margin: 0 0 16px;
}
.bb-hub-feed-empty-links {
    display: flex;
    gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
}
.bb-hub-feed-skeleton {
    padding: 4px 0;
}

/* Feed icon types */
[class*="bb-feed-icon-"] {
    width: 32px; height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    font-size: var(--bb-fs-sm);
    flex-shrink: 0;
}

/* ==========================================================================
   36. ATHLETE PROFILE PAGE
   ========================================================================== */

.bb-athlete-profile-page { }
.bb-athlete-profile { }
.bb-athlete-profile-skeleton {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-6);
}

/* Profile header inner */
.bb-profile-header-inner {
    display: flex;
    align-items: flex-start;
    gap: var(--bb-space-6);
    flex-wrap: wrap;
    position: relative;
    z-index: 1;
}

/* Profile photo */
.bb-profile-photo {
    /* 160, was 200. The claude-design avatar is ~150px, and the 40px mattered:
       with the at-a-glance card at its designed 320px width, the name column had
       510px against the 515px "RONNIE COLEMAN" needs at the shared 64px title
       size - measured, and the reason the H1 wrapped to two lines. The title
       scale is enforced page-wide by test-page-title-scale.mjs, so the photo
       gives, not the type. Bone-toned ring per the prototype's avatar. */
    width: 160px; height: 160px;
    flex-shrink: 0;
    border-radius: 50%;
    overflow: hidden;
    border: 3px solid rgba(250, 246, 239, 0.35);
}
.bb-profile-photo-img {
    width: 100%; height: 100%;
    object-fit: cover;
}
.bb-profile-photo-fallback {
    width: 100%; height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--bb-navy-mid), var(--bb-navy));
    color: white;
    font-size: 3rem;
    font-weight: 800;
}

/* Profile details */
.bb-profile-details {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-4);
    margin-top: var(--bb-space-4);
}
.bb-profile-detail {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.bb-profile-detail-label,
.bb-profile-detail__label {
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    /* Bone at 68%, was white at 50%. On PURE ink 50% white computes to 5.14:1 and
       looks safe, but the profile header is ink plus a 5% bone wash and two warm
       radial glows, and that lighter base drops light text to 4.43:1 - under the
       floor. Measuring against the composited background rather than the token is
       the only way to see it. Bone rather than white so the label sits on the
       palette's own axis. */
    color: rgba(250, 246, 239, 0.68);
}
.bb-profile-detail-value,
.bb-profile-detail__value {
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: white;
}
/* When the detail value is a link (the division on the profile hero), the base
   .bb-app a accent (oxblood) would be low-contrast on the dark band. Specificity
   (0,2,0) beats .bb-app a (0,1,1) so no !important is needed.

   --bb-amber-on-dark, NOT --bb-gold-champion. The gold token was split into an
   on-light and an on-dark pair, and --bb-gold-champion took the ON-LIGHT value
   (#8f5a1e) because that is what most of its consumers sit on. This one sits on
   the dark hero, so it followed the split into 2.93:1. #d98b4a on ink is 6.21:1.
   The comment here used to claim ~10:1 "on the navy hero" - measured when the
   band was navy, and left behind when it was warmed to ink. */
.bb-profile-detail-value.bb-link,
.bb-profile-detail__value.bb-link {
    color: var(--bb-amber-on-dark);
    text-decoration: underline;
    text-decoration-color: rgba(217, 139, 74, 0.45);
    text-underline-offset: 2px;
}
.bb-profile-detail-value.bb-link:hover,
.bb-profile-detail__value.bb-link:hover {
    color: var(--bb-amber-on-dark);
    text-decoration-color: var(--bb-amber-on-dark);
}

/*
 * Social links sit INSIDE .bb-profile-detail-value rather than being it, so the
 * .bb-profile-detail-value.bb-link rule above cannot reach them and they would
 * inherit the plain white value colour with no affordance that they are links.
 * Same amber-on-dark treatment, measured at 6.21:1 on ink.
 *
 * Wraps rather than scrolls: an athlete can carry three platforms and the hero
 * band is narrow at 320px.
 */
.bb-app .bb-profile-socials {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-1) var(--bb-space-3);
    align-items: center;
}
.bb-app .bb-profile-social-link {
    color: var(--bb-amber-on-dark);
    text-decoration: underline;
    text-decoration-color: rgba(217, 139, 74, 0.45);
    text-underline-offset: 2px;
    /* Meets --bb-touch-min without stretching the hero band: the row is short
       enough that padding alone would not reach 44px.
       min-width matters as much as min-height here: the X label is one character
       and measured 10px wide, a 10x44 tap target on a phone. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--bb-touch-min);
    min-width: var(--bb-touch-min);
}
.bb-app .bb-profile-social-link:hover,
.bb-app .bb-profile-social-link:focus-visible {
    color: var(--bb-amber-on-dark);
    text-decoration-color: var(--bb-amber-on-dark);
}

.bb-profile-status { margin-top: var(--bb-space-3); }

/* Career at a Glance: hero right column, per claude-design.
   Was a dark translucent panel of label:value rows; the prototype sets it as a
   LIGHT raised card sitting on the dark hero - tint header band reading
   AT A GLANCE, white body, and a grid of bordered stat cells with large mono
   figures. The light card is the one high-contrast surface in the hero, which
   is exactly why the design uses it: the career numbers are the answer the
   page exists to give.
   Lives inside .bb-profile-header-inner (flex row: photo + info + glance).
   Wider than the old 200px because three cells sit abreast. */
.bb-profile-glance {
    flex: 0 0 320px;
    width: 320px;
    align-self: start;
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
    box-shadow: var(--bb-shadow);
    padding: 0;
    overflow: hidden;
    position: relative;
    z-index: 1;
}
.bb-profile-glance-title {
    display: block;
    background: var(--bb-tint, #f0e9dc);
    border-bottom: 1px solid var(--bb-border);
    padding: 10px 16px;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs, 0.6875rem);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-ink);
    margin-bottom: 0;
}
.bb-profile-glance-list {
    display: grid;
    /* auto-fit at a 92px floor, not a fixed three columns: at the designed 320px
       panel this still yields three across ((320-24-16)/3 = 93px), but when the
       panel goes full-width on a 320px viewport - or a cell carries the widest
       value the template emits, the nine-character "1975-2021" lifespan - the
       row count adapts instead of the figure clipping. Measured: fixed 3-col at
       320px produced exactly one clipped cell. */
    grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
    gap: 8px;
    margin: 0;
    padding: 12px;
}
/* Each fact is its own bordered cell: label over a large mono figure.
   Padding is deliberately tight: at a 320px panel the cell interior is ~70px,
   and the widest value the template now emits is seven mono characters
   ("1990–07"), sized to fit that interior on one line. */
.bb-profile-glance-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
    padding: 8px 10px;
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-border-soft, var(--bb-border));
    border-radius: var(--bb-radius-sm);
    min-width: 0;
}
.bb-profile-glance-label {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs, 0.6875rem);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-warm-grey, #6b6259);
    margin: 0;
}
.bb-profile-glance-value {
    font-size: 1rem;
    font-weight: 500;
    color: var(--bb-ink);
    margin: 0;
    text-align: left;
    line-height: 1.25;
    font-variant-numeric: tabular-nums;
    /* One line, always: the template emits panel-only compact forms ("5'11\"",
       "287 lb", "1990–07") precisely so no cell value ever needs to wrap, and a
       wrapped figure was what made every row a different height before. */
    white-space: nowrap;
}
.bb-profile-glance-value--gold {
    /* Wins in oxblood, as the prototype sets them: the one figure the panel
       exists to surface. --bb-accent (#b23a35) on white is 5.5:1. The old
       amber was an on-dark colour for the panel this no longer is. */
    color: var(--bb-accent);
    font-weight: 600;
}
@media (max-width: 900px) {
    .bb-profile-glance {
        flex-basis: 100%;
        width: 100%;
    }
}

/* Profile content area */
.bb-profile-content {
    display: grid;
    grid-template-columns: 1fr 320px;
    gap: var(--bb-space-6);
    align-items: start;
}
@media (max-width: 900px) {
    .bb-profile-content { grid-template-columns: 1fr; }
}

.bb-profile-section {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
}
.bb-profile-section--results { }
.bb-profile-section--divisions { }

.bb-bio-text {
    font-size: var(--bb-fs-base);
    line-height: 1.7;
    color: var(--bb-gray-600);
    max-width: 800px;
}

.bb-profile-meta-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-sm);
    color: rgba(255,255,255,0.7);
}

/* Profile hero variant (athletes/detail.php) */
.bb-profile-hero {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border-radius: var(--bb-radius-lg);
    padding: 28px clamp(18px, 4.4vw, 32px);
    margin-bottom: 24px;
    position: relative;
    overflow: hidden;
}
.bb-profile-hero--skeleton { min-height: 200px; }
.bb-profile-hero::before {
    content: '';
    position: absolute;
    top: -50%; right: -10%;
    width: 300px; height: 300px;
    background: radial-gradient(circle, rgba(178, 58, 53,0.1) 0%, transparent 70%);
    border-radius: 50%;
    pointer-events: none;
}
.bb-profile-hero__avatar {
    width: 120px; height: 120px;
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    flex-shrink: 0;
    border: 2px solid rgba(255,255,255,0.2);
}
.bb-profile-hero__img {
    width: 100%; height: 100%;
    object-fit: cover;
    background: rgba(255,255,255,0.1);
}
.bb-profile-hero__img-placeholder {
    width: 100%; height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,255,255,0.1);
    color: rgba(255,255,255,0.4);
    font-size: 3rem;
}
.bb-profile-hero__info {
    display: flex;
    align-items: flex-start;
    gap: var(--bb-space-5);
    flex-wrap: wrap;
    position: relative;
    z-index: 1;
}
.bb-profile-hero__details { flex: 1; min-width: 200px; }
.bb-profile-hero__name {
    font-size: var(--bb-fs-2xl);
    font-weight: 800;
    color: white;
    margin-bottom: var(--bb-space-2);
}
.bb-profile-hero__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-3);
    font-size: var(--bb-fs-sm);
    color: rgba(255,255,255,0.7);
}

@media (max-width: 640px) {
    .bb-profile-photo { width: 120px; height: 120px; }
    .bb-profile-header-inner { flex-direction: column; align-items: center; text-align: center; }
    .bb-profile-details { justify-content: center; }
}

/* ==========================================================================
   37. ATHLETE DIRECTORY PAGE
   ========================================================================== */

.bb-directory-container { }
.bb-directory-filters-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-4);
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    margin-bottom: var(--bb-space-6);
}
.bb-directory-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--bb-space-12) var(--bb-space-6);
    color: var(--bb-gray-400);
}
.bb-directory-error {
    background: var(--bb-error-light);
    border: 1px solid rgba(143, 36, 32,0.2);
    border-radius: var(--bb-radius);
    padding: var(--bb-space-4);
    text-align: center;
    color: var(--bb-error);
    margin-bottom: var(--bb-space-4);
}

/* Athletes grid (countries/divisions detail) */
.bb-athlete-grid {
    display: grid;
    /*
     * 260, not 220. At 220 this gave five 226px columns and a 192px meta row,
     * which fits "Men's Open Bodybuilding" (162px) but not the longer division
     * names - 22 badges hung outside their card on /countries/united-states/.
     * At 260 the grid resolves to four columns with roughly 255px of meta, and
     * every current division name fits. The truncation below is the backstop
     * for narrower viewports, not the fix.
     */
    grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
    gap: var(--bb-space-4);
}
/* A nowrap badge in a shrinkable flex parent will always spill given a long
   enough label. Truncate rather than let it cross the card boundary. */
.bb-app .bb-athlete-card__meta,
.bb-app .bb-athlete-card__info {
    min-width: 0;
    max-width: 100%;
}
.bb-app .bb-compare-selected-meta,
.bb-app .bb-compare-selected-info { min-width: 0; max-width: 100%; }
.bb-app .bb-compare-selected-meta .bb-badge,
.bb-app .bb-athlete-card__meta .bb-badge,
.bb-app .bb-athlete-card__name {
    display: inline-block;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

/* Athlete card sub-components (BEM variant) */
.bb-athlete-card--link { cursor: pointer; text-decoration: none; color: inherit; display: flex; }
.bb-athlete-card__avatar {
    width: 100%;
    aspect-ratio: 3/4;
    overflow: hidden;
    flex-shrink: 0;
}
.bb-athlete-card__img {
    width: 100%; height: 100%;
    object-fit: cover;
    background: var(--bb-gray-100);
}
.bb-athlete-card__img-placeholder {
    width: 100%;
    aspect-ratio: 3/4;
    background: var(--bb-gray-100);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bb-gray-400);
    font-size: 3rem;
}
.bb-athlete-card__body {
    padding: var(--bb-space-4);
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
}
.bb-athlete-card__name { display: block; font-size: var(--bb-fs-base); font-weight: 700; color: var(--bb-text-primary); }
.bb-athlete-card__country { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
.bb-athlete-card__meta {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: auto;
}
.bb-athlete-card__stats { display: flex; gap: var(--bb-space-3); margin-top: auto; }

/*
 * The poster card lies down on a phone.
 *
 * The grid resolves to one column below about 600px, so each athlete got a
 * full-width 3:4 portrait with the name underneath: measured 565px per card at
 * 375px, 24 cards, 13,556px of a 19,323px page on /countries/us/ and 12,752px
 * on /divisions/classic-physique/. A phone screen held one and a half athletes.
 *
 * It also explains a result that looked impossible: /countries/us/ grew as the
 * viewport widened (19,331 / 19,790 / 20,297px at 375 / 390 / 414). One column
 * that never becomes two means a wider screen makes the portrait wider, and a
 * 3:4 portrait that gets wider gets taller.
 *
 * A thumbnail beside the text instead of a poster above it. The photo is still
 * there - it is what makes the list scannable without reading - it just stops
 * being the whole card.
 */
@media (max-width: 600px) {
    .bb-app .bb-athlete-grid { gap: 8px; }
    .bb-app .bb-athlete-card--link {
        flex-direction: row;
        align-items: stretch;
    }
    .bb-app .bb-athlete-card--link .bb-athlete-card__avatar,
    .bb-app .bb-athlete-card--link .bb-athlete-card__img-placeholder {
        width: 84px;
    }
    .bb-app .bb-athlete-card--link .bb-athlete-card__img-placeholder {
        font-size: 1.5rem;
    }
    .bb-app .bb-athlete-card--link .bb-athlete-card__body {
        padding: 9px 12px;
        gap: 3px;
        justify-content: center;
    }
    /* `margin-top: auto` pushed these to the bottom of a tall poster. In a row
       card there is no spare height to push into, and the auto margin only
       separates the name from its own stats. */
    .bb-app .bb-athlete-card--link .bb-athlete-card__meta,
    .bb-app .bb-athlete-card--link .bb-athlete-card__stats {
        margin-top: 0;
    }
    /*
     * The meta row holds a division badge and a status badge, and in a 267px
     * text column "Men's Open Bodybuilding" plus "Retired" does not fit: the
     * status badge was clipped mid-word by the card's own overflow, so it read
     * as "Retire" with no scrollbar and no document overflow to find it by.
     *
     * Wrapping rather than truncating. The badges already carry nowrap and an
     * ellipsis, so the other option was a division name cut to "Men's Open
     * Bodybuil…", and shortening the label a reader came for to save 20px on a
     * card that just lost 450 is the wrong trade. Short division names still
     * keep both badges on one line.
     */
    .bb-app .bb-athlete-card--link .bb-athlete-card__meta {
        flex-wrap: wrap;
        gap: 4px 6px;
    }
}
.bb-athlete-card__stat { display: flex; flex-direction: column; gap: 1px; }
.bb-athlete-card__stat-lbl { font-size: var(--bb-fs-2xs); color: var(--bb-text-muted); text-transform: uppercase; }
.bb-athlete-card__stat-val { font-size: var(--bb-fs-sm); font-weight: 700; color: var(--bb-text-primary); }
.bb-athlete-card__stat-val--accent { color: var(--bb-primary); }
.bb-athlete-card__wins {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: var(--bb-accent);
}

/* Hub athlete components */
.bb-athlete-avatar {
    width: 48px; height: 48px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--bb-gray-100);
}
.bb-athlete-photo {
    width: 48px; height: 48px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    object-fit: cover;
    background: var(--bb-gray-100);
}
.bb-athlete-initials {
    width: 100%; height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bb-navy);
    color: white;
    font-size: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}
.bb-athlete-info { flex: 1; min-width: 0; }
.bb-athlete-name {
    font-weight: 700;
    color: var(--bb-text-primary);
    font-size: var(--bb-fs-sm);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bb-athlete-meta {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin-top: 2px;
    flex-wrap: wrap;
}
.bb-athlete-country { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
.bb-athlete-rank {
    font-size: var(--bb-fs-sm);
    font-weight: 800;
    color: var(--bb-primary);
    min-width: 28px;
    flex-shrink: 0;
}
.bb-athlete-wins {
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: var(--bb-primary);
    margin-top: 3px;
    display: block;
}
.bb-athlete-link { color: var(--bb-text-primary); font-weight: inherit; min-height: 24px; } /* WCAG 2.2 target size: measured 23px */
.bb-athlete-link:hover { color: var(--bb-primary); }
.bb-athlete-row {
    transition: background var(--bb-transition);
    cursor: pointer;
}
.bb-athlete-row:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: -2px;
}
/* Legacy non-table usage (flex layout) */
div.bb-athlete-row {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-3) 0;
    border-bottom: 1px solid var(--bb-gray-100);
}
div.bb-athlete-row:last-child { border-bottom: none; }

.bb-card-name { font-weight: 700; color: var(--bb-text-primary); min-width: 180px; }
.bb-wsm-winner { background: rgba(217, 139, 74,0.04); }

/* Compact directory filters */
.bb-cd-search { flex: 1; min-width: 200px; }
.bb-cd-division { min-width: 160px; }
.bb-cd-gender { min-width: 120px; }
.bb-cd-sort { min-width: 160px; }

/* ==========================================================================
   UNIFIED DESIGN SYSTEM
   New canonical classes for filter toolbars, content grids, cards, tables,
   pagination, empty states, and skeleton loaders. These classes coexist with
   the legacy bb-filter-bar / bb-filter-tab / bb-contest-grid etc.; the old
   classes are kept intact for backward compatibility while templates migrate.
   ========================================================================== */

/* --------------------------------------------------------------------------
   UDS-1. UNIFIED TOOLBAR  (.bb-toolbar)
   Replaces: .bb-filter-bar, .bb-filters-bar, .bb-directory-filters-row,
             .bb-contests-filters, .bb-arnold-filters
   -------------------------------------------------------------------------- */

.bb-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}

/* Sticky variant */
.bb-toolbar--sticky {
    position: sticky;
    top: 0;
    z-index: 10;
}

/* --------------------------------------------------------------------------
   UDS-1a. TOOLBAR SEARCH  (.bb-toolbar-search)
   Replaces: .bb-search-box + .bb-search-input / .bb-filter-input patterns
   -------------------------------------------------------------------------- */

.bb-toolbar-search {
    position: relative;
    flex: 1;
    min-width: 220px;
}

.bb-toolbar-search__icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bb-gray-400);
    pointer-events: none;
    z-index: 1;
    width: 16px;
    height: 16px;
}

.bb-toolbar-search__input {
    display: block;
    width: 100%;
    padding: 10px 36px 10px 38px;
    font-family: var(--bb-font-body);
    font-size: var(--bb-fs-sm);
    color: var(--bb-gray-800);
    background: var(--bb-surface);
    border: 2px solid var(--bb-border);
    border-radius: var(--bb-radius);
    outline: none;
    min-height: 44px;
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-toolbar-search__input::placeholder {
    color: var(--bb-gray-400);
}

.bb-toolbar-search__input:hover:not(:focus) {
    border-color: var(--bb-border-strong);
}

.bb-toolbar-search__input:focus {
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
}

.bb-toolbar-search__clear {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    background: var(--bb-gray-200);
    border: none;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 13px;
    color: var(--bb-gray-600);
    line-height: 1;
    padding: 0;
    transition: background var(--bb-transition), color var(--bb-transition);
}

.bb-toolbar-search__clear:hover {
    background: var(--bb-gray-300);
    color: var(--bb-gray-800);
}

/* --------------------------------------------------------------------------
   UDS-1b. TOOLBAR FILTER  (.bb-toolbar-filter)
   Replaces: .bb-filter-group + .bb-filter-label + .bb-filter-select pattern
   -------------------------------------------------------------------------- */

.bb-toolbar-filter {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-1);
    min-width: 140px;
}

.bb-toolbar-filter__label {
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
}

.bb-toolbar-filter__select {
    display: block;
    width: 100%;
    padding: 9px 32px 9px 12px;
    font-family: var(--bb-font-body);
    font-size: var(--bb-fs-sm);
    font-weight: 500;
    color: var(--bb-gray-800);
    background: var(--bb-surface);
    border: 2px solid var(--bb-border);
    border-radius: var(--bb-radius);
    outline: none;
    cursor: pointer;
    min-height: 44px;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b95a5' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 12px;
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-toolbar-filter__select:hover:not(:focus) {
    border-color: var(--bb-border-strong);
}

.bb-toolbar-filter__select:focus {
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
}

/* --------------------------------------------------------------------------
   UDS-1c. TOOLBAR TABS  (.bb-toolbar-tabs / .bb-toolbar-tab)
   Replaces: .bb-filter-tabs/.bb-filter-tab, .bb-tabs/.bb-tab,
             .bb-division-filter/.bb-filter-btn patterns
   Pill-style tabs that sit inside or alongside the toolbar.
   -------------------------------------------------------------------------- */

.bb-toolbar-tabs {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
    border-bottom: 2px solid var(--bb-border);
    margin-bottom: 20px;
    padding: 0;
}

.bb-toolbar-tab {
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    border-radius: 0;
    padding: 10px 18px;
    background: none;
    font-family: var(--bb-font-body);
    font-size: 14px;
    font-weight: 600;
    color: var(--bb-text-muted);
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.15s;
}

.bb-toolbar-tab:hover {
    color: var(--bb-text-primary);
    border-color: transparent;
    background: none;
}

.bb-toolbar-tab--active,
.bb-toolbar-tab--active:hover {
    color: var(--bb-primary);
    border-bottom-color: var(--bb-primary);
    background: none;
}

.bb-toolbar-tab:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}

/* Optional count badge inside a tab */
.bb-toolbar-tab__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    background: var(--bb-gray-300);
    color: var(--bb-gray-700);
    border-radius: 9px;
    transition: background var(--bb-transition), color var(--bb-transition);
}

.bb-toolbar-tab--active .bb-toolbar-tab__count {
    background: var(--bb-primary-soft);
    color: var(--bb-primary);
}

/* --------------------------------------------------------------------------
   UDS-1d. TOOLBAR META  (.bb-toolbar-meta)
   Result count text in the toolbar, aria-live region for screen readers.
   Replaces: .bb-results-meta, .bb-stats-bar, .bb-filter-group--count
   -------------------------------------------------------------------------- */

.bb-toolbar-meta {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    margin-left: auto;
    white-space: nowrap;
    align-self: center;
    flex-shrink: 0;
}

.bb-toolbar-meta strong {
    font-weight: 700;
    color: var(--bb-text-primary);
}

/* --------------------------------------------------------------------------
   UDS-1e. TOOLBAR SECTION  (.bb-toolbar-section)
   Flex group inside the toolbar for related controls.
   -------------------------------------------------------------------------- */

.bb-toolbar-section {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    flex-wrap: wrap;
}

.bb-toolbar-section--grow {
    flex: 1;
}

/* --------------------------------------------------------------------------
   UDS-1f. TOOLBAR RESPONSIVE
   Stack all controls vertically on small screens.
   -------------------------------------------------------------------------- */

@media (max-width: 640px) {
    .bb-toolbar {
        flex-direction: column;
        align-items: stretch;
    }

    .bb-toolbar-search,
    .bb-toolbar-filter,
    .bb-toolbar-section {
        width: 100%;
        min-width: 0;
    }

    .bb-toolbar-meta {
        margin-left: 0;
    }

    .bb-toolbar-tabs {
        overflow-x: auto;
        flex-wrap: nowrap;
        -webkit-overflow-scrolling: touch;
        padding-bottom: 2px;
    }

    .bb-toolbar-tab {
        flex-shrink: 0;
    }
}

/* --------------------------------------------------------------------------
   UDS-2. UNIFIED CONTENT GRID  (.bb-content-grid)
   Replaces: .bb-contest-grid, .bb-divisions-grid, .bb-countries-grid
   -------------------------------------------------------------------------- */

.bb-content-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: var(--bb-space-4);
}

/* Fixed-column variants */
.bb-content-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.bb-content-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.bb-content-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Tighter gap option */
.bb-content-grid--dense { gap: var(--bb-space-3); }

/* Responsive: 2 → 2 col at 768, 1 col at 480 */
@media (max-width: 1024px) {
    .bb-content-grid--4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 768px) {
    .bb-content-grid--3,
    .bb-content-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 480px) {
    .bb-content-grid,
    .bb-content-grid--2,
    .bb-content-grid--3,
    .bb-content-grid--4 {
        grid-template-columns: 1fr;
    }
}

/* --------------------------------------------------------------------------
   UDS-3. UNIFIED CONTENT CARD  (.bb-content-card)
   Replaces: .bb-contest-card, .bb-division-card, .bb-country-card patterns
   -------------------------------------------------------------------------- */

.bb-content-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-6);
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
    box-shadow: var(--bb-shadow);
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition),
                transform var(--bb-transition);
}

/* Clickable whole-card variant, use as <a> element */
.bb-content-card--link {
    cursor: pointer;
    text-decoration: none;
    color: inherit;
    display: flex;
}

.bb-content-card--link:hover,
.bb-content-card:hover {
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
    transform: translateY(-2px);
}

.bb-content-card--link:focus-visible,
.bb-content-card:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}

/* Reduced motion: skip transform */
@media (prefers-reduced-motion: reduce) {
    .bb-content-card,
    .bb-content-card--link {
        transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
    }
    .bb-content-card--link:hover,
    .bb-content-card:hover {
        transform: none;
    }
}

/* Card sub-sections */
.bb-content-card__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--bb-space-3);
}

.bb-content-card__body {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
}

.bb-content-card__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--bb-space-2);
    padding-top: var(--bb-space-3);
    border-top: 1px solid var(--bb-gray-100);
    margin-top: auto;
}

.bb-content-card__meta {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    flex-wrap: wrap;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}

/* Typography inside a card */
.bb-content-card__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
    line-height: 1.3;
    margin: 0;
}

.bb-content-card__subtitle {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    margin: 0;
}

/* Small pill badge inside a card */
.bb-content-card__badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-radius: var(--bb-radius-full);
    background: var(--bb-primary-light);
    color: var(--bb-primary);
    white-space: nowrap;
    flex-shrink: 0;
}

/* Badge color variants */
.bb-content-card__badge--gold {
    background: rgba(217, 139, 74, 0.12);
    color: var(--bb-accent-hover);
}

.bb-content-card__badge--green {
    background: var(--bb-green-soft);
    color: var(--bb-green-600);
}

.bb-content-card__badge--gray {
    background: var(--bb-gray-100);
    color: var(--bb-gray-600);
}

/* Compact variant: less padding */
.bb-content-card--compact {
    padding: var(--bb-space-4);
    gap: var(--bb-space-2);
}

/* --------------------------------------------------------------------------
   UDS-4. UNIFIED CONTENT TABLE  (.bb-content-table)
   Replaces: .bb-table + .bb-table--responsive + .bb-table-container patterns
   -------------------------------------------------------------------------- */

/* Scrollable wrapper: always present for responsive overflow */
.bb-content-table-wrapper {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--bb-radius-lg);
    border: 1px solid var(--bb-gray-200);
    box-shadow: var(--bb-shadow);
}

.bb-content-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--bb-fs-sm);
    background: var(--bb-surface);
}

/* Header row */
.bb-content-table thead tr {
    background: var(--bb-gray-50);
}

.bb-content-table thead th {
    padding: 12px 16px;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-bottom: 2px solid var(--bb-border);
    text-align: left;
    white-space: nowrap;
    position: sticky;
    top: 0;
    background: var(--bb-gray-50);
    z-index: 1;
}

/* Body rows */
.bb-content-table tbody tr {
    border-bottom: 1px solid var(--bb-gray-100);
    transition: background var(--bb-transition);
}

.bb-content-table tbody tr:last-child {
    border-bottom: none;
}

/* No zebra striping (data-authority tables separate rows by hairline). */
.bb-content-table tbody tr:hover { background-color: var(--bb-gray-50); }

.bb-content-table td {
    padding: 14px 16px;
    color: var(--bb-text-secondary);
    vertical-align: middle;
}

/* Sortable column header */
.bb-content-table__sort {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    user-select: none;
    background: none;
    border: none;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    color: inherit;
    text-transform: inherit;
    letter-spacing: inherit;
    padding: 0;
    width: 100%;
}

.bb-content-table__sort:hover {
    color: var(--bb-text-primary);
}

.bb-content-table__sort-icon {
    width: 14px;
    height: 14px;
    opacity: 0.35;
    flex-shrink: 0;
    transition: opacity var(--bb-transition), transform var(--bb-transition);
}

.bb-content-table__sort--asc .bb-content-table__sort-icon,
.bb-content-table__sort--desc .bb-content-table__sort-icon {
    opacity: 1;
    color: var(--bb-primary);
}

.bb-content-table__sort--desc .bb-content-table__sort-icon {
    transform: rotate(180deg);
}

/* Responsive: card-like rows on mobile */
@media (max-width: 640px) {
    .bb-content-table--responsive thead {
        display: none;
    }

    .bb-content-table--responsive tbody tr {
        display: block;
        padding: var(--bb-space-3) var(--bb-space-4);
        border-bottom: 1px solid var(--bb-gray-200);
        background: var(--bb-surface) !important;
    }

    .bb-content-table--responsive tbody tr:hover {
        background: var(--bb-gray-50) !important;
    }

    .bb-content-table--responsive td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 4px 0;
        border: none;
    }

    .bb-content-table--responsive td[data-label]::before {
        content: attr(data-label);
        font-size: var(--bb-fs-xs);
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--bb-text-muted);
        flex-shrink: 0;
        margin-right: var(--bb-space-3);
    }
}

/* --------------------------------------------------------------------------
   UDS-5. UNIFIED PAGINATION  (.bb-pagination, canonical version)
   Standardised on ONE pattern; old .bb-page-btn is kept for compat.
   -------------------------------------------------------------------------- */

.bb-pagination {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 18px;
    border-top: 2px solid var(--bb-border);
    font-size: 13px;
    color: var(--bb-text-muted);
}

.bb-pagination__btn {
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--bb-text-secondary);
    cursor: pointer;
    background: none;
    font-family: inherit;
    transition: all 0.15s;
}

.bb-pagination__btn:hover {
    background: var(--bb-bg);
}

.bb-pagination__btn--active,
.bb-pagination__btn--active:hover {
    background: var(--bb-primary);
    color: white;
}

.bb-pagination__btn:disabled,
.bb-pagination__btn[disabled] {
    opacity: 0.4;
    cursor: not-allowed;
}

.bb-pagination__btn:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}

.bb-pagination__ellipsis {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    color: var(--bb-text-muted);
    font-size: 13px;
    cursor: default;
    user-select: none;
}

/* --------------------------------------------------------------------------
   UDS-5b. CRAWLABLE SSR PAGER  (.bb-pager)
   Server-rendered prev/next links remain crawlable with or without JavaScript,
   so crawlers can walk every indexable directory page without relying on the
   XML sitemap. Scoped, token-driven, and matched to the directory chrome.
   -------------------------------------------------------------------------- */

.bb-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 16px 18px;
    border-top: 2px solid var(--bb-border);
    font-size: 13px;
}

.bb-pager__link {
    display: inline-flex;
    align-items: center;
    padding: 8px 14px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    color: var(--bb-text-secondary);
    background: var(--bb-bg);
    border: 1px solid var(--bb-border);
    transition: background 0.15s, color 0.15s;
}

.bb-pager__link:hover {
    background: var(--bb-primary);
    color: #fff;
    border-color: var(--bb-primary);
}

.bb-pager__link:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}

.bb-pager__link--disabled {
    opacity: 0.4;
    pointer-events: none;
    cursor: not-allowed;
}

.bb-pager__status {
    color: var(--bb-text-muted);
    font-weight: 600;
}

/* --------------------------------------------------------------------------
   UDS-6. UNIFIED EMPTY STATE  (.bb-empty-state, enhanced)
   The existing .bb-empty-state and .bb-empty are kept; these add structure.
   -------------------------------------------------------------------------- */

.bb-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: var(--bb-space-12) var(--bb-space-6);
    /* --bb-text-muted, not --bb-gray-400. #8a8076 measured 3.79:1 on the bone
       cards these states sit in, and the brief names #6b6259 as the LIGHTEST grey
       permitted on bone - so the empty-state body copy was lighter than the stated
       floor. This block is duplicated verbatim later in the file; both copies carry
       the same value so neither can win with the old one. */
    color: var(--bb-text-muted);
}

.bb-empty-state__icon {
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bb-gray-100);
    border-radius: var(--bb-radius-xl);
    margin-bottom: var(--bb-space-4);
    color: var(--bb-gray-400);
    font-size: 1.75rem;
}

.bb-empty-state__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-gray-700);
    margin: 0 0 var(--bb-space-2);
}

.bb-empty-state__desc {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    max-width: 380px;
    line-height: 1.6;
    margin: 0 0 var(--bb-space-5);
}

.bb-empty-state__cta {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    padding: 9px 20px;
    background: var(--bb-primary);
    color: #fff;
    border-radius: var(--bb-radius);
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    text-decoration: none;
    transition: background var(--bb-transition);
    border: none;
    cursor: pointer;
    font-family: var(--bb-font-body);
}

.bb-empty-state__cta:hover {
    background: var(--bb-primary-hover);
    color: #fff;
}

/* --------------------------------------------------------------------------
   UDS-7. UNIFIED SKELETON LOADERS  (.bb-skeleton, enhanced)
   The keyframe bb-shimmer already exists; these add layout composites.
   -------------------------------------------------------------------------- */

/* Base shimmer helper: applies the shimmer animation */
.bb-skeleton {
    background: linear-gradient(90deg, var(--bb-gray-100) 25%, var(--bb-gray-200) 50%, var(--bb-gray-100) 75%);
    background-size: 200% 100%;
    animation: bb-shimmer 1.5s infinite;
    border-radius: var(--bb-radius);
}

/* Card-shaped skeleton: matches .bb-content-card dimensions */
.bb-skeleton-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
}

.bb-skeleton-card .bb-skeleton-line,
.bb-skeleton-line {
    height: 14px;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--bb-gray-100) 25%, var(--bb-gray-200) 50%, var(--bb-gray-100) 75%);
    background-size: 200% 100%;
    animation: bb-shimmer 1.5s ease-in-out infinite;
}

.bb-skeleton-card .bb-skeleton-line--title {
    height: 18px;
    width: 70%;
}

.bb-skeleton-card .bb-skeleton-line--sm {
    height: 11px;
    width: 45%;
}

.bb-skeleton-card .bb-skeleton-line--badge {
    height: 22px;
    width: 60px;
    border-radius: var(--bb-radius-full);
}

/* Table row skeleton */
.bb-skeleton-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1rem 0;
    border-bottom: 1px solid var(--bb-gray-100);
}

.bb-skeleton-row .bb-skeleton-cell {
    flex: 1;
    height: 14px;
    border-radius: 4px;
    background: linear-gradient(90deg, var(--bb-gray-100) 25%, var(--bb-gray-200) 50%, var(--bb-gray-100) 75%);
    background-size: 200% 100%;
    animation: bb-shimmer 1.5s infinite;
}

.bb-skeleton-row .bb-skeleton-cell--narrow { flex: 0 0 60px; }
.bb-skeleton-row .bb-skeleton-cell--wide   { flex: 2; }

/* Stagger skeleton animation for visual interest */
.bb-skeleton-card:nth-child(2) .bb-skeleton-line,
.bb-skeleton-row:nth-child(2) .bb-skeleton-cell { animation-delay: 0.1s; }
.bb-skeleton-card:nth-child(3) .bb-skeleton-line,
.bb-skeleton-row:nth-child(3) .bb-skeleton-cell { animation-delay: 0.2s; }
.bb-skeleton-card:nth-child(4) .bb-skeleton-line,
.bb-skeleton-row:nth-child(4) .bb-skeleton-cell { animation-delay: 0.3s; }
.bb-skeleton-card:nth-child(5) .bb-skeleton-line,
.bb-skeleton-row:nth-child(5) .bb-skeleton-cell { animation-delay: 0.4s; }
.bb-skeleton-card:nth-child(6) .bb-skeleton-line,
.bb-skeleton-row:nth-child(6) .bb-skeleton-cell { animation-delay: 0.5s; }

/* ==========================================================================
   END UNIFIED DESIGN SYSTEM
   ========================================================================== */

/* ==========================================================================
   CAREER TIMELINE (athlete profile)
   ========================================================================== */

/* Career summary bar */
.bb-career-timeline-summary {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-4) var(--bb-space-6);
    padding: var(--bb-space-4) var(--bb-space-5);
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius);
    margin-bottom: var(--bb-space-5);
}
.bb-career-timeline-summary-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 80px;
}
.bb-career-timeline-summary-value {
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    color: var(--bb-text-primary);
    line-height: 1.2;
}
.bb-career-timeline-summary-label {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
}

/* Timeline container - horizontal scroll */
.bb-career-timeline {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    position: relative;
    overflow-x: auto;
    overflow-y: visible;
    /* 26/24/20, claude-design's card padding. Was 80/16/24: the 80 was tooltip
       headroom and the 16 left the strip tighter to the card edge than the
       prototype sets it. */
    padding: 26px 24px 20px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: var(--bb-gray-300) transparent;
}
.bb-career-timeline::-webkit-scrollbar { height: 6px; }
.bb-career-timeline::-webkit-scrollbar-track { background: transparent; }
.bb-career-timeline::-webkit-scrollbar-thumb { background: var(--bb-gray-300); border-radius: 3px; }

/* The main track line */
.bb-career-timeline-track {
    position: relative;
    display: flex;
    align-items: flex-end;
    /* 150px floor, down from 180. Dropping it to 0 looked right on Coleman - the
       height then comes from the dot stack - but a two-result career has almost
       no stack, so its first dot sat near the top of the scrollport and the 114px
       tooltip opened straight through the ceiling. The floor is headroom for the
       tooltip, not decoration. 34px below clears the rotated year label (25px)
       and its tick; milestones left the strip so nothing else needs reserving. */
    min-height: 150px;
    /* 0: the rotated year label and its tick are laid out inside the column, and
       the legend's own 20+16 above its rule is all the separation the prototype
       leaves under the labels. Anything here is dead white on top of that. */
    padding-bottom: 0;
}
/* No horizontal axis bar on desktop. claude-design draws none: each year column
   carries its own 1px x 9px tick, and a 3px rule across the card competed with
   the dots it was meant to sit under. The spine survives only on mobile, where
   the track becomes a stacked column and genuinely needs one (see the 767px
   block below). */

/* Year column.
   36px, measured off claude-design: its year columns sit 35px apart. Ours were
   80px, which is most of why the strip sprawled sideways and had to scroll.
   The width drop is only possible because the label below turned vertical. */
/* Dots, then tick, then year label - stacked in normal flow with one gap, the
   way claude-design builds the column. They used to be absolutely positioned at
   fixed offsets from the column's bottom (label at 0, tick at 22) while the
   rotated label is 26-28px tall, so the tick sat ON the digits. Nothing could
   hold that: the label's height depends on the font, and a hardcoded offset
   cannot follow it. In flow the gap is measured from the label's real box. */
.bb-career-timeline-year {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    /* 36px preferred, shrinking to 16 when a career has enough years to need it.
       Fixed 36px columns are why the strip ever scrolled: 27 years needed 972px
       and a longer career more, so the card became a scrollport, which clipped
       the tooltips, which is what the 80px paddings were reserved to work
       around. Shrinking columns removes the whole chain - claude-design's own
       columns are 13px wide. 16 is the floor because the rotated year label
       needs 14. */
    flex: 0 1 36px;
    min-width: 16px;
    position: relative;
}
/* Year label: 10.5px IBM Plex Mono set vertical-rl, exactly as the prototype
   does it. Horizontal 12px Archivo labels needed ~29px of width each, which is
   what forced the 80px columns; rotated they need 14px and the whole strip
   compacts. */
.bb-career-timeline-year-label {
    writing-mode: vertical-rl;
    font-family: var(--bb-font-mono);
    /* 11, where claude-design measures 10.5. The half pixel is invisible at this
       size and clears the contrast audit's small-text floor, which flagged all 18
       year labels; matching a mockup exactly is not worth shipping text the
       project's own gate calls too small to read. */
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.04em;
    color: var(--bb-warm-grey-2);
    white-space: nowrap;
    z-index: 1;
}
.bb-career-timeline-year-tick {
    width: 2px;
    height: 12px;
    background: var(--bb-gray-300);
    flex-shrink: 0;
    z-index: 1;
}

/* Dots stack above the tick */
/* 5px gap: the prototype's rows sit 18px apart on a 13px dot, so the gap is 5.
   No padding-bottom - it existed to lift the stack clear of the absolutely
   positioned label and tick underneath it. Those are in flow now, so the
   column's own 8px gap is the whole separation and 40px here would just be
   dead white the prototype does not have. */
.bb-career-timeline-dots {
    display: flex;
    flex-direction: column-reverse;
    align-items: center;
    gap: 5px;
    padding-bottom: 0;
    min-height: 0;
}

/* Individual result dot.
   12px with a 1.5px ring, measured off claude-design (11-13px there). Ours were
   18px, and at eleven stacked rows that alone added ~66px of height and made
   the strip read as a chart rather than the prototype's compact record. */
.bb-career-timeline-dot {
    display: block;
    padding: 0;
    appearance: none;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1.5px solid #fff;
    cursor: pointer;
    position: relative;
    z-index: 2;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    flex-shrink: 0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}
.bb-career-timeline-dot:hover,
.bb-career-timeline-dot:focus-visible {
    transform: scale(1.35);
    box-shadow: 0 2px 8px rgba(0,0,0,0.2);
    outline: none;
    z-index: 10;
}
/* P3-10a: the shared hover/focus rule zeroes the outline, so a keyboard-focused dot
   looked identical to a hovered one. Restore a visible focus ring (later, equal-
   specificity rule wins over the outline:none above); the scale/shadow still apply. */
.bb-career-timeline-dot:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset, 2px);
}
.bb-career-timeline-dot--gold   { background: var(--bb-amber-dark); }
.bb-career-timeline-dot--silver { background: var(--bb-gray-400); }
.bb-career-timeline-dot--bronze { background: #cd7f32; }
.bb-career-timeline-dot--other  { background: var(--bb-gray-300); }
.bb-career-timeline-dot--olympia {
    background: var(--bb-primary);
    box-shadow: 0 0 0 3px rgba(178, 58, 53, 0.25), 0 1px 3px rgba(0,0,0,0.12);
}

/* Star overlay for Olympia dots */
.bb-career-timeline-dot--olympia::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 8px;
    height: 8px;
    transform: translate(-50%, -50%);
    background: #fff;
    clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}

/* Tooltip */
.bb-career-timeline-tooltip {
    display: none;
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--bb-navy);
    color: #fff;
    padding: 10px 14px;
    border-radius: var(--bb-radius);
    font-size: var(--bb-fs-xs);
    white-space: nowrap;
    z-index: 20;
    pointer-events: none;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    line-height: 1.5;
}
.bb-career-timeline-dot:hover > .bb-career-timeline-tooltip,
.bb-career-timeline-dot:focus > .bb-career-timeline-tooltip {
    display: block;
}
.bb-career-timeline-tooltip::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: var(--bb-navy);
}
.bb-career-timeline-tooltip-contest {
    font-weight: 700;
    display: block;
    margin-bottom: 2px;
}
.bb-career-timeline-tooltip-detail {
    display: block;
    opacity: 0.8;
}
.bb-career-timeline-tooltip-placement {
    display: inline-block;
    font-weight: 700;
    margin-top: 2px;
}
.bb-career-timeline-tooltip-placement--gold   { color: var(--bb-amber); }
.bb-career-timeline-tooltip-placement--silver { color: var(--bb-gray-300); }
.bb-career-timeline-tooltip-placement--bronze { color: var(--bb-amber); }

/* Milestone flags */
/* Milestones live in their own band BELOW the year axis.
   They used to sit at bottom:42px, growing upward into the dot stack. That is
   fine when a career has twelve dots in the column and nothing to collide with,
   and wrong when it has two: on paul-maccarone and carlos-chan the flag covered
   a result dot outright. Anchoring below the axis makes the collision impossible
   by construction rather than by clearance arithmetic that the next long label
   would break again. The track's padding-bottom reserves the band. */
.bb-career-timeline-milestone {
    pointer-events: none;
    position: absolute;
    top: 100%;
    margin-top: 4px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 3;
}
/* Milestone flags run vertical, like the year labels beneath them.
   They were horizontal pills ~100px wide sitting in what are now 36px columns,
   so "Pro Debut", "First Win" and "Olympia Debut" overlapped into an unreadable
   smear on any athlete whose first three seasons are consecutive - which is most
   of them. Rotated they occupy the column they belong to and read cleanly, and
   the mono/uppercase treatment matches the axis labels rather than fighting them.
   Kept, not dropped: the prototype has no milestones, but they are real
   information this page adds. */
.bb-career-timeline-milestone-flag {
    display: inline-flex;
    align-items: center;
    writing-mode: vertical-rl;
    background: transparent;
    color: var(--bb-ink);
    font-family: var(--bb-font-mono);
    font-size: 9.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    padding: 0;
    border-radius: 0;
    white-space: nowrap;
    box-shadow: none;
}
.bb-career-timeline-milestone-flag::after {
    /* The pill's downward arrow belonged to a filled pill; a hairline tying the
       label to its column reads correctly on a transparent one. */
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    width: 1px;
    height: 6px;
    background: var(--bb-border);
    border: 0;
}
.bb-career-timeline-milestone-flag svg {
    width: 10px;
    height: 10px;
    flex-shrink: 0;
}

/* Timeline legend */
.bb-career-timeline-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-3) var(--bb-space-5);
    padding-top: var(--bb-space-4);
    border-top: 1px solid var(--bb-gray-100);
    margin-top: var(--bb-space-2);
}
.bb-career-timeline-legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}
.bb-career-timeline-legend-dot {
    position: relative;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

@media (min-width: 768px) {
    /* No horizontal reserve on the track. It was 80px each side so a 160px
       tooltip on the first or last dot had somewhere to go inside the clipping
       scrollport - a hover state charging rent on every pageview. It also
       indented the first year column 80px from the card padding while the
       legend below started at the padding, which is the misalignment you could
       see. The tooltip now steers away from the edges instead (below). */
    .bb-career-timeline-track {
        padding-left: 0;
        padding-right: 0;
    }

    /* The columns now always fit, so the card does not need to be a scrollport
       and therefore does not need to clip. Tooltips simply hang outside it. This
       is what retires the 26px-of-headroom problem for tall stacks: there is no
       ceiling left to clip against. */
    .bb-career-timeline {
        overflow: visible;
    }

    /* A tooltip is 160px on a 12px dot, so one on an end column would still run
       off the page. First two columns open rightward, last two leftward. The
       nth-child(n+5) matters: on a career of four years or fewer a column is in
       BOTH sets, and right-align won the cascade and threw the tooltip off the
       left edge. Short careers leave the whole card free to the right, so they
       need no right-align at all. */
    .bb-career-timeline-year:nth-child(-n + 2) .bb-career-timeline-tooltip {
        left: 0;
        right: auto;
        transform: none;
    }
    .bb-career-timeline-year:nth-last-child(-n + 2):nth-child(n + 5) .bb-career-timeline-tooltip {
        left: auto;
        right: 0;
        transform: none;
    }
    .bb-career-timeline-tooltip {
        width: max-content;
        max-width: 10rem;
        white-space: normal;
        overflow-wrap: anywhere;
        text-align: left;
    }
    /* The stack is column-reverse, so the last DOM dot is the visually topmost
       one - the one with no room above it. It opens downward. The old selector
       carried :not(:first-child), which exempted exactly the single-result
       columns whose only dot is also the topmost, and those were the ones
       clipping. */
    .bb-career-timeline-dot:nth-last-child(-n + 2) > .bb-career-timeline-tooltip {
        top: calc(100% + var(--bb-space-2-5));
        bottom: auto;
    }
    .bb-career-timeline-dot:nth-last-child(-n + 2) > .bb-career-timeline-tooltip::after {
        top: auto;
        bottom: 100%;
        border-top-color: transparent;
        border-bottom-color: var(--bb-navy);
    }
}

/* Mobile: vertical layout */
@media (max-width: 767px) {
    .bb-career-timeline { overflow-x: visible; padding: var(--bb-space-4) 0; }

    /*
     * No left padding, because nothing is pulled back out of it any more.
     *
     * The track reserved 30px and the year label was then dragged back across
     * it with margin-left:-30px, which put the label at the track's own left
     * edge. The spine, meanwhile, was positioned 13px in. So the rail ran
     * straight down THROUGH the year labels: measured at 375px, spine at x=32,
     * labels spanning x=19 to x=94. The two rules were written against
     * different assumptions about where the gutter was.
     *
     * The year now sits in the grid column that was always meant for it, and
     * the spine sits to the right of that column where a rail belongs.
     */
    .bb-career-timeline-track {
        flex-direction: column;
        align-items: flex-start;
        min-height: auto;
        padding-bottom: 0;
        padding-left: 0;
    }
    /* Vertical spine for the stacked mobile layout. Declared in full here because
       the desktop bar is gone, so there is nothing to override. */
    .bb-career-timeline-track::after {
        content: '';
        position: absolute;
        top: 0;
        bottom: 0;
        /* Clear of the year column (--bb-space-12) with a gap, so the rail
           separates the years from the results instead of crossing them. */
        left: calc(var(--bb-space-12) + var(--bb-space-3));
        right: auto;
        width: 3px;
        height: auto;
        background: var(--bb-gray-200);
        border-radius: 2px;
        z-index: 0;
    }

    .bb-career-timeline-year {
        display: grid;
        grid-template-columns: var(--bb-space-12) minmax(0, 1fr);
        align-items: start;
        min-width: auto;
        width: 100%;
        /* The spine now lives inside this gap, so it has to be wide enough to
           hold a 3px rail with air on both sides of it. */
        column-gap: var(--bb-space-6);
        row-gap: var(--bb-space-1);
        margin-bottom: var(--bb-space-4);
    }
    .bb-career-timeline-year-label {
        grid-column: 1;
        grid-row: 1;
        position: relative;
        bottom: auto;
        /* Horizontal again below 768. The vertical label exists to fit a 36px
           column in the horizontal strip; this layout stacks one year per ROW
           with the full width available, so rotating buys nothing and costs
           height - 27px against 18px, times 27 years on a long career, which is
           what tipped greg-grant past the timeline height ceiling. */
        writing-mode: horizontal-tb;
        font-family: var(--bb-font-mono);
        font-size: var(--bb-fs-sm);
        font-weight: 700;
        color: var(--bb-text-primary);
        min-width: 40px;
        margin-left: 0;
    }
    /* Same reasoning for the milestone flag: horizontal in the stacked layout,
       where it sits in its own grid row and cannot collide with a dot. */
    .bb-career-timeline-milestone-flag {
        writing-mode: horizontal-tb;
    }
    .bb-career-timeline-milestone-flag::after { display: none; }
    /*
     * The tick is a 2x12 VERTICAL mark, built to drop from a year label onto
     * the horizontal axis of the desktop strip. In the stacked layout it points
     * the wrong way, which is why it was hidden rather than restyled. Turned on
     * its side it does the job it was always doing: joining the year to the
     * rail, so eleven rows read as one timeline rather than two columns that
     * happen to line up.
     */
    .bb-career-timeline-year-tick {
        display: block;
        position: absolute;
        left: var(--bb-space-12);
        top: 9px;
        width: var(--bb-space-3);
        height: 2px;
    }

    .bb-career-timeline-dots {
        grid-column: 2;
        grid-row: 1;
        flex-direction: row;
        flex-wrap: wrap;
        padding-bottom: 0;
        min-height: auto;
        gap: var(--bb-space-1-5);
    }

    .bb-career-timeline-milestone {
        grid-column: 2;
        grid-row: 2;
        justify-self: start;
        position: relative;
        bottom: auto;
        left: auto;
        transform: none;
        margin-top: var(--bb-space-1);
    }

    .bb-career-timeline-summary {
        gap: var(--bb-space-3) var(--bb-space-4);
    }
    .bb-career-timeline-summary-item { min-width: 70px; }
    .bb-career-timeline-summary-value { font-size: var(--bb-fs-base); }
}

/* Broken image fallback - hide broken images gracefully */
.bb-img-fallback {
    position: relative;
}
.bb-img-fallback img[src=""],
.bb-img-fallback img:not([src]) {
    display: none;
}

/* =========================================================================
   On This Day - Full Page
   ========================================================================= */

.bb-otd-hero {
    text-align: center;
}
.bb-otd-hero-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 12px;
}
.bb-otd-hero-badge svg {
    flex-shrink: 0;
}

/* Date navigation bar */
.bb-otd-date-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin: 0 0 32px;
    padding: 16px 0;
}
.bb-otd-nav-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.bb-otd-current-date {
    font-size: 16px;
    font-weight: 700;
    color: var(--bb-text-primary);
    min-width: 120px;
    text-align: center;
}

/* Timeline layout */
.bb-otd-timeline {
    position: relative;
    padding-left: 80px;
    margin: 0 0 48px;
}
.bb-otd-timeline::before {
    content: '';
    position: absolute;
    left: 36px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--bb-border);
    border-radius: 1px;
}

/* Individual event */
.bb-otd-event {
    position: relative;
    margin-bottom: 24px;
}
.bb-otd-event::before {
    content: '';
    position: absolute;
    left: -48px;
    top: 16px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--bb-primary);
    border: 2px solid var(--bb-surface, #fff);
    box-shadow: 0 0 0 2px var(--bb-primary-light);
    z-index: 1;
}
.bb-otd-event--milestone::before {
    background: var(--bb-accent);
    box-shadow: 0 0 0 2px var(--bb-accent-light);
}

/* --- Archive block ------------------------------------------------------
   Contests that did NOT happen on the requested date, shown when a date is
   thin. They used to render in the timeline above, which read them as results
   for that day. Everything here says "related, not dated": the heading sits
   below the main one, the marker is hollow rather than filled, and the whole
   block is set back so a reader's eye reaches it after the real entries. */
/* NOTE: the archive heading's margin-top lives further down the file, after
   the .bb-app .bb-section-title declarations at 13649 and 18568. Both match
   this element at the same specificity, so a rule written here would be
   overridden by source order and silently compute 0. Measured, not assumed. */
.bb-app .bb-otd-timeline--archive {
    margin-top: 16px;
}
.bb-app .bb-otd-event--archive::before {
    /* Hollow marker: the filled dot is what a dated entry earns. */
    background: var(--bb-surface, #fff);
    border-color: var(--bb-border);
    box-shadow: 0 0 0 2px var(--bb-border);
}
.bb-app .bb-otd-event--archive .bb-otd-event-meta {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-warm-grey-2);
    margin: 4px 0 0;
}

/* The count of contests withheld from this date because their day is not
   recorded. Reads as provenance, not as an error state. */
.bb-app .bb-otd-imprecise-note {
    margin: 0 0 24px;
}

/* Year badge */
.bb-otd-year-badge {
    position: absolute;
    left: -80px;
    top: 10px;
    width: 56px;
    text-align: right;
    font-size: 14px;
    font-weight: 700;
    color: var(--bb-text-muted);
    line-height: 1;
}

/* Event card */
.bb-otd-event-card {
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius, 10px);
    padding: 16px 20px;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.bb-otd-event-card:hover {
    border-color: var(--bb-primary-light);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
}
.bb-otd-event--milestone .bb-otd-event-card {
    border-color: rgba(217, 139, 74, 0.5);
    background: linear-gradient(135deg, rgba(217, 139, 74, 0.08), var(--bb-surface, #fff) 42%);
}

.bb-otd-event-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 6px;
}
.bb-otd-event-title {
    font-size: 16px;
    font-weight: 700;
    color: var(--bb-text-primary);
    margin: 0;
    line-height: 1.3;
}
.bb-otd-event-link {
    color: var(--bb-text-primary);
    text-decoration: none;
    transition: color 0.15s ease;
}
.bb-otd-event-link:hover {
    color: var(--bb-primary);
}
.bb-otd-milestone-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--bb-accent-light);
    color: var(--bb-accent-hover);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

.bb-otd-event-text {
    font-size: 14px;
    color: var(--bb-text-secondary);
    margin: 0 0 8px;
    line-height: 1.55;
}

/* Winners list */
.bb-otd-winners {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 8px 0;
}
.bb-otd-winner {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
}
.bb-otd-winner-trophy {
    font-size: 14px;
    flex-shrink: 0;
}
.bb-otd-winner-name {
    font-weight: 600;
    color: var(--bb-primary);
    text-decoration: none;
    transition: color 0.15s ease;
}
.bb-otd-winner-name:hover {
    color: var(--bb-primary-hover);
}
.bb-otd-winner-division {
    color: var(--bb-text-muted);
    font-size: 13px;
}

/* Event meta (location) */
.bb-otd-event-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--bb-text-muted);
    margin-top: 6px;
}

/* Mobile responsive timeline */
@media (max-width: 640px) {
    .bb-otd-timeline {
        padding-left: 40px;
    }
    .bb-otd-timeline::before {
        left: 14px;
    }
    .bb-otd-event::before {
        left: -30px;
        width: 8px;
        height: 8px;
    }
    .bb-otd-year-badge {
        position: relative;
        left: auto;
        top: auto;
        text-align: left;
        margin-bottom: 6px;
        font-size: 13px;
        color: var(--bb-primary);
        font-weight: 700;
    }
    .bb-otd-event-card {
        padding: 12px 14px;
    }
    .bb-otd-event-title {
        font-size: 15px;
    }
    .bb-otd-date-nav {
        gap: 10px;
    }
    .bb-otd-current-date {
        font-size: 14px;
        min-width: 90px;
    }
}

/* =========================================================================
   On This Day - Hub Widget
   ========================================================================= */

.bb-otd-widget {
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg, 14px);
    padding: 24px;
    margin: 32px 0;
}
.bb-otd-widget-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}
.bb-otd-widget-title-row {
    display: flex;
    align-items: center;
    gap: 8px;
}
.bb-otd-widget-heading {
    margin: 0 !important;
    padding: 0 !important;
    /* 22px, the minor tier. 18 is on no tier - and the !important is why it
       survived every heading pass: nothing else could reach it. */
    font-size: var(--bb-fs-22) !important;
    letter-spacing: -0.016em;
}
.bb-otd-widget-date {
    font-size: 14px;
    font-weight: 600;
    color: var(--bb-primary);
    background: var(--bb-primary-light);
    padding: 4px 12px;
    border-radius: 999px;
}

.bb-otd-widget-events {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 16px;
}
.bb-otd-widget-event {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 14px;
    background: var(--bb-bg);
    border-radius: var(--bb-radius, 10px);
    transition: background 0.15s ease;
}
.bb-otd-widget-event:hover {
    background: var(--bb-gray-100, #f1f3f5);
}
.bb-otd-widget-year {
    flex-shrink: 0;
    font-size: 14px;
    font-weight: 700;
    color: var(--bb-primary);
    min-width: 40px;
    padding-top: 1px;
}
.bb-otd-widget-event-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.bb-otd-widget-event-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--bb-text-primary);
    line-height: 1.3;
    /* WCAG 2.2 target size: measured 18px tall on the hub's This Day widget. */
    min-height: 24px;
}
.bb-otd-widget-event-text {
    font-size: 13px;
    color: var(--bb-text-muted);
    line-height: 1.4;
}
.bb-otd-widget-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

@media (max-width: 640px) {
    .bb-otd-widget {
        padding: 16px;
        margin: 24px 0;
    }
    .bb-otd-widget-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
    }
    /* 16px is below every H2 tier. A widget heading is a minor section
       heading, which is what the 22 step is for; being in a widget does not
       make it a label. */
    .bb-otd-widget-heading {
        font-size: var(--bb-fs-22) !important;
    }
}

/* ==========================================================================
   DIVISION ANALYTICS DASHBOARD
   ========================================================================== */

/* Division selector */
.bb-analytics-selector {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-6);
    flex-wrap: wrap;
}

.bb-analytics-selector__label {
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-text-secondary);
}

.bb-analytics-selector__select {
    padding: 10px 36px 10px 14px;
    font-size: var(--bb-fs-sm);
    font-family: var(--bb-font-body);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    color: var(--bb-text-primary);
    cursor: pointer;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7585' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    min-width: 260px;
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-analytics-selector__select:focus {
    outline: none;
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
}

/* Division banner */
.bb-analytics-division-banner {
    margin-bottom: var(--bb-space-5);
}

.bb-analytics-division-name {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-text-primary);
    font-family: var(--bb-font-heading);
}

/* Stats grid - 5 cards */
.bb-analytics-stats-grid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-6);
}

@media (max-width: 1024px) {
    .bb-analytics-stats-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 640px) {
    .bb-analytics-stats-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Chart card container */
.bb-analytics-chart-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-5);
    margin-bottom: var(--bb-space-6);
}

.bb-analytics-chart-title {
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-primary);
    margin: 0 0 var(--bb-space-1) 0;
    font-family: var(--bb-font-heading);
}

.bb-analytics-chart-subtitle {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin: 0 0 var(--bb-space-4) 0;
}

/* Two-column layout */
.bb-analytics-two-col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--bb-space-6);
    margin-bottom: 0;
}

.bb-analytics-two-col .bb-analytics-chart-card {
    margin-bottom: var(--bb-space-6);
}

@media (max-width: 768px) {
    .bb-analytics-two-col {
        grid-template-columns: 1fr;
    }
}

/* ---- Vertical Bar Chart (Growth by Year) ---- */
.bb-bar-chart {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 220px;
    padding-top: var(--bb-space-2);
}

.bb-bar-chart__col {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 100%;
    justify-content: flex-end;
    min-width: 0;
}

.bb-bar-chart__value {
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    color: var(--bb-text-muted);
    margin-bottom: 4px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

.bb-bar-chart__bar {
    width: 100%;
    max-width: 40px;
    background: var(--bb-primary);
    border-radius: 4px 4px 0 0;
    transition: height 0.5s ease, background 0.2s;
    min-height: 4px;
    cursor: default;
}

.bb-bar-chart__bar:hover {
    background: var(--bb-primary-hover);
}

.bb-bar-chart__label {
    font-size: var(--bb-fs-2xs);
    color: var(--bb-text-muted);
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
}

/*
 * On a narrow screen the chart used to shrink its type instead of its ambition:
 * font-size dropped to a hardcoded 8px, below this plugin's own 11px legibility
 * floor and not a token at all. Measured on /divisions/analytics/ at 390px with 15
 * columns: each column 20.2px wide, value and label both 8px, and 3 of the 15
 * values still clipped by their own text-overflow because 20px cannot hold the
 * number regardless of how small the text gets.
 *
 * test-type-scale-floor.mjs could never have caught this: it exempts bar-chart
 * from the floor precisely because these were assumed to be furniture.
 *
 * Give each column a width it can actually hold a number in and let the chart
 * scroll, the same choice the event-page division tabs needed. Type stays on the
 * token.
 */
@media (max-width: 640px) {
    .bb-bar-chart {
        height: 160px;
        gap: 3px;
        overflow-x: auto;
        /* Room for the scrollbar so it cannot sit on top of the labels. */
        padding-bottom: var(--bb-space-1);
    }
    .bb-bar-chart__col {
        flex: 0 0 auto;
        min-width: 30px;
    }
}

/* ---- Horizontal Bar Chart (Top Countries) ---- */
.bb-hbar-chart {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.bb-hbar-chart__row {
    display: grid;
    grid-template-columns: 140px 1fr 60px;
    align-items: center;
    gap: var(--bb-space-3);
}

.bb-hbar-chart__label {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-primary);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bb-hbar-chart__rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--bb-gray-100);
    font-size: 11px;
    font-weight: 700;
    color: var(--bb-text-muted);
    flex-shrink: 0;
}

.bb-hbar-chart__track {
    height: 24px;
    background: var(--bb-gray-100);
    border-radius: 6px;
    overflow: hidden;
}

.bb-hbar-chart__fill {
    height: 100%;
    background: linear-gradient(90deg, var(--bb-primary), var(--bb-primary-hover));
    border-radius: 6px;
    transition: width 0.6s ease;
    min-width: 4px;
}

.bb-hbar-chart__count {
    font-size: var(--bb-fs-sm);
    font-weight: 700;
    color: var(--bb-text-primary);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
    .bb-hbar-chart__row {
        grid-template-columns: 100px 1fr 50px;
        gap: var(--bb-space-2);
    }
    .bb-hbar-chart__label { font-size: var(--bb-fs-xs); }
    .bb-hbar-chart__track { height: 18px; }
}

/* ---- Notable Athletes List ---- */
.bb-analytics-notable-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.bb-analytics-notable-item {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: 10px 12px;
    border-radius: var(--bb-radius);
    text-decoration: none;
    color: var(--bb-text-primary);
    transition: background var(--bb-transition);
}

.bb-analytics-notable-item:hover {
    background: var(--bb-gray-50);
}

.bb-analytics-notable-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--bb-primary-light);
    font-size: 12px;
    font-weight: 800;
    color: var(--bb-primary);
    flex-shrink: 0;
}

.bb-analytics-notable-info {
    flex: 1;
    min-width: 0;
}

.bb-analytics-notable-name {
    display: block;
    font-weight: 600;
    font-size: var(--bb-fs-sm);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bb-analytics-notable-meta {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}

.bb-analytics-notable-country {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    flex-shrink: 0;
}

/* ---- Trends Table ---- */
.bb-analytics-trends-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.bb-analytics-trends-table {
    width: 100%;
    font-size: var(--bb-fs-sm);
}

.bb-analytics-trends-table th {
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
    color: var(--bb-text-muted);
    padding: 8px 12px;
    border-bottom: 2px solid var(--bb-gray-200);
    white-space: nowrap;
}

.bb-analytics-trends-table td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--bb-gray-100);
    font-variant-numeric: tabular-nums;
}

.bb-analytics-growth--up {
    color: var(--bb-green-600);
    font-weight: 600;
}

.bb-analytics-growth--down {
    color: var(--bb-error);
    font-weight: 600;
}

/* ---- Competitiveness Card ---- */
.bb-analytics-comp-body {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-4);
}

.bb-analytics-comp-value {
    display: flex;
    align-items: baseline;
    gap: var(--bb-space-2);
}

.bb-analytics-comp-number {
    font-size: 48px;
    font-weight: 800;
    color: var(--bb-primary);
    letter-spacing: -0.03em;
    line-height: 1;
    font-family: var(--bb-font-heading);
}

.bb-analytics-comp-unit {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    font-weight: 500;
}

.bb-analytics-comp-desc {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
    line-height: 1.6;
    margin: 0;
}

.bb-analytics-comp-meter__track {
    height: 10px;
    background: var(--bb-gray-100);
    border-radius: 5px;
    overflow: hidden;
}

.bb-analytics-comp-meter__fill {
    height: 100%;
    background: linear-gradient(90deg, var(--bb-green-500), var(--bb-accent), var(--bb-primary));
    border-radius: 5px;
    transition: width 0.6s ease;
}

.bb-analytics-comp-meter__labels {
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    color: var(--bb-text-muted);
    margin-top: 4px;
}

/* ========================================================================
   Programmatic SEO Pages
   ======================================================================== */

.bb-pseo-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
    gap: 16px;
    margin-bottom: 32px;
}

.bb-pseo-stat-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 20px 16px;
    min-height: 100px;
}

.bb-pseo-stat-value {
    font-size: 28px;
    font-weight: 800;
    color: var(--bb-primary);
    line-height: 1.1;
    letter-spacing: -0.02em;
}

.bb-pseo-stat-label {
    font-size: 13px;
    color: var(--bb-text-muted);
    margin-top: 6px;
    line-height: 1.3;
}

@media (max-width: 640px) {
    .bb-pseo-stats-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 12px;
    }
    .bb-pseo-stat-value {
        font-size: 22px;
    }
    .bb-pseo-stat-label {
        font-size: 12px;
    }
}

/* =========================================================================
   Predictions Engine
   ========================================================================= */

.bb-predictions-page {
    padding-bottom: var(--bb-space-8, 32px);
}

/* Contest selector bar */
.bb-predictions-contest-bar {
    margin-bottom: var(--bb-space-4, 16px);
}
.bb-predictions-contest-tabs {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.bb-predictions-contest-tab {
    display: inline-flex;
    align-items: center;
    padding: 10px 20px;
    border-radius: var(--bb-radius, 10px);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    color: var(--bb-text-secondary);
    background: var(--bb-surface);
    border: 2px solid var(--bb-border);
    transition: all 0.2s ease;
}
.bb-predictions-contest-tab:hover {
    border-color: var(--bb-primary);
    color: var(--bb-primary);
}
.bb-predictions-contest-tab--active {
    background: var(--bb-primary);
    border-color: var(--bb-primary);
    color: #fff;
}
.bb-predictions-contest-tab--active:hover {
    color: #fff;
}

/* Division tabs overflow scroll */
.bb-predictions-division-tabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    margin-bottom: var(--bb-space-6, 24px);
}

/* Prediction card list */
.bb-predictions-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.bb-prediction-card {
    display: grid;
    grid-template-columns: 48px 1fr auto auto;
    gap: 16px;
    align-items: center;
    padding: 16px 20px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius, 10px);
    transition: all 0.2s ease;
}
.bb-prediction-card:hover {
    border-color: var(--bb-border-strong);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

/* Podium highlight */
.bb-prediction-card--gold {
    border-color: var(--bb-gold);
    background: linear-gradient(135deg, rgba(217, 139, 74, 0.04), rgba(217, 139, 74, 0.01));
}
.bb-prediction-card--silver {
    border-color: var(--bb-warm-grey-2);
    background: linear-gradient(135deg, rgba(34, 28, 24, 0.04), rgba(34, 28, 24, 0.01));
}
.bb-prediction-card--bronze {
    border-color: var(--bb-amber-dark);
    background: linear-gradient(135deg, rgba(217, 139, 74, 0.04), rgba(217, 139, 74, 0.01));
}

/* Rank column */
.bb-prediction-rank {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Athlete info */
.bb-prediction-athlete {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}
.bb-prediction-athlete-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.bb-prediction-athlete-name {
    font-weight: 600;
    font-size: 15px;
    color: var(--bb-text-primary);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bb-prediction-athlete-name:hover {
    color: var(--bb-primary);
}
.bb-prediction-athlete-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    color: var(--bb-text-muted);
}

/* Form trend indicators */
.bb-prediction-trend {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.bb-prediction-trend--up {
    color: var(--bb-moss-dark);
}
.bb-prediction-trend--down {
    color: var(--bb-danger);
}
.bb-prediction-trend--stable {
    color: var(--bb-text-muted);
}

/* Stats columns */
.bb-prediction-stats {
    display: flex;
    gap: 20px;
}
.bb-prediction-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-width: 70px;
}
.bb-prediction-stat-label {
    font-size: var(--bb-fs-2xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--bb-text-muted);
    font-weight: 600;
    white-space: nowrap;
}
.bb-prediction-stat-value {
    font-size: 13px;
    font-weight: 600;
    color: var(--bb-text-primary);
}

/* Confidence bar */
.bb-prediction-confidence {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    min-width: 90px;
}
.bb-prediction-confidence-value {
    font-size: 18px;
    font-weight: 700;
    color: var(--bb-text-primary);
    line-height: 1;
}
.bb-prediction-confidence-bar {
    width: 100%;
    height: 6px;
    background: var(--bb-gray-100);
    border-radius: 3px;
    overflow: hidden;
}
.bb-prediction-confidence-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.6s ease;
}
.bb-prediction-confidence-fill--high {
    background: linear-gradient(90deg, var(--bb-moss-dark), var(--bb-moss));
}
.bb-prediction-confidence-fill--mid {
    background: linear-gradient(90deg, var(--bb-amber-dark), var(--bb-amber));
}
.bb-prediction-confidence-fill--low {
    background: linear-gradient(90deg, var(--bb-danger), var(--bb-danger));
}

/* Community voting */
.bb-predictions-community {
    margin-top: var(--bb-space-8, 32px);
}
.bb-predictions-picks-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
    padding: 12px 16px;
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius, 10px);
    font-size: 14px;
}
.bb-predictions-vote-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.bb-predictions-vote-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border-radius: 999px;
    border: 2px solid var(--bb-border);
    background: var(--bb-surface);
    color: var(--bb-text-secondary);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.2s ease;
    font-family: inherit;
}
.bb-predictions-vote-btn:hover:not(:disabled) {
    border-color: var(--bb-primary);
    color: var(--bb-primary);
}
.bb-predictions-vote-btn--selected {
    background: var(--bb-primary);
    border-color: var(--bb-primary);
    color: #fff;
}
.bb-predictions-vote-btn--selected:hover:not(:disabled) {
    background: var(--bb-primary-hover, #c0392b);
    color: #fff;
}
.bb-predictions-vote-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.bb-predictions-vote-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.3);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
}

/* Community bar chart */
.bb-predictions-community-chart {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.bb-predictions-community-row {
    display: grid;
    grid-template-columns: 140px 1fr 50px;
    gap: 12px;
    align-items: center;
    font-size: 13px;
}
.bb-predictions-community-name {
    font-weight: 500;
    color: var(--bb-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bb-predictions-community-bar-wrap {
    height: 8px;
    background: var(--bb-gray-100);
    border-radius: 4px;
    overflow: hidden;
}
.bb-predictions-community-bar {
    height: 100%;
    border-radius: 4px;
    transition: width 0.4s ease;
    background: var(--bb-primary);
}
.bb-predictions-community-pct {
    font-weight: 600;
    color: var(--bb-text-secondary);
    text-align: right;
}

/* Historical accuracy */
.bb-predictions-accuracy {
    margin-top: var(--bb-space-8, 32px);
}

/* Responsive */
@media (max-width: 1024px) {
    .bb-prediction-card {
        grid-template-columns: 40px 1fr auto;
        gap: 12px;
    }
    .bb-prediction-stats {
        display: none;
    }
}

@media (max-width: 768px) {
    .bb-prediction-card {
        grid-template-columns: 1fr;
        gap: 12px;
        padding: 16px;
    }
    .bb-prediction-rank {
        position: absolute;
        top: 12px;
        right: 12px;
    }
    .bb-prediction-card {
        position: relative;
    }
    .bb-prediction-confidence {
        align-items: flex-start;
        min-width: 100%;
    }
    .bb-prediction-confidence-bar {
        max-width: 200px;
    }
    .bb-prediction-stats {
        display: flex;
        gap: 12px;
        flex-wrap: wrap;
    }
    .bb-prediction-stat {
        min-width: auto;
        align-items: flex-start;
    }
    .bb-predictions-community-row {
        grid-template-columns: 100px 1fr 40px;
        gap: 8px;
        font-size: 12px;
    }
    .bb-predictions-contest-tab {
        padding: 8px 14px;
        font-size: 13px;
    }
}

/* ==========================================================================
   FANTASY BODYBUILDING LEAGUE
   ========================================================================== */

/* --- Modal (shared) --- */
.bb-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    backdrop-filter: blur(2px);
}

.bb-modal {
    background: var(--bb-surface);
    border-radius: var(--bb-radius-xl);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
    width: 100%;
    max-width: 640px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.bb-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--bb-space-5) var(--bb-space-6);
    border-bottom: 1px solid var(--bb-gray-100);
}

.bb-modal-title {
    margin: 0;
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    color: var(--bb-text-primary);
}

.bb-modal-close {
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px;
    color: var(--bb-text-muted);
    border-radius: var(--bb-radius-sm);
    transition: background 0.15s, color 0.15s;
}

.bb-modal-close:hover {
    background: var(--bb-gray-100);
    color: var(--bb-text-primary);
}

.bb-modal-body {
    padding: var(--bb-space-6);
    overflow-y: auto;
    flex: 1;
}

.bb-modal-footer {
    padding: var(--bb-space-4) var(--bb-space-6);
    border-top: 1px solid var(--bb-gray-100);
    background: var(--bb-gray-50);
}

/* --- Fantasy Tabs --- */
.bb-fantasy-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 24px;
    padding: 4px;
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius-lg);
    border: 1px solid var(--bb-gray-200);
    overflow-x: auto;
}

.bb-fantasy-tab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    font-family: var(--bb-font-sans);
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-text-muted);
    background: transparent;
    border: none;
    border-radius: var(--bb-radius);
    cursor: pointer;
    transition: all 0.15s;
    white-space: nowrap;
}

.bb-fantasy-tab:hover {
    color: var(--bb-text-primary);
    background: var(--bb-surface);
}

.bb-fantasy-tab--active {
    color: var(--bb-primary);
    background: var(--bb-surface);
    box-shadow: var(--bb-shadow-sm);
}

.bb-fantasy-tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    font-size: 11px;
    font-weight: 700;
    background: var(--bb-primary);
    color: white;
    border-radius: var(--bb-radius-full);
}

/* --- How to Play --- */
.bb-fantasy-how-to-play {
    margin-bottom: 24px;
}

.bb-fantasy-rules-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: 16px;
    margin-bottom: 24px;
}

.bb-fantasy-rule {
    display: flex;
    gap: 12px;
    align-items: flex-start;
}

.bb-fantasy-rule-number {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bb-primary);
    color: white;
    font-weight: 700;
    font-size: var(--bb-fs-sm);
    border-radius: 50%;
}

.bb-fantasy-rule strong {
    display: block;
    margin-bottom: 2px;
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-primary);
}

.bb-fantasy-rule p {
    margin: 0;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    line-height: 1.4;
}

/* Points table */
.bb-fantasy-points-table {
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius);
    padding: 16px;
}

.bb-fantasy-points-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 0;
    font-size: var(--bb-fs-sm);
    border-bottom: 1px solid var(--bb-gray-200);
}

.bb-fantasy-points-row:last-child {
    border-bottom: none;
}

.bb-fantasy-points-label {
    color: var(--bb-text-secondary);
}

.bb-fantasy-points-value {
    font-weight: 700;
    font-family: var(--bb-font-mono);
}

.bb-fantasy-points-row--exact .bb-fantasy-points-value { color: var(--bb-green-600); }
.bb-fantasy-points-row--close .bb-fantasy-points-value { color: var(--bb-green-500); }
.bb-fantasy-points-row--near .bb-fantasy-points-value  { color: var(--bb-accent); }
.bb-fantasy-points-row--in .bb-fantasy-points-value    { color: var(--bb-accent-hover); }
.bb-fantasy-points-row--miss .bb-fantasy-points-value  { color: var(--bb-text-muted); }

/* --- Contest Grid --- */
.bb-fantasy-contest-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
    gap: 16px;
}

.bb-fantasy-contest-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: var(--bb-space-5);
}

.bb-fantasy-contest-info {
    flex: 1;
    min-width: 0;
}

.bb-fantasy-contest-name {
    margin: 4px 0;
    font-size: var(--bb-fs-base);
    /* Long contest names wrap instead of truncating, so the full name is
       always readable (a title attribute alone does not work on touch). */
    white-space: normal;
    overflow-wrap: break-word;
    word-break: break-word;
}

.bb-fantasy-contest-meta {
    display: flex;
    gap: 8px;
    font-size: var(--bb-fs-xs);
    flex-wrap: wrap;
}

.bb-fantasy-contest-pick-status {
    margin-top: 6px;
}

/* --- Pick Card (My Picks tab) --- */
.bb-fantasy-picks-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.bb-fantasy-pick-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.bb-fantasy-pick-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--bb-gray-50);
    border-radius: var(--bb-radius);
    transition: background 0.15s;
}

.bb-fantasy-pick-item:hover {
    background: var(--bb-gray-100);
}

.bb-fantasy-pick-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--bb-navy);
    color: white;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    flex-shrink: 0;
}

.bb-fantasy-pick-name {
    font-weight: 600;
    color: var(--bb-text-primary);
    font-size: var(--bb-fs-sm);
}

.bb-fantasy-pick-flag img {
    vertical-align: middle;
}

/* --- Pick Modal Slots --- */
.bb-fantasy-slots {
    margin-bottom: 20px;
}

.bb-fantasy-slot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    margin-bottom: 6px;
    border: 2px dashed var(--bb-gray-200);
    border-radius: var(--bb-radius);
    min-height: 48px;
    transition: border-color 0.15s, background 0.15s;
}

.bb-fantasy-slot--filled {
    border-style: solid;
    border-color: var(--bb-gray-200);
    background: var(--bb-surface);
}

.bb-fantasy-slot--empty {
    background: var(--bb-gray-50);
}

.bb-fantasy-slot-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--bb-navy);
    color: white;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    flex-shrink: 0;
}

.bb-fantasy-slot--empty .bb-fantasy-slot-rank {
    background: var(--bb-gray-300);
}

.bb-fantasy-slot-athlete {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
}

.bb-fantasy-slot-name {
    font-weight: 600;
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bb-fantasy-slot-flag img {
    vertical-align: middle;
}

.bb-fantasy-slot-remove {
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px;
    color: var(--bb-text-muted);
    border-radius: var(--bb-radius-sm);
    transition: background 0.15s, color 0.15s;
    margin-left: auto;
}

.bb-fantasy-slot-remove:hover {
    background: var(--bb-error-light);
    color: var(--bb-error);
}

.bb-fantasy-slot-placeholder {
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-sm);
    font-style: italic;
}

.bb-fantasy-slot-reorder {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex-shrink: 0;
}

.bb-fantasy-reorder-btn {
    background: var(--bb-gray-100);
    border: none;
    cursor: pointer;
    padding: 3px;
    border-radius: 4px;
    color: var(--bb-text-muted);
    transition: background 0.15s, color 0.15s;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bb-fantasy-reorder-btn:hover:not(:disabled) {
    background: var(--bb-primary-light);
    color: var(--bb-primary);
}

.bb-fantasy-reorder-btn:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

/* --- Athlete Search Results --- */
.bb-fantasy-search-section {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--bb-gray-100);
}

.bb-fantasy-athlete-results {
    margin-top: 8px;
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius);
    max-height: 240px;
    overflow-y: auto;
}

.bb-fantasy-athlete-result {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 10px 14px;
    border: none;
    background: var(--bb-surface);
    cursor: pointer;
    font-family: var(--bb-font-sans);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-primary);
    text-align: left;
    border-bottom: 1px solid var(--bb-gray-100);
    transition: background 0.1s;
}

.bb-fantasy-athlete-result:last-child {
    border-bottom: none;
}

.bb-fantasy-athlete-result:hover:not(:disabled) {
    background: var(--bb-primary-light);
}

.bb-fantasy-athlete-result--disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* --- Score Table --- */
.bb-fantasy-score-table {
    width: 100%;
}

.bb-fantasy-row--exact { background: rgba(69, 114, 63, 0.08); }
.bb-fantasy-row--close { background: rgba(69, 114, 63, 0.05); }
.bb-fantasy-row--near  { background: rgba(217, 139, 74, 0.06); }
.bb-fantasy-row--in    { background: rgba(217, 139, 74, 0.04); }
.bb-fantasy-row--miss  { }

.bb-fantasy-score-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 2px 8px;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    font-family: var(--bb-font-mono);
    border-radius: var(--bb-radius-full);
}

.bb-fantasy-score-badge--exact { background: var(--bb-green-soft); color: var(--bb-green-700); }
.bb-fantasy-score-badge--close { background: var(--bb-green-soft); color: var(--bb-green-600); }
.bb-fantasy-score-badge--near  { background: var(--bb-accent-soft); color: var(--bb-accent-hover); }
.bb-fantasy-score-badge--in    { background: var(--bb-accent-light); color: var(--bb-accent-hover); }
.bb-fantasy-score-badge--miss  { background: var(--bb-gray-100); color: var(--bb-text-muted); }

/* --- Total Score Display --- */
.bb-fantasy-total-score {
    display: flex;
    align-items: baseline;
    gap: 6px;
}

.bb-fantasy-score-number {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-2xl);
    font-weight: 800;
    color: var(--bb-primary);
}

.bb-fantasy-score-number--large {
    font-size: var(--bb-fs-3xl);
}

.bb-fantasy-score-label {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
    font-weight: 500;
}

/* --- Results List --- */
.bb-fantasy-results-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* --- Responsive --- */
@media (max-width: 640px) {
    .bb-fantasy-tabs {
        gap: 2px;
        padding: 3px;
    }

    .bb-fantasy-tab {
        padding: 8px 10px;
        font-size: var(--bb-fs-xs);
    }

    .bb-fantasy-tab svg {
        display: none;
    }

    .bb-fantasy-contest-grid {
        grid-template-columns: 1fr;
    }

    .bb-fantasy-contest-card {
        flex-direction: column;
        align-items: flex-start;
    }

    .bb-fantasy-contest-card .bb-btn {
        width: 100%;
    }

    .bb-fantasy-rules-grid {
        grid-template-columns: 1fr;
    }

    .bb-modal {
        max-height: 95vh;
        border-radius: var(--bb-radius-lg);
    }

    .bb-modal-overlay {
        padding: 8px;
    }

    .bb-fantasy-slot-reorder {
        flex-direction: row;
        gap: 4px;
    }
}

@media (max-width: 768px) {
    .bb-app .bb-th-breakdown,
    .bb-app .bb-td-breakdown { display: none; }
}

/* ==========================================================================
   THEME INTEGRATION
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    .bb-app *, .bb-app *::before, .bb-app *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ADDED 2026-04-04 - Page enrichment styles */
.bb-contest-summary{color:var(--bb-text-secondary);font-size:var(--bb-fs-sm);line-height:1.6;margin-bottom:var(--bb-space-4)}
.bb-past-editions{background:var(--bb-surface);border:1px solid var(--bb-gray-200);border-radius:var(--bb-radius-lg);padding:var(--bb-space-5);margin-top:var(--bb-space-5)}
.bb-past-editions h3{font-size:var(--bb-fs-base);font-weight:700;margin-bottom:var(--bb-space-3)}
.bb-past-editions-list{display:flex;flex-wrap:wrap;gap:8px}
/* P3-10b (WCAG 2.5.8 AA): inline-flex + min-height floors the pill at 24px tall (was
   ~21px from 4px padding on 13px text); horizontal padding already clears 24px wide. */
.bb-past-edition-link{display:inline-flex;align-items:center;justify-content:center;min-height:24px;padding:4px 12px;border-radius:20px;font-size:13px;font-weight:600;background:var(--bb-gray-100);color:var(--bb-text-secondary);text-decoration:none;transition:background .2s,color .2s}
.bb-past-edition-link:hover{background:var(--bb-primary);color:#fff}
.bb-past-edition--current{background:var(--bb-primary);color:#fff;pointer-events:none}
.bb-division-stats-grid{display:grid;grid-template-columns:repeat(4, minmax(0, 1fr));gap:var(--bb-space-4);margin-bottom:var(--bb-space-5)}
.bb-olympia-summary{display:flex;flex-wrap:wrap;gap:var(--bb-space-3);margin-bottom:var(--bb-space-4)}
.bb-badge--tier{font-size:11px;padding:2px 8px;border-radius:4px;font-weight:600}
.bb-badge--olympia{background:rgba(217, 139, 74,.15);color:var(--bb-amber-dark)}
.bb-badge--arnold{background:rgba(143, 90, 30, .15);color:var(--bb-navy)}
.bb-badge--major{background:var(--bb-gray-100);color:var(--bb-text-secondary)}
@media(max-width:768px){.bb-division-stats-grid{grid-template-columns:repeat(2, minmax(0, 1fr))}}
@media(max-width:480px){.bb-division-stats-grid{grid-template-columns:1fr}}
.bb-season-nav{display:flex;align-items:center;justify-content:center;gap:var(--bb-space-4);margin-bottom:var(--bb-space-5)}
.bb-season-nav-current{font-size:var(--bb-fs-lg);font-weight:700;color:var(--bb-text-primary)}
/* Last edition's winners on a fantasy pick card. Third line, quieter than the
   date, and it wraps rather than truncating: the names are the useful part. */
.bb-app .bb-fantasy-prior {
    display: block;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--bb-border-soft);
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-xs);
    line-height: 1.5;
}

/* Road to Olympia history chips. Sit beside the athlete name in a dense table,
   so they stay small and never push the row taller than the link. */
.bb-app .bb-rto-history-chip {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--bb-tint);
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    white-space: nowrap;
}
.bb-app .bb-rto-history-chip--champion {
    color: var(--bb-amber-on-light);
}

/* Olympia champions of the season. A list, not a table: one division and one
   name per row, and a table header for two columns earns nothing. */
.bb-app .bb-season-champions {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
    gap: 8px 20px;
    margin: 0 0 12px;
    padding: 0;
    list-style: none;
}
.bb-app .bb-season-champions li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    padding: 6px 0;
    border-bottom: 1px solid var(--bb-border-soft);
}
.bb-app .bb-season-champions__division {
    flex: 1 1 auto;
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.bb-season-narrative{border:1px solid rgba(178, 58, 53,.18);background:rgba(178, 58, 53,.04);padding:var(--bb-space-4);border-radius:var(--bb-radius-md);margin-bottom:var(--bb-space-5);line-height:1.7;color:var(--bb-text-secondary)}
.bb-country-highlights{margin-bottom:var(--bb-space-5)}
.bb-country-highlights .bb-stats-row{display:flex;flex-wrap:wrap;gap:var(--bb-space-5)}
.bb-country-highlights .bb-stat-item{display:flex;flex-direction:column;align-items:center;min-width:100px}
.bb-country-highlights .bb-stat-number{font-size:var(--bb-fs-xl);font-weight:800}
@media(max-width:640px){.bb-country-highlights .bb-stat-item{min-width:80px}}
.bb-rivals-section{margin-bottom:var(--bb-space-5)}
.bb-rivals-list{display:grid;grid-template-columns:repeat(auto-fill, minmax(min(280px, 100%), 1fr));gap:var(--bb-space-4)}
.bb-rival-card{display:flex;align-items:center;gap:var(--bb-space-3);padding:var(--bb-space-4);background:var(--bb-surface);border:1px solid var(--bb-gray-200);border-radius:var(--bb-radius-md);transition:box-shadow .2s}
.bb-rival-card:hover{border-color:rgba(178, 58, 53, 0.34)}
.bb-rival-avatar{position:relative;width:40px;height:40px;border-radius:50%;flex-shrink:0;overflow:hidden}
.bb-rival-avatar-img{width:100%;height:100%;object-fit:cover;display:block}
.bb-rival-avatar-fallback{display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:var(--bb-gray-200);color:var(--bb-navy);font-weight:700;font-size:var(--bb-fs-sm)}
.bb-rival-info{flex:1;min-width:0}
.bb-rival-h2h{text-align:right;font-size:var(--bb-fs-sm)}
.bb-rival-record{font-weight:700}
.bb-rival-wins{color:var(--bb-moss-dark)}
.bb-rival-losses{color:var(--bb-primary)}
.bb-rival-record-line{display:block;font-size:var(--bb-fs-sm);font-weight:600;color:var(--bb-text-primary);line-height:1.4}
.bb-rival-meta{display:block;font-size:11px;color:var(--bb-text-muted);margin-top:4px}
.bb-rival-h2h{display:flex;flex-direction:column;align-items:flex-end;gap:3px}
.bb-rival-verdict-badge{display:inline-block;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:2px 7px;border-radius:var(--bb-radius-sm)}
.bb-rival-verdict-badge--beat{background:rgba(69, 114, 63,.12);color:var(--bb-moss-dark)}
.bb-rival-verdict-badge--lost{background:rgba(178, 58, 53,.12);color:var(--bb-primary)}
.bb-rival-record-label{font-size:10px;color:var(--bb-text-muted);text-transform:uppercase;letter-spacing:.04em}
.bb-rival-card--beat{border-left:3px solid rgba(69, 114, 63,.55)}
.bb-rival-card--lost{border-left:3px solid rgba(178, 58, 53,.5)}
.bb-btn-xs{font-size:11px;padding:2px 10px;border-radius:var(--bb-radius-sm)}
@media(max-width:480px){.bb-rivals-list{grid-template-columns:1fr}}
.bb-related-card--athlete{display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--bb-space-2);padding:var(--bb-space-4)}
.bb-related-athlete-avatar{position:relative;width:56px;height:56px;border-radius:50%;flex-shrink:0;overflow:hidden}
.bb-related-athlete-avatar-img{width:100%;height:100%;object-fit:cover;display:block}
.bb-related-athlete-avatar-fallback{display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:var(--bb-gray-200);color:var(--bb-navy);font-weight:700}

/* ==========================================================================
   ATHLETE PROFILE PAGE - Visual Polish (appended)
   Scoped to .bb-athlete-profile-page to avoid side effects.
   ========================================================================== */

/* --- Keyframes --- */
@keyframes bb-profile-fade-up {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}
/* 1. Hero header - warm-gold radial glow, bottom-left */
.bb-athlete-profile-page .bb-profile-header {
    background-image:
        radial-gradient(ellipse 60% 55% at 10% 110%, rgba(178, 58, 53, 0.18) 0%, transparent 70%),
        var(--bb-dark-wash);
}

/* Name text-shadow for depth */
.bb-athlete-profile-page h1.bb-profile-name,
.bb-athlete-profile-page .bb-profile-name {
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
}

/* Avatar photo: subtle gold ring glow on hover */
.bb-athlete-profile-page .bb-profile-photo {
    transition: box-shadow 280ms var(--bb-ease-out);
}
.bb-athlete-profile-page .bb-profile-photo:hover {
    box-shadow: 0 0 0 3px rgba(217, 139, 74, 0.55), 0 0 20px rgba(217, 139, 74, 0.25);
}

/* P1-12: the active/success badge previously pulsed (bb-badge-pulse), animating
   low-contrast text and pulling the eye to the wrong element. Animation removed;
   the badge is now static and reads via its (AA-fixed) color alone. */

/* 2. Profile meta row - label-over-value columns, per claude-design.
   These were glass pills (translucent wash, blur, full radius). The prototype
   sets them as bare columns: a small mono uppercase label over a plain value,
   no container at all. The pill treatment also fought the ribbon and the
   at-a-glance card for surface attention; three competing glass surfaces is
   part of why the hero read as busy. Column layout itself lives in the base
   .bb-profile-detail rule; this keeps only the label face. */
.bb-athlete-profile-page .bb-profile-detail-label {
    font-family: var(--bb-font-mono);
    letter-spacing: 0.08em;
}

/* 3. Career stats: card lift on hover */
.bb-athlete-profile-page .bb-stats-career-summary .bb-stat-item {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
    padding: var(--bb-space-4) var(--bb-space-5);
    box-shadow: var(--bb-shadow-sm);
    transition: transform 220ms var(--bb-ease-out), box-shadow 220ms var(--bb-ease-out);
}
.bb-athlete-profile-page .bb-stats-career-summary .bb-stat-item:hover {
    transform: translateY(-3px);
    box-shadow: var(--bb-shadow-md);
}

/* Wins number stands out with accent */
.bb-athlete-profile-page .bb-stat-wins {
    color: var(--bb-accent);
    font-weight: var(--bb-weight-extrabold);
}

/* 4. Olympia stats card: premier-title medal gold (not the retired amber) */
.bb-athlete-profile-page .bb-stats-wsm {
    border: 1px solid rgba(143, 90, 30, 0.38);
    background: linear-gradient(135deg, rgba(143, 90, 30, 0.07) 0%, transparent 60%);
}

/* 5. Results table: no zebra (hairline rows), flat warm-gray hover, win-row
   keeps its functional gold tint (placement signal). */
.bb-athlete-profile-page .bb-results-table tbody tr:hover td {
    background: var(--bb-gray-50);
}
.bb-athlete-profile-page .bb-results-table tbody tr.bb-result-win td {
    background: rgba(143, 90, 30, 0.08);
}
.bb-athlete-profile-page .bb-results-table tbody tr.bb-result-win td:first-child {
    /* Deep AA gold (the bright accent failed contrast at table size). */
    color: #92600a;
    font-weight: 700;
}

/* 6. Section card hover shadow + fade-up entrance */
.bb-athlete-profile-page .bb-profile-section,
.bb-athlete-profile-page .bb-stats-box {
    animation: bb-profile-fade-up 420ms var(--bb-ease-out) both;
    transition: box-shadow 250ms var(--bb-ease-out);
}
.bb-athlete-profile-page .bb-profile-section:hover,
.bb-athlete-profile-page .bb-stats-box:hover {
    box-shadow: var(--bb-shadow-lg);
}

/* 7. Timeline dots: glow without scaling the nested tooltip */
.bb-athlete-profile-page .bb-career-timeline-dot:hover,
.bb-athlete-profile-page .bb-career-timeline-dot:focus-visible {
    transform: none;
    box-shadow: 0 0 0 4px rgba(217, 139, 74, 0.3);
    z-index: 2;
}

/* 8. Responsive: 640px stack */
@media (max-width: 640px) {
    .bb-athlete-profile-page .bb-profile-detail {
        padding: 4px 10px;
        font-size: var(--bb-fs-xs);
    }
    .bb-athlete-profile-page .bb-stats-career-summary .bb-stat-item {
        padding: var(--bb-space-3) var(--bb-space-4);
    }
    .bb-athlete-profile-page .bb-profile-section,
    .bb-athlete-profile-page .bb-stats-box {
        animation-duration: 300ms;
    }
}

/* Profile heading consistency fixes. The h2 size matches the app-wide section
   tier (.bb-app .bb-section-title in the route-wide layer) so "Championship
   Record" sits on the same step as "Career Timeline" / "Career Results". */
.bb-athlete-profile-page .bb-section-title,
.bb-athlete-profile-page .bb-stats-box-title,
.bb-athlete-profile-page .bb-stats-category-title {
    display: flex;
    align-items: center;
    gap: 8px;
    /*
     * px, not rem. The theme sets html { font-size: 15px }, so every rem in
     * this stylesheet computes 6.25% under its intended value: 1.375rem is
     * 20.6px, not 22, and 1.5rem is 22.5px, not 24. Both land off the
     * 32/26/24/22 H2 ladder, and both did so at every viewport - the type
     * conformance gate never saw it because these routes were not in its list.
     */
    font-size: clamp(var(--bb-fs-22), 2vw, var(--bb-fs-26));
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--bb-text-primary);
    margin-bottom: var(--bb-space-4);
    line-height: 1.3;
}
.bb-athlete-profile-page .bb-section-title svg,
.bb-athlete-profile-page .bb-stats-box-title svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--bb-primary);
}
.bb-athlete-profile-page .bb-stats-category-title {
    font-size: 0.875rem;
    margin-bottom: var(--bb-space-3);
}
/* Consistent section spacing */
.bb-athlete-profile-page .bb-profile-section,
.bb-athlete-profile-page .bb-stats-box {
    padding: var(--bb-space-5);
    margin-bottom: var(--bb-space-4);
}
/* Consistent stat number sizing */
.bb-athlete-profile-page .bb-stats-career-summary .bb-stat-number {
    font-size: 1.5rem;
    font-weight: 800;
    line-height: 1.1;
}
.bb-athlete-profile-page .bb-stats-career-summary .bb-stat-text {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
    color: var(--bb-text-muted);
    margin-top: 4px;
}
.bb-athlete-profile-page .bb-stats-career-summary {
    gap: var(--bb-space-4);
}

/* Profile width fix - remove fixed sidebar, use full width */
.bb-athlete-profile-page .bb-profile-content {
    grid-template-columns: 1fr;
    max-width: 100%;
}
@media (min-width: 1024px) {
    .bb-athlete-profile-page .bb-profile-content {
        grid-template-columns: 1fr;
    }
}

/* ==========================================================================
   ATHLETE PROFILE: Wave 3 trading-card hero + timeline centerpiece
   (plan 3.2). The three repeated stat clusters collapse to ONE (the hero
   "At a Glance" column); this adds the decisive accolade line, the gold
   champion ribbon, the relocated-under-hero timeline + placement sparkline,
   and the 44px touch targets the old 18px dots lacked. Designed median-first
   so a name+country+division+results profile reads as intentional.
   ========================================================================== */

/* --- Accolade: the credential eyebrow ABOVE the name ---
   claude-design leads with the credential and lets the name answer it, set as an
   uppercase mono pill with a plain amber outline. The old amber-wash gradient is
   gone: on a transparent chip the amber text sits straight on the ink header,
   where #d98b4a measures 6.21:1. */
.bb-app .bb-profile-accolade {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 var(--bb-space-2);
    padding: 5px 14px;
    background: transparent;
    border: 1px solid rgba(217, 139, 74, 0.55);
    border-radius: var(--bb-radius-full);
    color: var(--bb-amber-on-dark);
    font-family: var(--bb-font-mono);
    font-weight: 600;
    font-size: var(--bb-fs-2xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1.2;
}

/* --- Gold credential ribbon: champions only, top-right corner of the hero --- */
.bb-app .bb-profile-header--champion {
    border: 1px solid rgba(217, 139, 74, 0.28);
}
.bb-app .bb-profile-ribbon {
    position: absolute;
    top: 30px;
    right: -35px;
    z-index: 2;
    width: 170px;
    padding: 6px 0;
    transform: rotate(45deg);
    /* Solid amber, ink text: 6.21:1 everywhere on the ribbon.
       It was a gradient from --bb-amber to --bb-amber-dark with #4a3b00 text,
       which measured 4.04:1 at the light end and 1.90:1 at the dark end - so the
       accolade was least readable exactly where the ribbon is darkest, and a
       single-point contrast check passes or fails depending on which end it
       samples. A flat fill has one ratio, and ink is the palette's own text
       colour rather than a bespoke olive that appears nowhere else. */
    background: var(--bb-amber);
    color: var(--bb-ink);
    text-align: center;
    font-size: var(--bb-fs-2xs);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    pointer-events: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --- Timeline is now the centerpiece directly under the hero --- */
.bb-app .bb-athlete-profile-page.bb-core-route-handoff {
    grid-template-columns: minmax(0, 1fr);
}

.bb-app .bb-profile-timeline-section {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    /* It leads the body content, so it carries a touch more presence. */
    border-top: 3px solid var(--bb-accent, var(--bb-amber));
}

/* Placement sparkline figure (the one-shape career overview). Sits on the
   white section; the W1 kit owns the canvas/fallback styling. */
.bb-app .bb-profile-sparkline {
    margin: 0 0 var(--bb-space-4);
    padding: var(--bb-space-3) var(--bb-space-4) var(--bb-space-2);
    background: var(--bb-gray-50, #f8f9fa);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md, 10px);
}
.bb-app .bb-profile-sparkline .bb-chart__title {
    margin-bottom: var(--bb-space-2);
}

/* Peak-year highlight pill (the only non-duplicated timeline summary fact). */
.bb-app .bb-timeline-peak {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 var(--bb-space-4);
    padding: 6px 14px;
    /* Medal gold (matches the timeline's 1st-place dots), not the retired amber. */
    background: rgba(143, 90, 30, 0.1);
    border: 1px solid rgba(143, 90, 30, 0.38);
    border-radius: var(--bb-radius-full);
}
.bb-app .bb-timeline-peak-label {
    font-size: var(--bb-fs-2xs, 0.6875rem);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-muted);
}
.bb-app .bb-timeline-peak-value {
    font-weight: 700;
    color: var(--bb-text-primary);
    font-variant-numeric: tabular-nums;
}

/* --- Touch targets (P2-30): keep the modest 18px VISUAL dot but expand the
   interactive hit area via a transparent pseudo-element. Dots stack vertically
   at an 18px + 6px = 24px pitch, so a literal 44x44 halo would overlap the
   neighbour and steal its tap. Instead the hit area is a 44px-wide x 24px-tall
   PILL: generous horizontally, vertical capped to the pitch so adjacent halos
   just touch and never overlap. 44x24 clears the WCAG 2.5.8 AA 24px floor; the
   full Career Results table below remains the complete accessible path to every
   result, so the dots are supplementary. --- */
.bb-app .bb-career-timeline-dot::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 24px;
    transform: translate(-50%, -50%);
    border-radius: 12px;
    /* transparent: enlarges the tap/click target only */
}

@media (max-width: 768px) {
    /*
     * The corner ribbon comes off on a phone.
     *
     * It is a 160px band rotated 45 degrees, so its rendered box is 133px
     * square, and at top:12px that box starts 40px ABOVE .bb-profile-header__clip,
     * which is overflow:hidden. A corner ribbon is meant to be clipped by the
     * corner it runs off; this one was being sliced by an invisible edge partway
     * inside the card, leaving a blunt cut end hanging in the middle of the
     * hero. Measured at 375px: ribbon box top 152, clip container top 193.
     *
     * Pushing it down far enough to clear the cut puts it through the athlete
     * photograph, and widening it runs it past the card. The accolade pill
     * directly under the photo already reads "8X MR. OLYMPIA, 1998-2005", which
     * is the same claim plus the years, so nothing is lost by dropping the
     * decoration and the defect goes with it. Restoring the ribbon here means
     * fixing where the clip container starts, which is a change to the hero
     * rather than to the ribbon.
     */
    .bb-app .bb-profile-ribbon {
        display: none;
    }
    .bb-app .bb-profile-accolade {
        font-size: var(--bb-fs-xs);
    }
}

/* ==========================================================================
   OLYMPIA INDEX REDESIGN  (appended - overrides section 26)
   ========================================================================== */

/* --- Hero --- */
.bb-app .bb-olympia-hero {
    padding: 36px clamp(18px, 4.4vw, 40px);
    align-items: center;
    gap: 32px;
    min-height: 200px;
}

.bb-app .bb-olympia-hero .bb-hero-text {
    flex: 1;
    min-width: 0;
}

.bb-olympia-hero-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    /* On-dark hero kicker: light-warm label, not oxblood (AA on near-black). */
    color: rgba(255, 253, 248, 0.72);
    margin-bottom: var(--bb-space-3);
    position: relative;
    z-index: 1;
}

.bb-olympia-hero-eyebrow svg { color: rgba(255, 253, 248, 0.72); flex-shrink: 0; }

.bb-app .bb-olympia-hero .bb-page-title {
    /* Display tier: the olympia year is the page headline. */
    font-size: var(--bb-fs-page-title);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.05;
    margin-bottom: var(--bb-space-2);
    position: relative;
    z-index: 1;
}

.bb-app .bb-olympia-hero .bb-page-subtitle {
    font-size: var(--bb-fs-sm);
    color: rgba(255,255,255,0.65);
    margin-bottom: var(--bb-space-5);
    position: relative;
    z-index: 1;
}

/* Stat pills row inside hero */
.bb-olympia-hero-stats {
    display: inline-flex;
    align-items: center;
    gap: 0;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: var(--bb-radius-full);
    overflow: hidden;
    position: relative;
    z-index: 1;
}

.bb-olympia-hero-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 10px 24px;
    gap: 2px;
}

.bb-olympia-hero-stat-divider {
    width: 1px;
    height: 32px;
    background: rgba(255,255,255,0.12);
    flex-shrink: 0;
}

.bb-olympia-hero-stat-num {
    font-size: var(--bb-fs-lg);
    font-weight: 800;
    color: #ffffff;
    line-height: 1;
    letter-spacing: -0.02em;
}

.bb-olympia-hero-stat-label {
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.5);
}

/* Trophy icon in hero */
.bb-olympia-hero-icon {
    width: 120px;
    height: 120px;
    flex-shrink: 0;
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0.9;
}

.bb-olympia-hero-icon svg {
    width: 100%;
    height: 100%;
    filter: drop-shadow(0 0 20px rgba(217, 139, 74,0.3));
}

/* --- Timeline cards --- */
.bb-olympia-timeline {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
}

.bb-olympia-year-card {
    display: flex;
    gap: 0;
    background: var(--bb-surface);
    border: 1px solid rgba(217, 139, 74, 0.32);
    border-radius: var(--bb-radius-md);
    overflow: hidden;
    transition: box-shadow 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}

.bb-olympia-year-card:hover {
    box-shadow: 0 4px 18px rgba(0,0,0,0.08);
    border-color: rgba(178, 58, 53, 0.48);
    transform: translateY(-1px);
}

/* Year aside */
.bb-olympia-year-aside {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: var(--bb-space-5) var(--bb-space-4);
    background: var(--bb-gray-50);
    border-right: 1px solid var(--bb-gray-200);
    min-width: 88px;
    flex-shrink: 0;
}

.bb-olympia-year-num-link {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-decoration: none;
    /* WCAG 2.2 target size: the 61 year links measured 84x19 at 390px. */
    justify-content: center;
    min-height: 24px;
}

.bb-olympia-year-card .bb-olympia-year-num {
    font-size: 1.75rem;
    font-weight: 800;
    color: var(--bb-navy);
    letter-spacing: -0.04em;
    line-height: 1;
    transition: color 0.15s;
}

.bb-olympia-year-num-link:hover .bb-olympia-year-num { color: var(--bb-primary); }

.bb-olympia-year-arrow {
    color: var(--bb-gray-400);
    transition: color 0.15s, transform 0.15s;
}

.bb-olympia-year-num-link:hover .bb-olympia-year-arrow {
    color: var(--bb-primary);
    transform: translateX(2px);
}

/* Year body */
.bb-olympia-year-body {
    flex: 1;
    min-width: 0;
    padding: var(--bb-space-4) var(--bb-space-5);
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
}

/* Open champion spotlight */
.bb-olympia-open-champion {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
}

.bb-olympia-open-label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-accent);
    background: var(--bb-accent-light);
    padding: 3px 9px;
    border-radius: var(--bb-radius-full);
    flex-shrink: 0;
}

.bb-olympia-open-label svg { flex-shrink: 0; }

.bb-olympia-open-name {
    font-size: var(--bb-fs-md);
    font-weight: 700;
    color: var(--bb-navy);
    text-decoration: none;
    transition: color 0.15s;
}

.bb-olympia-open-name:hover { color: var(--bb-primary); }

.bb-olympia-open-country {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    font-weight: 500;
}

/* Reigns, turnover, closest finals and champion age. Four sections that read as
   one band above the year timeline, so they share a rule rather than each
   carrying a card border that would fragment the page. */
.bb-app .bb-olympia-insight {
    margin: 0 0 32px;
}
.bb-app .bb-olympia-insight > p {
    max-width: 68ch;
    margin: 0 0 12px;
    line-height: 1.6;
}
.bb-app .bb-olympia-insight__lede {
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-sm);
}
.bb-app .bb-olympia-insight__flag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--bb-tint);
    color: var(--bb-amber-on-light);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    white-space: nowrap;
}

/* Visually inert: the year's size and weight live on .bb-olympia-year-num, so the
   heading element only contributes document structure. */
.bb-olympia-year-heading {
    margin: 0;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    letter-spacing: inherit;
    color: inherit;
}

/* Division mini-cards grid */
.bb-olympia-divisions-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr));
    gap: var(--bb-space-2);
}

.bb-olympia-div-card {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 8px 12px;
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-sm);
    transition: border-color 0.15s, background 0.15s;
    min-width: 0;
}

.bb-olympia-div-card:hover {
    border-color: var(--bb-gray-300);
    background: var(--bb-gray-100);
}

/*
 * These labels wrap rather than clip.
 *
 * The grid is repeat(auto-fill, minmax(160px, 1fr)) and the label is 11px uppercase
 * with 0.07em tracking, so "MEN'S OPEN BODYBUILDING" needs about 196px including the
 * card's 24px of horizontal padding and never had it. With nowrap + ellipsis the
 * result was a wall of cut-off labels: measured on /olympia/ 146 clipped at 1440px,
 * 150 at 768px and 150 at 390px - essentially width-independent, because adding
 * viewport width just adds columns and leaves each tile at ~160px. Nine of the
 * eleven division names on every one of 61 year cards read "MEN'S OPEN BODYBU...".
 *
 * Two lines of small caps is not a layout problem; an unreadable label is. Grid rows
 * equalise their own height, so wrapping does not ragged the cards.
 */
.bb-olympia-div-name {
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
    /* Tracking on the last letter of a wrapped line pushes the box 1px wide. */
    overflow-wrap: anywhere;
}

/* Same for the winner: 19 to 29 names were cut off, e.g. "Ramon Rocha Que...". A
   name is the payload of this card, so it wraps rather than truncates. */
.bb-olympia-div-winner {
    font-size: var(--bb-fs-sm);
    font-weight: 700;
    color: var(--bb-navy);
    text-decoration: none;
    transition: color 0.15s;
    display: block;
    /*
     * WCAG 2.2 target size: 190 of these measured 136x21 at 390px, the largest single
     * group of undersized targets in the plugin. Vertical padding rather than
     * min-height or a switch to flex, because UI-44 fixed these labels to WRAP
     * instead of clip and changing the display type risks that.
     */
    padding-block: 2px;
}

.bb-olympia-div-winner:hover { color: var(--bb-primary); }

.bb-olympia-div-winner--empty {
    color: var(--bb-gray-400);
    font-weight: 500;
    font-style: italic;
}

/* Responsive */
@media (max-width: 768px) {
    .bb-app .bb-olympia-hero { padding: 24px 20px; gap: 20px; }
    .bb-app .bb-olympia-hero .bb-page-title { font-size: var(--bb-fs-page-title); }
    .bb-olympia-hero-icon { width: 80px; height: 80px; }
    .bb-olympia-divisions-grid { grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr)); }
    .bb-olympia-year-aside { min-width: 72px; padding: var(--bb-space-4) var(--bb-space-3); }
    .bb-olympia-year-card .bb-olympia-year-num { font-size: 1.4rem; }
}

@media (max-width: 540px) {
    /*
     * The padding here is DEAD and kept only so this block still reads as a whole.
     * `.bb-app .bb-olympia-hero-stat` at L19962 sets 24px 22px unconditionally, and a
     * media query adds no specificity, so 0,1,0 here never beat 0,2,0 there. The live
     * phone override now sits directly after that rule, where source order settles it.
     */
    .bb-olympia-hero-icon { display: none; }
    .bb-olympia-hero-stats { width: 100%; justify-content: stretch; }
    .bb-olympia-hero-stat { flex: 1; padding: 8px 12px; }
    .bb-olympia-year-card {
        flex-direction: column;
        border-top: none;
    }
    .bb-olympia-year-aside {
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        border-right: none;
        border-bottom: 1px solid var(--bb-gray-200);
        padding: var(--bb-space-3) var(--bb-space-4);
        min-width: unset;
        background: var(--bb-gray-50);
    }
    .bb-olympia-year-num-link {
        flex-direction: row;
        align-items: center;
        gap: var(--bb-space-2);
    }
    .bb-olympia-year-card .bb-olympia-year-num { font-size: 1.25rem; }
    .bb-olympia-divisions-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .bb-olympia-open-champion { gap: var(--bb-space-2); }
    /*
     * The shared section-heading rule at :19533 gives .bb-olympia-year-heading a
     * 2px ink rule, 20px of padding under it and 26px of margin below that. It
     * is the right treatment for a heading that opens a page section and the
     * wrong one for a year label repeated 61 times inside a card: measured at
     * 375px the aside stood 96px around a 24px number, and its 2px rule sat
     * 46px above the aside's own 1px divider, so every card drew two lines
     * under the same year.
     *
     * 61 cards x 50px is 3,050px of a 28,724px page.
     */
    .bb-app .bb-olympia-year-aside .bb-olympia-year-heading {
        margin: 0;
        padding-bottom: 0;
        border-bottom: 0;
    }
}

/* ==========================================================================
   ATHLETE PROFILE PAGE - About section accent bar (appended)
   ========================================================================== */

.bb-athlete-profile-page .bb-bio-text {
    /* Plain editorial prose on the card. The oxblood-tinted box spent the one
       accent on decoration (color only where it means something). */
    border: 0;
    padding: 0;
    margin-left: 0;
    background: transparent;
    color: var(--bb-text-secondary);
    line-height: 1.75;
    max-width: 70ch;
    margin-inline: auto;
}

.bb-athlete-profile-page .bb-profile-section--about .bb-section-title {
    max-width: 70ch;
    margin-inline: auto;
}
/* ==========================================================================
   ARNOLD CLASSIC INDEX REDESIGN  (matches Olympia pattern)
   ========================================================================== */

/* Hero: reuse Olympia hero styles, add subtle bronze accent tint */
.bb-arnold-hero.bb-olympia-hero {
    /* The Arnold hero uses the same dark header + stat pills as Olympia.
       Override accent color to amber/bronze for visual distinction. */
    --bb-arnold-accent: var(--bb-amber);
}

.bb-arnold-hero .bb-olympia-hero-eyebrow {
    /* On-dark hero kicker: light-warm label, not the Arnold orange (restraint
       + AA on the near-black hero). */
    color: rgba(255, 253, 248, 0.72);
}

.bb-arnold-hero .bb-olympia-hero-eyebrow svg {
    color: rgba(255, 253, 248, 0.72);
}

/* Arnold-specific hero icon sizing (trophy with handles) */
.bb-arnold-hero-icon {
    width: 120px;
    height: 120px;
    flex-shrink: 0;
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0.9;
}

.bb-arnold-hero-icon svg {
    width: 100%;
    height: 100%;
    filter: drop-shadow(0 0 20px rgba(217, 139, 74,0.35));
}

/* Responsive: hide Arnold trophy on small screens */
@media (max-width: 540px) {
    .bb-arnold-hero-icon { display: none; }
}

/* Arnold index: "View all divisions" CTA inside year card body */
.bb-arnold-year-cta {
    display: flex;
    align-items: center;
}

.bb-arnold-year-results-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: var(--bb-text-muted);
    text-decoration: none;
    transition: color 0.15s;
}

.bb-arnold-year-results-link:hover {
    color: var(--bb-primary);
}

.bb-arnold-year-results-link svg {
    transition: transform 0.15s;
}

.bb-arnold-year-results-link:hover svg {
    transform: translateX(2px);
}

/* Design tokens consolidated 2026-06-20 into the single .bb-app block under
   "1. DESIGN TOKENS" at the top of this file; this 2026-05-21 layer was removed
   and its unique tokens (border-soft, control-bg(-hover), text-tertiary, the
   shadow-sm fallback) merged up. */

.bb-app .bb-card,
.bb-app .bb-card-hover,
.bb-app .bb-card-interactive,
.bb-app .bb-stat-card,
.bb-app .bb-content-card,
.bb-app .bb-table-card,
.bb-app .bb-table-wrapper,
.bb-app .bb-content-table-wrapper,
.bb-app .bb-past-editions,
.bb-app .bb-rival-card,
.bb-app .bb-related-card,
.bb-app .bb-profile-section,
.bb-app .bb-stats-box {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    box-shadow: none;
}

.bb-app .bb-card,
.bb-app .bb-card-hover,
.bb-app .bb-card-interactive,
.bb-app .bb-stat-card,
.bb-app .bb-content-card {
    border-radius: var(--bb-radius-lg);
}

.bb-app .bb-card:hover,
.bb-app .bb-card-hover:hover,
.bb-app .bb-card-interactive:hover,
.bb-app .bb-stat-card:hover,
.bb-app .bb-content-card:hover,
.bb-app .bb-content-card--link:hover,
.bb-app .bb-rival-card:hover,
.bb-app .bb-related-card:hover,
.bb-app .bb-profile-section:hover,
.bb-app .bb-stats-box:hover {
    border-color: var(--bb-primary);
    box-shadow: none;
}

.bb-app .bb-content-card:hover,
.bb-app .bb-content-card--link:hover,
.bb-app .bb-card--link:hover,
.bb-app .bb-stat-card:hover {
    transform: translateY(-2px);
}

.bb-app .bb-card-header,
.bb-app .bb-card-footer,
.bb-app .bb-content-card__footer {
    border-color: var(--bb-border-soft);
}

.bb-app .bb-card-footer {
    background: var(--bb-gray-50);
}

.bb-app .bb-table-wrapper,
.bb-app .bb-content-table-wrapper,
.bb-app .bb-table-card {
    overflow: hidden;
    border-radius: var(--bb-radius-lg);
}

.bb-app .bb-table,
.bb-app .bb-content-table,
.bb-app .bb-results-table {
    font-variant-numeric: tabular-nums;
}

.bb-app .bb-table thead tr,
/* The header band is --bb-tint, the same warm tone the profile results table
   uses. It was --bb-gray-50, a shade cooler and flatter against the bone page,
   and because it was !important the profile could only answer it with a second
   !important - so one value had two owners and every other table kept the wrong
   one. Corrected here instead, and the profile's counter-override is gone.

   The !important stays only because the parent theme styles th directly and
   would otherwise win; it is answering the theme, not another plugin rule. */
.bb-app .bb-content-table thead tr,
.bb-app .bb-results-table thead tr {
    background: var(--bb-tint);
}

.bb-app .bb-table th,
.bb-app .bb-content-table thead th,
.bb-app .bb-results-table th {
    background: var(--bb-tint) !important;
    /* 1px hairline, not a 2px spine. The prototype separates a header band from
       its rows with the same hairline it uses everywhere else. */
    border-bottom: 1px solid var(--bb-border) !important;
    color: var(--bb-warm-grey-2) !important;
}

.bb-app .bb-table tbody tr,
.bb-app .bb-content-table tbody tr,
.bb-app .bb-results-table tbody tr {
    background: var(--bb-surface);
}

.bb-app .bb-table tbody tr:nth-child(even),
.bb-app .bb-content-table tbody tr:nth-child(even),
.bb-app .bb-results-table tbody tr:nth-child(even),
.bb-athlete-profile-page .bb-results-table tbody tr:nth-child(even) td {
    background: var(--bb-surface);
}

.bb-app .bb-table tbody tr:hover,
.bb-app .bb-content-table tbody tr:hover,
.bb-app .bb-results-table tbody tr:hover,
.bb-athlete-profile-page .bb-results-table tbody tr:hover td {
    /* Flat warm-gray row hover, not an accent wash (data-authority tables). */
    background: var(--bb-gray-50);
}

.bb-app .bb-btn {
    border: 2px solid transparent;
    box-shadow: none;
    transition:
        background-color var(--bb-transition),
        border-color var(--bb-transition),
        color var(--bb-transition),
        transform var(--bb-transition);
}

.bb-app .bb-btn-primary,
.bb-app .bb-btn--primary,
.bb-app .bb-btn-cta {
    background: var(--bb-primary);
    border-color: var(--bb-primary);
    color: #fff !important;
    box-shadow: none;
}

.bb-app .bb-btn-primary:hover:not(:disabled),
.bb-app .bb-btn--primary:hover:not(:disabled),
.bb-app .bb-btn-cta:hover:not(:disabled) {
    background: var(--bb-primary-hover);
    border-color: var(--bb-primary-hover);
    box-shadow: none;
    transform: translateY(-1px);
}

.bb-app .bb-btn-secondary,
.bb-app .bb-btn--secondary,
.bb-app .bb-btn-outline,
.bb-app .bb-btn--outline {
    background: var(--bb-surface);
    border: 2px solid var(--bb-border);
    color: var(--bb-text-primary) !important;
    box-shadow: none;
}

.bb-app .bb-btn-secondary:hover:not(:disabled),
.bb-app .bb-btn--secondary:hover:not(:disabled),
.bb-app .bb-btn-outline:hover:not(:disabled),
.bb-app .bb-btn--outline:hover:not(:disabled) {
    background: var(--bb-gray-50);
    border-color: var(--bb-border-strong);
    color: var(--bb-text-primary) !important;
}

.bb-app .bb-btn:disabled {
    background: var(--bb-gray-100);
    border-color: var(--bb-border);
    color: var(--bb-text-muted) !important;
    opacity: 1;
    transform: none;
}

.bb-app .bb-input,
.bb-app .bb-select,
.bb-app .bb-filter-input,
.bb-app select.bb-filter-select,
.bb-app .bb-search-input,
.bb-app .bb-nav-search-input,
.bb-app input[type="text"],
.bb-app input[type="search"],
.bb-app input[type="number"],
.bb-app input[type="email"],
.bb-app select,
.bb-app textarea {
    min-height: 44px;
    /* 38 on the right, not 14: the busy spinner sits there and a long query
       otherwise runs straight under it. */
    padding: 10px 38px 10px 14px;
    font-family: var(--bb-font-body);
    font-size: 14px;
    color: var(--bb-gray-800);
    background-color: var(--bb-control-bg);
    border: 1px solid var(--bb-border-strong, var(--bb-border));
    border-radius: var(--bb-radius);
    box-shadow: none;
    outline: none;
}

/* Single-line controls share one EXACT height so mixed toolbars (search +
   selects + per-page) sit on a single 44px line; only textarea stays fluid.
   Hairline borders above match the editorial retheme (cards/rules are 1px). */
.bb-app .bb-input,
.bb-app .bb-select,
.bb-app .bb-filter-input,
.bb-app select.bb-filter-select,
.bb-app .bb-search-input,
.bb-app input[type="text"],
.bb-app input[type="search"],
.bb-app input[type="number"],
.bb-app input[type="email"],
.bb-app select {
    height: 44px;
}

.bb-app .bb-input-with-icon,
.bb-app .bb-input--search,
.bb-app .bb-search-input,
.bb-app .bb-toolbar-search__input,
.bb-app .bb-toolbar-search .bb-toolbar-search__input {
    padding-left: 40px;
}

.bb-app .bb-select,
.bb-app select.bb-filter-select,
.bb-app select.bb-toolbar-filter__select {
    padding-right: 36px;
}

.bb-app .bb-input:hover:not(:focus):not(:disabled),
.bb-app .bb-select:hover:not(:focus):not(:disabled),
.bb-app .bb-filter-input:hover:not(:focus):not(:disabled),
.bb-app select:hover:not(:focus):not(:disabled),
.bb-app textarea:hover:not(:focus):not(:disabled) {
    border-color: var(--bb-border-strong);
    background-color: var(--bb-control-bg-hover);
}

.bb-app .bb-input:focus,
.bb-app .bb-select:focus,
.bb-app .bb-filter-input:focus,
.bb-app select:focus,
.bb-app textarea:focus,
.bb-app .bb-nav-search-input:focus {
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
    background-color: var(--bb-surface);
}

.bb-app .bb-filter-bar,
.bb-app .bb-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: var(--bb-space-4);
    padding: 0;
    background: transparent;
    border: none;
    box-shadow: none;
}

.bb-app .bb-tabs,
.bb-app .bb-toolbar-tabs,
.bb-app .bb-filter-tabs,
.bb-app .bb-tab-bar,
.bb-app .bb-division-filter {
    display: flex;
    gap: 0;
    overflow-x: auto;
    border-bottom: 2px solid var(--bb-border);
    scrollbar-width: none;
}

.bb-app .bb-tabs::-webkit-scrollbar,
.bb-app .bb-toolbar-tabs::-webkit-scrollbar,
.bb-app .bb-filter-tabs::-webkit-scrollbar,
.bb-app .bb-tab-bar::-webkit-scrollbar,
.bb-app .bb-division-filter::-webkit-scrollbar {
    display: none;
}

.bb-app .bb-tab,
.bb-app .bb-toolbar-tab,
.bb-app .bb-filter-tab,
.bb-app .bb-filter-btn,
.bb-app .bb-tab-btn {
    min-height: 44px;
    padding: 10px 18px;
    color: var(--bb-text-muted);
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    box-shadow: none;
}

.bb-app .bb-tab:hover,
.bb-app .bb-toolbar-tab:hover,
.bb-app .bb-filter-tab:hover,
.bb-app .bb-filter-btn:hover,
.bb-app .bb-tab-btn:hover {
    color: var(--bb-text-primary);
    background: transparent;
}

.bb-app .bb-tab--active,
.bb-app .bb-toolbar-tab--active,
.bb-app .bb-filter-tab--active,
.bb-app .bb-filter-btn-active,
.bb-app .bb-filter-btn.active,
.bb-app .bb-tab-btn.active {
    color: var(--bb-primary);
    background: transparent;
    border-bottom-color: var(--bb-primary);
}

/* Keyboard focus must be visible on the filter/tab strips (the route-wide
   .bb-app .bb-filter-btn reset above otherwise swallows the toolbar-tab
   focus-visible ring). */
.bb-app .bb-filter-btn:focus-visible,
.bb-app .bb-tab-btn:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}

.bb-app .bb-badge,
.bb-app .bb-content-card__badge,
.bb-app .bb-section-label,
.bb-app .bb-placement,
.bb-app .bb-rank-badge {
    border: 1px solid transparent;
    font-weight: 700;
    letter-spacing: 0.04em;
}

/*
 * The prototype badge is weight 600. The group above is (0,2,0) and set 700, so
 * the base .bb-badge rule at (0,1,0) could not reach it - which is why the badge
 * kept rendering 700 after the base was corrected.
 *
 * Split rather than changed in place: .bb-placement and .bb-rank-badge are
 * numerals whose whole job is to read as emphasis, and they keep 700.
 *
 * nowrap because the prototype badge is uniformly single-line at 26px, while 141
 * of 570 here grew to a second line on a long division name. One class rendering
 * at two heights is most of what makes a page look unsettled. Every badge that
 * wraps sits inside a table cell, and those tables already carry scroll wrappers,
 * so the column widens rather than the document overflowing.
 */
.bb-app .bb-badge {
    font-weight: 600;
    white-space: nowrap;
}

.bb-app .bb-badge--default,
.bb-app .bb-badge-neutral,
.bb-app .bb-badge--division,
.bb-app .bb-content-card__badge--gray {
    background: var(--bb-gray-100);
    border-color: var(--bb-border-soft);
    color: var(--bb-gray-700);
}

.bb-app .bb-badge--primary,
.bb-app .bb-badge--female,
.bb-app .bb-section-label {
    background: var(--bb-primary-light);
    border-color: rgba(178, 58, 53, 0.18);
    color: var(--bb-primary-hover);
}

.bb-app .bb-badge--info,
.bb-app .bb-badge--male {
    background: rgba(34, 28, 24, 0.08);
    border-color: rgba(34, 28, 24, 0.16);
    color: var(--bb-navy-mid);
}

/* --bb-accent-light is the OXBLOOD tint (rgba(168,55,42,.1)) - correctly named,
   since --bb-accent resolves to oxblood. This is the amber/medal family, so it was
   putting amber text on an oxblood wash: the badge disagreed with itself about
   which accent it belonged to. Amber tint with --bb-amber-deep text reads as one
   colour and measures 6.13:1 on bone, 6.56:1 on paper. */
.bb-app .bb-badge--gold,
.bb-app .bb-badge--elite,
.bb-app .bb-badge--warning,
.bb-app .bb-badge--olympia,
.bb-app .bb-placement--gold,
.bb-app .bb-place-badge--gold {
    background: rgba(217, 139, 74, 0.12);
    border-color: rgba(217, 139, 74, 0.24);
    color: var(--bb-amber-deep);
}

/* P3-12: background + border live on the single route-wide source (section near L11936). */
.bb-app .bb-page-header,
.bb-app .bb-page-header.bb-page-header-dark,
.bb-app .bb-page-header.bb-page-header--dark {
    display: flex;
    align-items: center;
    gap: var(--bb-space-6);
    padding: 40px clamp(18px, 4.4vw, 48px);
    margin-bottom: var(--bb-space-8);
    border-radius: var(--bb-radius-xl);
    box-shadow: none;
}

.bb-app .bb-page-header::before,
.bb-app .bb-page-header.bb-page-header-dark::before,
.bb-app .bb-page-header.bb-page-header--dark::before {
    width: 360px;
    height: 360px;
    top: -110px;
    right: -80px;
    background:
        radial-gradient(circle, rgba(217, 139, 74, 0.16) 0%, transparent 54%),
        radial-gradient(circle, rgba(178, 58, 53, 0.12) 0%, transparent 68%);
}

.bb-app .bb-page-header::after {
    content: '';
    position: absolute;
    inset: auto -70px -130px auto;
    width: 420px;
    height: 170px;
    background: rgba(255, 255, 255, 0.08);
    transform: rotate(-16deg);
    z-index: 0;
    pointer-events: none;
}

.bb-app .bb-page-header > * {
    position: relative;
    z-index: 1;
}

.bb-app .bb-page-header .bb-page-title {
    /* Display tier: the page H1 leads big. */
    font-size: var(--bb-fs-page-title);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.05;
}

.bb-app .bb-page-header .bb-page-subtitle,
.bb-app .bb-page-header .bb-page-desc {
    max-width: 720px;
    line-height: 1.65;
}

.bb-app .bb-section-header {
    text-align: center;
    margin-bottom: var(--bb-space-10);
}

.bb-app .bb-section-title,
.bb-app .bb-section-heading,
.bb-app .bb-heading-section {
    /* Section tier: a clearly smaller, lighter step below the display H1 so the
       three-tier hierarchy reads (display 800 > section 700 > label). Warm ink,
       not the cool slate gray-800 (off the warm-paper palette). */
    /*
     * px, not rem. The theme sets html { font-size: 15px }, so every rem in
     * this stylesheet computes 6.25% under its intended value: 1.375rem is
     * 20.6px, not 22, and 1.5rem is 22.5px, not 24. Both land off the
     * 32/26/24/22 H2 ladder, and both did so at every viewport - the type
     * conformance gate never saw it because these routes were not in its list.
     */
    font-size: clamp(var(--bb-fs-22), 2vw, var(--bb-fs-26));
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--bb-text-primary);
}

.bb-app .bb-stat-card-value,
.bb-app .bb-stat-number,
.bb-app .bb-rank-badge,
.bb-app .bb-placement {
    font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
    .bb-app .bb-page-header,
    .bb-app .bb-page-header.bb-page-header-dark,
    .bb-app .bb-page-header.bb-page-header--dark {
        display: block;
        padding: 24px 18px;
        border-radius: var(--bb-radius-lg);
    }

    .bb-app .bb-page-header .bb-page-title {
        /* The shared token's own clamp already handles narrow phones: it floors
           at 30px. This override held clamp(1.875rem, 8vw, 2.25rem), and 8vw of
           a 390px viewport is 31.2px, which is why Arnold and compare sat out of
           step with every other title at mobile widths. */
        font-size: var(--bb-fs-page-title);
    }

    .bb-app .bb-filter-bar,
    .bb-app .bb-toolbar {
        flex-direction: column;
        align-items: stretch;
    }

    .bb-app .bb-filter-bar > *,
    .bb-app .bb-toolbar > *,
    .bb-app .bb-filter-bar > .bb-filter-select,
    .bb-app .bb-toolbar > .bb-filter-select,
    .bb-app .bb-filter-bar > .bb-toolbar-filter,
    .bb-app .bb-toolbar > .bb-toolbar-filter,
    .bb-app .bb-filter-bar > .bb-per-page-select,
    .bb-app .bb-toolbar > .bb-per-page-select {
        width: 100%;
        max-width: none;
        margin-left: 0;
    }

    .bb-app .bb-tabs,
    .bb-app .bb-toolbar-tabs,
    .bb-app .bb-filter-tabs,
    .bb-app .bb-tab-bar {
        margin-left: calc(var(--bb-space-4) * -1);
        margin-right: calc(var(--bb-space-4) * -1);
        padding-left: var(--bb-space-4);
        padding-right: var(--bb-space-4);
    }

    .bb-rankings-page .bb-tabs,
    .bb-rankings-page .bb-toolbar-tabs,
    .bb-goat-page .bb-tabs,
    .bb-goat-page .bb-toolbar-tabs {
        margin-left: 0;
        margin-right: 0;
        padding-left: 0;
        padding-right: 0;
    }

    .bb-app .bb-division-filter {
        flex-wrap: wrap;
        overflow-x: visible;
        gap: var(--bb-space-2) 0;
        margin-left: 0;
        margin-right: 0;
        padding-left: 0;
        padding-right: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .bb-app .bb-content-card:hover,
    .bb-app .bb-content-card--link:hover,
    .bb-app .bb-card--link:hover,
    .bb-app .bb-stat-card:hover,
    .bb-app .bb-btn-primary:hover:not(:disabled),
    .bb-app .bb-btn--primary:hover:not(:disabled),
    .bb-app .bb-btn-cta:hover:not(:disabled) {
        transform: none;
    }
}

/* ==========================================================================
   HUB STANDARDIZATION - 2026-05-21
   Brings older inline-styled hub modules back onto the shared design system.
   ========================================================================== */

.bb-app .bb-nav-search-inline .bb-nav-search-input {
    padding-left: 40px;
}

.bb-app .bb-nav-search-inline .bb-nav-search-icon {
    color: var(--bb-text-tertiary);
}

.bb-app .bb-olympia-hub-widget {
    margin-bottom: var(--bb-space-8) !important;
}

/* Three rule blocks used to sit here, all keyed on
   `.bb-olympia-hub-widget > .bb-olympia-card`. NO template emits
   `.bb-olympia-card` - the widget's card is `.bb-olympia-hub-card` - so all
   three were dead, and had been since the widget was de-inlined to classes.
   Between them they restated the dark espresso gradient, a white-tint border and
   white-tint pill fills, every declaration `!important`. Had the class ever come
   back they would have silently overridden the light card the brief asks for.

   This is the second time this exact selector chain has gone stale here: the
   comment that used to sit in the middle of the block already recorded four DEAD
   `[style*="#d4af37"]` overrides removed for the same reason. The lesson is the
   one above the pill rules - a dead `!important` is not harmless, it is a trap
   armed for whoever renames a class back. */

/* Welcome-back banner.
   Every !important here was fighting the nine inline style attributes the markup
   used to carry (hub.php). The inline styles are gone, so the !importants are
   too - they had already outlived their cause, which is how a stylesheet ends up
   unable to restyle its own components.

   The banner is now flex for real. The old inline rule set align-items,
   justify-content, gap and flex-wrap but never set `display`, and no class rule
   supplied it either, so all four were inert and the banner was a plain block. */
.bb-app .bb-welcome-back {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--bb-space-4);
    padding: var(--bb-space-4) var(--bb-space-5);
    margin-bottom: var(--bb-space-6);
    border: 1px solid var(--bb-border);
    border-left: 3px solid var(--bb-primary);
    border-radius: var(--bb-radius-lg);
    background: var(--bb-surface-sunken);
    box-shadow: none;
    font-size: var(--bb-fs-sm);
}

/* .bb-hidden is what the JS toggles. It has to beat display:flex above, and it
   is the one place a !important is doing real work: a hidden banner that paints
   is a bug, and `hidden` alone loses to any display declaration. */
.bb-app .bb-welcome-back.bb-hidden,
.bb-app .bb-welcome-back[hidden] {
    display: none !important;
}

.bb-app .bb-welcome-back__body {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
}

.bb-app .bb-welcome-back__title {
    font-family: var(--bb-font-heading);
    font-weight: 700;
    color: var(--bb-text-primary);
}

.bb-app .bb-welcome-back__message {
    color: var(--bb-text-secondary);
}

.bb-app .bb-welcome-back__actions {
    display: flex;
    align-items: center;
    gap: var(--bb-space-2);
}

.bb-app .bb-welcome-back__dismiss {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: var(--bb-touch-min);
    min-height: var(--bb-touch-min);
    padding: 0;
    font-size: var(--bb-fs-lg);
    line-height: 1;
    color: var(--bb-text-secondary);
    background: none;
    border: 1px solid transparent;
    border-radius: var(--bb-radius);
    cursor: pointer;
}

.bb-app .bb-welcome-back__dismiss:hover {
    color: var(--bb-text-primary);
    background: var(--bb-surface-raised);
    border-color: var(--bb-border);
}

/* Design tokens consolidated 2026-06-20 into the single .bb-app block under
   "1. DESIGN TOKENS" at the top of this file; this route-wide polish layer was
   removed and all its winning token values merged up. */

/* An @supports (color: oklch(...)) block used to sit here restating --bb-bg,
   --bb-surface, --bb-gray-50/100/200, --bb-navy and --bb-navy-mid on .bb-app.
   Removed 2026-07-29 with the Iron & Bone palette.

   Its own comment already understood the hazard and deliberately kept the
   accent tokens out, on the grounds that this was the LAST declaration on
   oklch-capable browsers and would beat the single oxblood source. The two it
   did keep were the problem: oklch(18% 0.035 278) and oklch(31% 0.075 250) are
   hue 278 and hue 250 - violet and blue. So on every modern browser the navy
   ramp resolved here, at .bb-app specificity, not in :root.

   That is why the blue kept surviving edits to the token block: there were two
   builders for one value and the winning one was 12,700 lines away. Retiring
   blue in :root alone would have changed nothing that a user could see.

   What it bought was a marginally wider-gamut warm tint on four surface
   tokens. That is not in the design, which is specified in hex throughout, and
   it is not worth a second source of truth for colour (rule 17). */

.bb-app {
    /*
     * The page canvas. ONE owner for this value; .bb-app::before near the top of
     * the file paints the same token full-bleed so the gutters either side of
     * the 356px wrapper are not left white on a phone.
     *
     * Was `#fff !important` under a 2026-06-02 owner directive that removed a
     * cream tint and radial brand glows. Superseded 2026-08-06, on two grounds:
     * Iron & Bone landed on 2026-07-29, eight weeks after that directive, and
     * specifies bone as the paper base with raised surfaces in white; and the
     * owner chose bone from side-by-side screenshots of both grounds at 375px.
     *
     * This is not the cream tint the old directive removed. There are no
     * gradients and no glows here, just the flat --bb-bone the token layer has
     * defined since July.
     */
    background: var(--bb-bone) !important;
}

/* Host for portaled overlays: modals and toasts that must sit on <body> to
   escape the theme's stacking context. It carries the .bb-app scope and its
   design tokens to those nodes (see bbPortalHost in bb-ui.js) without becoming
   a visible box itself, so the page canvas rule above must not apply to it. */
.bb-app.bb-portal {
    background: none !important;
    max-width: none;
    margin: 0;
    padding: 0;
    /* A transform, filter or perspective here would make this host the containing
       block for its own position:fixed children, which is the exact bug that
       pushed these overlays onto document.body in the first place. Pinned so a
       future rule on .bb-app cannot reintroduce it. */
    transform: none;
    filter: none;
    perspective: none;
}

/* Was max-width 1192, which left the app's own content inset a further 84px a
   side inside an already full-bleed .bb-app - the plugin re-boxing what the
   theme had just been told to stop boxing. claude-design runs its content to
   about 1360 at a 1440 viewport, which is exactly what .bb-main now measures,
   so the container fills its parent and the single gutter lives on .bb-app. */
.bb-app .bb-container {
    max-width: none;
}

.bb-app .bb-nav {
    background:
        linear-gradient(90deg, rgba(255, 253, 248, 0.96), rgba(255, 253, 248, 0.9)),
        radial-gradient(circle at 18% 0%, rgba(178, 58, 53, 0.08), transparent 18rem);
    border: 1px solid rgba(34, 28, 24, 0.08);
    border-radius: 0 0 var(--bb-radius-xl) var(--bb-radius-xl);
    box-shadow: 0 12px 34px rgba(34, 28, 24, 0.06);
}

.bb-app .bb-nav-logo-text {
    font-family: var(--bb-font-heading);
    font-stretch: condensed;
    letter-spacing: 0.035em;
}

.bb-app .bb-nav-link,
.bb-app .bb-nav-dropdown-trigger,
.bb-app .bb-toolbar-tab,
.bb-app .bb-filter-tab,
.bb-app .bb-filter-btn {
    font-family: var(--bb-font-heading);
    letter-spacing: 0.01em;
}

.bb-app .bb-nav-group-active,
.bb-app .bb-nav-link:hover,
.bb-app .bb-nav-dropdown[data-open="true"] .bb-nav-dropdown-trigger {
    background: var(--bb-primary-light);
    color: var(--bb-text-primary);
}

.bb-app .bb-page-header,
.bb-app .bb-page-header.bb-page-header-dark,
.bb-app .bb-page-header.bb-page-header--dark,
.bb-athlete-profile-page .bb-profile-header,
.bb-app .bb-hero,
.bb-app .bb-rto-cta-card,
.bb-app .bb-featured-card {
    /* P3-12: single source of truth for hero/header background after removing the
       three superseded earlier definitions, so !important is no longer needed here.
       POLISH PASS 3: the band itself was the last cool-navy survivor of the
       editorial retheme (#171523 -> #12365a -> #244763). Warmed onto the ink/
       espresso axis of the warm-paper palette; the oxblood + amber glows stay. */
    background:
        radial-gradient(ellipse 52% 70% at 100% 0%, rgba(217, 139, 74, 0.16), transparent 58%),
        radial-gradient(ellipse 44% 50% at 8% 110%, rgba(178, 58, 53, 0.24), transparent 64%),
        linear-gradient(135deg, #1d1916 0%, #2b211a 62%, #3c2c21 100%);
    border: 1px solid rgba(255, 253, 248, 0.12);
    box-shadow: 0 24px 70px rgba(27, 24, 21, 0.2);
}

/* Display tier: page H1 (athlete name, contest name, olympia year, hero title)
   plus the SSR summary name. Weight 800, tight tracking. */
.bb-app .bb-page-title,
.bb-app .bb-page-header .bb-page-title,
.bb-athlete-profile-page .bb-profile-name,
.bb-app .bb-heading-hero,
.bb-app .bb-ssr-summary__name,
.bb-app #bb-ssr-h1 {
    font-family: var(--bb-font-heading);
    font-weight: 800;
    letter-spacing: -0.02em;
}

/* Section tier sits a clear step below the display H1: same family, lighter
   weight and tracking so the hierarchy is obvious. */
.bb-app .bb-heading-section,
.bb-app .bb-section-heading {
    font-family: var(--bb-font-heading);
    font-weight: 700;
    letter-spacing: -0.015em;
}

.bb-app .bb-page-header .bb-page-title,
.bb-app .bb-page-header .bb-page-subtitle,
.bb-app .bb-page-header .bb-page-desc,
.bb-athlete-profile-page .bb-profile-name,
.bb-app .bb-hero .bb-heading-hero,
.bb-app .bb-hero .bb-heading-hero-sub,
.bb-app .bb-hero .bb-hero-description,
.bb-app .bb-rto-cta-card,
.bb-app .bb-featured-card {
    color: var(--bb-on-dark) !important;
}

.bb-app .bb-hero .bb-heading-hero:not(.bb-hero-tagline) {
    /* W3: the hub h1 is the real headline now, not a faint backdrop label behind a
       separate .bb-hero-tagline (a pattern no template emits). Restore full contrast
       so the headline reads as the anchor and clears WCAG AA on the navy gradient. */
    color: var(--bb-on-dark) !important;
    font-size: var(--bb-fs-page-title);

    /*
     * max-width was 14ch and line-height 0.95, and between them they built the wall
     * of text this hero was reported for. The headline is "The world's most complete
     * bodybuilding resource" - 47 characters. A 14ch column wraps that to FOUR lines,
     * and at the old 72px with 0.95 leading that is ~273px of headline before the
     * description, buttons or stat row are counted. The old comment claimed "sizing
     * kept as-is", which is how a constraint this strong stayed invisible.
     *
     * 26ch fits those 47 characters on two lines while keeping the measure well short
     * of a full-width banner headline, so it still reads as a stacked display block
     * rather than a paragraph.
     *
     * Leading goes to 1.08. Sub-1.0 is a legitimate choice for a display headline that
     * occupies ONE line, and it is what the desktop tier was written for - but this one
     * wraps at every width, and leading below the type size on wrapped lines is exactly
     * the defect test-page-title-scale.mjs calls "crushed". It closed four lines into a
     * solid block.
     */
    line-height: 1.08;
    max-width: 26ch;
}

.bb-app .bb-hero .bb-hero-tagline {
    color: var(--bb-on-dark) !important;
    font-size: clamp(2.4rem, 5vw, 5rem);
    line-height: 0.92;
    text-wrap: balance;
}

.bb-app .bb-hero .bb-hero-subtitle {
    color: rgba(255, 253, 248, 0.78) !important;
}

.bb-app .bb-hero-badge,
.bb-app .bb-section-label {
    background: rgba(255, 253, 248, 0.1);
    border: 1px solid rgba(255, 253, 248, 0.16);
    border-radius: var(--bb-radius-full);
}

.bb-app .bb-card,
.bb-app .bb-card-hover,
.bb-app .bb-card-interactive,
.bb-app .bb-stat-card,
.bb-app .bb-content-card,
.bb-app .bb-table-wrapper,
.bb-app .bb-content-table-wrapper,
.bb-app .bb-profile-section,
.bb-app .bb-stats-box,
.bb-app .bb-news-card,
.bb-app .bb-past-editions,
.bb-app .bb-otd-event-card,
.bb-app .bb-rival-card,
.bb-app .bb-related-card {
    background:
        linear-gradient(180deg, rgba(255, 253, 248, 0.96), rgba(255, 253, 248, 0.88)),
        var(--bb-surface);
    border: 1px solid var(--bb-border);
    /* Hairline cards: the 1px hairline + a tight contact edge only. The former
       12px/32px ambient layer (and the 20px/48px hover bloom below) read as
       floating SaaS chrome against the editorial hairline language. */
    box-shadow: 0 1px 2px rgba(34, 28, 24, 0.07);
}

/* Interactive cards signal hover via the accent hairline, not a shadow bloom.
   .bb-profile-section / .bb-stats-box are static containers and no longer
   pretend to be clickable on hover. */
.bb-app .bb-card:hover,
.bb-app .bb-card-hover:hover,
.bb-app .bb-card-interactive:hover,
.bb-app .bb-stat-card:hover,
.bb-app .bb-content-card:hover,
.bb-app .bb-content-card--link:hover,
.bb-app .bb-news-card:hover,
.bb-app .bb-rival-card:hover,
.bb-app .bb-related-card:hover {
    border-color: rgba(178, 58, 53, 0.34);
    box-shadow: 0 1px 2px rgba(34, 28, 24, 0.07);
}

.bb-app .bb-stat-number,
.bb-app .bb-stat-card-value,
.bb-app .bb-rank-badge,
.bb-app .bb-placement,
.bb-app .bb-olympia-year-num {
    font-family: var(--bb-font-heading);
    font-variant-numeric: tabular-nums;
}

.bb-app .bb-result-callout {
    --bb-result-color: var(--bb-primary);
    border-color: color-mix(in srgb, var(--bb-result-color) 34%, transparent) !important;
    background:
        radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--bb-result-color) 14%, transparent), transparent 12rem),
        var(--bb-surface) !important;
}

.bb-app .bb-result-callout--success {
    --bb-result-color: var(--bb-moss);
}

.bb-app .bb-btn-primary,
.bb-app .bb-btn--primary,
.bb-app .bb-btn-cta {
    background: linear-gradient(135deg, var(--bb-primary), var(--bb-primary-hover));
    border-color: transparent;
    box-shadow: 0 10px 24px rgba(178, 58, 53, 0.22);
}

.bb-app .bb-btn-secondary,
.bb-app .bb-btn--secondary,
.bb-app .bb-btn-outline,
.bb-app .bb-btn--outline {
    background: rgba(255, 253, 248, 0.84);
}

.bb-app .bb-input,
.bb-app .bb-select,
.bb-app .bb-filter-input,
.bb-app select.bb-filter-select,
.bb-app .bb-search-input,
.bb-app .bb-nav-search-input,
.bb-app input[type="text"],
.bb-app input[type="search"],
.bb-app input[type="number"],
.bb-app input[type="email"],
.bb-app select,
.bb-app textarea {
    background-color: rgba(255, 253, 248, 0.9);
    border-color: rgba(34, 28, 24, 0.14);
}

@media (max-width: 700px) {
    .bb-app .bb-nav {
        border-radius: 0 0 var(--bb-radius-lg) var(--bb-radius-lg);
    }

    .bb-app .bb-hero .bb-heading-hero:not(.bb-hero-tagline),
    .bb-app .bb-hero .bb-hero-tagline {
        max-width: 100%;
    }
}

/* =========================================================================
   Confidence Badge
   Markup (emitted by templates):
   <span class="bb-confidence bb-confidence--TIER" tabindex="0">
     <span class="bb-confidence__dot"></span>
     <span class="bb-confidence__label">LABEL</span>
     <span class="bb-confidence__tip" role="tooltip">REASONS</span>
   </span>
   TIER = verified | high | medium | review
   ========================================================================= */

.bb-confidence {

    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.375em;
    padding: 0.15em 0.55em 0.15em 0.5em;
    border: 1px solid transparent;
    border-radius: var(--bb-radius-full);
    font-family: var(--bb-font-body);
    font-size: var(--bb-fs-xs);
    font-weight: var(--bb-weight-semibold);
    line-height: 1.4;
    white-space: nowrap;
    cursor: help;
    vertical-align: middle;
    transition: background-color var(--bb-transition), border-color var(--bb-transition);
}

.bb-confidence:focus-visible {
    outline: var(--bb-focus-ring-width) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset);
}

.bb-confidence__dot {
    flex: 0 0 auto;
    width: 0.55em;
    height: 0.55em;
    border-radius: 50%;
    background: currentColor;
    /* Subtle ring so the dot reads on any tier background. */
    box-shadow: 0 0 0 0.12em rgba(255, 255, 255, 0.6);
}

.bb-confidence__label {
    color: inherit;
}

/* ---- Tier colors (text + dot inherit via currentColor) ---- */

/* Every tier took its text and background from a token and then hardcoded the
   border as a raw rgba of the same colour. That is one value with two owners,
   so the 2026-07-29 repaint moved three of them and left four blue and green
   borders behind - a live blue ring on .bb-confidence--high survived the whole
   palette change and was caught in the browser, not in the CSS. The rgba here
   now tracks the token above it; if you move a token, move its border too. */

/* Verified = green */
.bb-confidence--verified {
    color: var(--bb-green-700);
    background: var(--bb-success-light);
    border-color: rgba(69, 114, 63, 0.35);
}

/* High = deep green. Was blue until the Iron & Bone palette retired blue; the
   ramp is now green -> amber -> grey and every chip carries a text label. */
.bb-confidence--high {
    color: var(--bb-status-high);
    background: var(--bb-status-high-soft);
    border-color: rgba(47, 81, 41, 0.3);
}

/* Medium = amber. Label uses the darker amber for AA contrast (4.5:1+)
   on the light background; the dot/border keep the brighter amber. */
.bb-confidence--medium {
    color: var(--bb-status-medium);
    background: var(--bb-warning-light);
    border-color: rgba(217, 139, 74, 0.4);
}

/* Was var(--bb-accent-hover), which is the brand oxblood at its darkest - so a
   MEDIUM-confidence dot wore the same colour as a primary button. Deviation B:
   the accent does not double as a status. */
.bb-confidence--medium .bb-confidence__dot {
    color: var(--bb-amber-dark);
}

/* Review = grey, matching the design's "out" step. Reads as unresolved rather
   than as an error, which is what a review tier actually means, and it keeps
   the alarm colour reserved for validation. */
.bb-confidence--review {
    color: var(--bb-status-review);
    background: rgba(107, 98, 89, 0.1);
    border-color: rgba(107, 98, 89, 0.35);
}

/* ---- Per-tier dot glyph variation (CSS only, no icons) ---- */
/* Verified: solid filled dot (default). */
/* High: hollow ring. */
.bb-confidence--high .bb-confidence__dot {
    background: transparent;
    border: 0.16em solid currentColor;
    box-shadow: 0 0 0 0.12em rgba(255, 255, 255, 0.6);
}
/* Medium: half/triangle-ish via inset highlight. */
.bb-confidence--medium .bb-confidence__dot {
    border-radius: 0.12em;
    transform: rotate(45deg);
}
/* Review: dot with a centered slash to read as "needs attention". */
.bb-confidence--review .bb-confidence__dot {
    position: relative;
    background: currentColor;
}
.bb-confidence--review .bb-confidence__dot::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 12%;
    width: 76%;
    height: 0.12em;
    background: var(--bb-surface);
    transform: translateY(-50%) rotate(-45deg);
    border-radius: 1px;
}

/* ---- Tooltip ---- */
.bb-confidence__tip {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    z-index: 9999;
    min-width: 160px;
    max-width: 280px;
    padding: 0.5rem 0.65rem;
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface);
    color: var(--bb-text-secondary);
    border: 1px solid var(--bb-border-strong);
    box-shadow: var(--bb-shadow-lg);
    font-size: var(--bb-fs-xs);
    font-weight: var(--bb-weight-normal);
    line-height: 1.5;
    white-space: normal;
    text-align: left;
    /* Hidden by default. */
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--bb-transition), transform var(--bb-transition), visibility 0s linear var(--bb-transition-fast);
}

/* Little pointer arrow. */
.bb-confidence__tip::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-top-color: var(--bb-surface);
    /* Filter shadow so the arrow blends with the panel edge. */
    filter: drop-shadow(0 1px 0 var(--bb-border-strong));
    margin-top: -1px;
}

.bb-confidence:hover .bb-confidence__tip,
.bb-confidence:focus-within .bb-confidence__tip {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
    transition: opacity var(--bb-transition), transform var(--bb-transition), visibility 0s;
}

@media (prefers-reduced-motion: reduce) {
    .bb-confidence,
    .bb-confidence__tip {
        transition: none;
    }
}

/* P1-2: the centered tooltip (left:50% + translateX(-50%)) overflowed the left
   viewport edge on narrow screens. Anchor it to the badge's left edge instead and
   cap its width so it stays on-screen. Both the hidden and shown transforms are
   overridden so the centering math no longer applies below 480px. */
@media (max-width: 480px) {
    .bb-confidence__tip {
        left: 0;
        transform: none;
        max-width: 90vw;
    }
    .bb-confidence:hover .bb-confidence__tip,
    .bb-confidence:focus-within .bb-confidence__tip {
        transform: none;
    }
    /* Left-anchored, so move the pointer arrow under the badge, not the center. */
    .bb-confidence__tip::after {
        left: 18px;
        transform: none;
    }
}

/* P1-2: flip-below variant for badges near the top of the dark hero, where the
   default above-placement would clip above the viewport / hero edge. The JS that
   toggles this class based on position is wired in a later wave; this is the CSS
   hook it targets. */
.bb-confidence__tip--below {
    bottom: auto;
    top: calc(100% + 8px);
    transform: translateX(-50%) translateY(-4px);
}
.bb-confidence__tip--below::after {
    top: auto;
    bottom: 100%;
    border-top-color: transparent;
    border-bottom-color: var(--bb-surface);
    filter: drop-shadow(0 -1px 0 var(--bb-border-strong));
    margin-top: 0;
    margin-bottom: -1px;
}
.bb-confidence:hover .bb-confidence__tip--below,
.bb-confidence:focus-within .bb-confidence__tip--below {
    transform: translateX(-50%) translateY(0);
}
@media (max-width: 480px) {
    .bb-confidence__tip--below {
        transform: none;
    }
    .bb-confidence:hover .bb-confidence__tip--below,
    .bb-confidence:focus-within .bb-confidence__tip--below {
        transform: none;
    }
}

/* =========================================================================
   Report Modal (built lazily by window.bbReport in bodybuilding.js)
   ========================================================================= */

.bb-report-modal {
    /* The mirrored token block that used to live here is gone. It existed because
       this modal was appended straight to document.body, which put it outside the
       .bb-app scope where the tokens are declared, so every var(--bb-*) resolved
       to nothing. It now mounts into the .bb-app portal host (bbPortalHost in
       bb-ui.js) and inherits the real tokens, so a mirrored copy would be a
       second source of truth that silently drifts. Removing it is also what let
       the px type scale reach this modal: the mirror still held the old rem
       values for --bb-fs-sm and --bb-fs-lg.

       The old comment also claimed .bb-app carries a transform that would capture
       position:fixed. It does not, verified by grep and by measuring the mounted
       modal at full viewport size. .bb-portal pins transform:none anyway so a
       future transform on .bb-app cannot quietly break every overlay. */
    position: fixed;
    inset: 0;
    z-index: 100000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--bb-space-4);
    font-family: var(--bb-font-body);
    color: var(--bb-text-primary);
}

.bb-report-modal[hidden] {
    display: none;
}

.bb-report-modal__overlay {
    position: absolute;
    inset: 0;
    background: rgba(34, 28, 24, 0.55);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

.bb-report-modal__panel {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 460px;
    max-height: calc(100vh - 2 * var(--bb-space-4));
    overflow-y: auto;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-lg);
    padding: var(--bb-space-6);
    animation: bb-report-pop var(--bb-transition-normal) var(--bb-ease-out);
}

@keyframes bb-report-pop {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .bb-report-modal__panel {
        animation: none;
    }
}

.bb-report-modal__title {
    margin: 0 0 var(--bb-space-1);
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
    font-weight: var(--bb-weight-bold);
    color: var(--bb-text-primary);
}

.bb-report-modal__entity {
    margin: 0 0 var(--bb-space-4);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-muted);
}

.bb-report-modal__entity strong {
    color: var(--bb-text-secondary);
    font-weight: var(--bb-weight-semibold);
}

.bb-report-modal__field {
    margin-bottom: var(--bb-space-4);
}

.bb-report-modal__field label {
    display: block;
    margin-bottom: var(--bb-space-2);
    font-size: var(--bb-fs-sm);
    font-weight: var(--bb-weight-semibold);
    color: var(--bb-text-secondary);
}

/*
 * Storage disclosure under the optional email field. Smaller and quieter than the
 * label, but held above the 12.5px legibility floor this plugin enforces rather than
 * shrunk to fine print, since the whole point is that it gets read.
 */
.bb-report-modal__privacy {
    margin: var(--bb-space-2) 0 0;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--bb-text-muted);
}

.bb-report-modal__field select,
.bb-report-modal__field input,
.bb-report-modal__field textarea {
    width: 100%;
    box-sizing: border-box;
    padding: 0.6rem 0.7rem;
    font-family: inherit;
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-primary);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border-strong);
    border-radius: var(--bb-radius-sm);
    transition: border-color var(--bb-transition), box-shadow var(--bb-transition);
}

.bb-report-modal__field textarea {
    min-height: 90px;
    resize: vertical;
}

.bb-report-modal__field select:focus,
.bb-report-modal__field input:focus,
.bb-report-modal__field textarea:focus {
    outline: none;
    border-color: var(--bb-primary);
    box-shadow: 0 0 0 3px var(--bb-primary-light);
}

/* Honeypot: visually removed but not display:none (must be submittable). */
.bb-report-modal__hp {
    position: absolute !important;
    left: -9999px !important;
    top: auto !important;
    width: 1px !important;
    height: 1px !important;
    overflow: hidden !important;
    opacity: 0 !important;
}

.bb-report-modal__msg {
    margin: 0 0 var(--bb-space-4);
    padding: 0.6rem 0.7rem;
    border-radius: var(--bb-radius-sm);
    font-size: var(--bb-fs-sm);
    line-height: 1.45;
}

.bb-report-modal__msg[hidden] {
    display: none;
}

.bb-report-modal__msg--success {
    background: var(--bb-success-light);
    color: var(--bb-green-700);
    border: 1px solid rgba(69, 114, 63, 0.35);
}

.bb-report-modal__msg--error {
    background: var(--bb-error-light);
    color: var(--bb-danger);
    border: 1px solid rgba(143, 36, 32, 0.35);
}

.bb-report-modal__actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-2);
}

.bb-report-modal__btn {
    padding: 0.55rem 1.1rem;
    font-family: inherit;
    font-size: var(--bb-fs-sm);
    font-weight: var(--bb-weight-semibold);
    border-radius: var(--bb-radius-sm);
    border: 1px solid transparent;
    cursor: pointer;
    transition: background-color var(--bb-transition), border-color var(--bb-transition), opacity var(--bb-transition);
}

.bb-report-modal__btn:focus-visible {
    outline: var(--bb-focus-ring-width) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset);
}

.bb-report-modal__btn--cancel {
    background: var(--bb-surface);
    color: var(--bb-text-secondary);
    border-color: var(--bb-border-strong);
}

.bb-report-modal__btn--cancel:hover {
    background: var(--bb-gray-100);
}

.bb-report-modal__btn--submit {
    background: var(--bb-primary);
    color: #fff;
}

.bb-report-modal__btn--submit:hover {
    background: var(--bb-primary-hover);
}

.bb-report-modal__btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* ---------------------------------------------------------------
 * Server-rendered SEO summary hydration handoff.
 * Raw no-JS HTML remains visible; vanilla initialization adds .bb-hydrated.
 * --------------------------------------------------------------- */
.bb-hydrated .bb-ssr-summary__tldr,
.bb-hydrated .bb-ssr-summary__facts,
.bb-hydrated .bb-ssr-summary__subhead,
.bb-hydrated .bb-ssr-summary__results,
.bb-hydrated .bb-ssr-summary__links,
.bb-hydrated .bb-ssr-summary .bb-chart--career-arc {
    display: none;
}

.bb-hydrated .bb-ssr-summary .bb-data-freshness {
    display: none;
}

.bb-hydrated .bb-ssr-summary__tldr--persist {
    display: block;
}

.bb-hydrated .bb-ssr-summary {
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
}

.bb-hydrated #bb-ssr-h1 {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}
.bb-ssr-summary {
    margin: 0 0 24px;
    padding: 20px 24px;
    background: var(--bb-gray-50, #f8f9fa);
    border: 1px solid var(--bb-gray-200);
    border-radius: 10px;
}
.bb-ssr-summary__name {
    margin: 0 0 8px;
    /* Display tier: the SSR H1 is the visible page headline pre-hydration. */
    font-size: var(--bb-fs-page-title);
    line-height: 1.05;
}
.bb-vitals-answer {
    margin: 0 0 16px;
    padding: 12px 16px;
    font-size: 1.05rem;
    line-height: 1.6;
    color: var(--bb-text-primary, #1b1815);
    background: var(--bb-white, #fff);
    border-left: 3px solid var(--bb-primary, #c0392b);
    border-radius: 6px;
    max-width: 70ch;
}
.bb-ssr-summary__tldr {
    margin: 0 0 16px;
    font-size: 1rem;
    line-height: 1.55;
    color: var(--bb-gray-700);
    max-width: 70ch;
}
.bb-ssr-summary__facts {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 20px;
    margin: 0 0 18px;
}
.bb-ssr-fact {
    display: flex;
    flex-direction: column;
    min-width: 90px;
}
.bb-ssr-fact dt {
    font-size: var(--bb-fs-2xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bb-gray-500);
}
.bb-ssr-fact dd {
    margin: 2px 0 0;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--bb-gray-900);
}
.bb-ssr-fact dd a {
    color: var(--bb-primary); /* single oxblood accent (P1-11 AA-safe on white) */
    text-decoration: none;
}
.bb-ssr-fact dd a:hover { text-decoration: underline; }
.bb-ssr-summary__subhead {
    margin: 8px 0 10px;
    font-size: 1.05rem;
}
.bb-ssr-summary__results { margin: 0 0 16px; }
.bb-ssr-summary__links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
    margin: 0;
    font-size: 0.9rem;
}
.bb-ssr-summary__links a {
    color: var(--bb-primary); /* single oxblood accent (P1-11 AA-safe on white) */
    text-decoration: none;
}
.bb-ssr-summary__links a:hover { text-decoration: underline; }

/* Keep SSR and enhanced core-route states in one stable layout cell. */
.bb-core-route-handoff {
    display: grid;
    min-width: 0;
}
.bb-core-route-handoff > .bb-ssr-summary,
.bb-core-route-handoff > .bb-athlete-profile-page,
.bb-core-route-handoff > .bb-event-detail {
    grid-area: 1 / 1;
    min-width: 0;
}
.bb-core-route-handoff--has-summary:not(.bb-core-route-handoff--ready) > .bb-athlete-profile-page,
.bb-core-route-handoff--has-summary:not(.bb-core-route-handoff--ready) > .bb-event-detail,
.bb-core-route-handoff--ready > .bb-ssr-summary {
    visibility: hidden;
    pointer-events: none;
}

.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary {
    margin: 0 0 24px;
    padding: 20px 24px;
    background: var(--bb-gray-50, #f8f9fa);
    border: 1px solid var(--bb-gray-200);
}
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary .bb-ssr-summary__tldr,
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary .bb-ssr-summary__subhead,
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary .bb-ssr-summary__results,
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary .bb-data-freshness,
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary .bb-chart--career-arc {
    display: block;
}
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary .bb-ssr-summary__facts,
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary .bb-ssr-summary__links {
    display: flex;
}
.bb-hydrated .bb-core-route-handoff > .bb-ssr-summary #bb-ssr-h1 {
    position: static;
    width: auto;
    height: auto;
    padding: 0;
    margin: 0 0 8px;
    overflow: visible;
    clip: auto;
    clip-path: none;
    white-space: normal;
}

/* ---------------------------------------------------------------
 * Server-rendered country "Dynasty" authority section (.bb-dynasty)
 * Ranked, data-rich "greatest bodybuilders from {country}" block.
 * Static HTML so crawlers/AI engines read the full ranking without JS.
 * --------------------------------------------------------------- */
.bb-dynasty {
    margin: 0 0 28px;
    padding: 22px 24px;
    background: #fff;
    border: 1px solid var(--bb-gray-200);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(34, 28, 24, 0.04);
}
.bb-dynasty__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    margin: 0 0 12px;
}
.bb-dynasty__title {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    font-size: clamp(1.25rem, 3vw, 1.6rem);
    line-height: 1.2;
}
.bb-dynasty__flag {
    width: 28px;
    height: 21px;
    border-radius: 3px;
    object-fit: cover;
    box-shadow: 0 0 0 1px rgba(34, 28, 24, 0.08);
    flex: none;
}
.bb-dynasty__lead {
    margin: 0 0 18px;
    font-size: 1.02rem;
    line-height: 1.55;
    color: var(--bb-gray-700);
    max-width: 72ch;
}
.bb-dynasty__stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr));
    gap: 12px;
    margin: 0 0 18px;
    padding: 16px;
    background: var(--bb-gray-50, #f8f9fa);
    border-radius: 10px;
}
.bb-dynasty__stat { display: flex; flex-direction: column; }
.bb-dynasty__stat--wide { grid-column: span 2; }
/*
 * 0.04em tracking and inherited weight put this off the 11 / 400 / 0.16em
 * eyebrow spec every other label in the plugin holds.
 *
 * .bb-app-scoped, and that is load-bearing rather than housekeeping: the theme
 * ships `.rbct dt { font-weight: 700 }` and the plugin's content renders inside
 * .rbct, so a bare `.bb-dynasty__stat dt` ties it at (0,1,1) and loses on order.
 * The tracking here applied and the weight did not, which is what a tie looks
 * like from the outside.
 */
.bb-app .bb-dynasty__stat dt {
    font-size: var(--bb-fs-2xs);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--bb-gray-500);
}
.bb-dynasty__stat dd {
    margin: 3px 0 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--bb-gray-900);
}
.bb-dynasty__stat dd a {
    color: var(--bb-primary);
    text-decoration: none;
    font-weight: 700;
}
.bb-dynasty__stat dd a:hover { text-decoration: underline; }
.bb-dynasty__stat-sub {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--bb-gray-500);
}
.bb-dynasty__divisions {
    margin: 0 0 18px;
    font-size: 0.92rem;
    color: var(--bb-gray-600);
    line-height: 1.5;
}
.bb-dynasty__divisions-label {
    font-weight: 600;
    color: var(--bb-gray-700);
}
.bb-dynasty__roster-title {
    margin: 0 0 4px;
    font-size: 1.1rem;
}
.bb-dynasty__roster-note {
    margin: 0 0 12px;
    font-size: 0.85rem;
    color: var(--bb-gray-500);
}
/* P0-3: the dynasty "All-Time Ranking" table is ~642px wide and had no scroll
   wrapper CSS of its own, so its right columns (Olympia / Major-Pro / Wins /
   Results) were unreachable at 375-390px. Make the wrapper scroll horizontally. */
.bb-dynasty__table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}
.bb-dynasty__table th,
.bb-dynasty__table td { vertical-align: middle; }
.bb-dynasty__col-rank {
    width: 44px;
    text-align: center;
    font-variant-numeric: tabular-nums;
    color: var(--bb-gray-500);
    font-weight: 600;
}
.bb-dynasty__col-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.bb-dynasty__table td a {
    color: var(--bb-primary);
    text-decoration: none;
    font-weight: 600;
}
.bb-dynasty__table td a:hover { text-decoration: underline; }
/* P2-18: 0.06 amber was nearly invisible under the .bb-app zebra striping.
   0.12 survives the striping so the champion-row cue actually reads. (The
   template-side "skip when every row is a champion" guard is a separate item.) */
.bb-dynasty__row--champion td { background: rgba(217, 139, 74, 0.12); }
.bb-dynasty__champ-badge {
    margin-left: 6px;
    color: var(--bb-amber);
    font-size: 0.85em;
    line-height: 1;
}

.bb-h2h-verdict {
    margin: 4px 0 16px;
    font-size: 1rem;
    font-weight: 600;
    color: var(--bb-navy);
}

/* =========================================================================
   Stream 3 - Static top-list detail / hub
   ========================================================================= */

/* Above-the-fold one-line answer (highest-leverage SERP/AI snippet). */
.bb-app .bb-answer-block {
    margin: 0 0 16px;
    padding: 12px 16px;
    border-left: 3px solid var(--bb-primary);
    border-radius: var(--bb-radius-sm, 6px);
    background: var(--bb-primary-light, rgba(178, 58, 53, 0.08));
    color: var(--bb-text-primary);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.45;
}

/* Honest-confidence note shown on thin (noindex) division facets. */
.bb-app .bb-data-note {
    margin: 0 0 16px;
    padding: 10px 14px;
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius, 10px);
    background: var(--bb-gray-50);
    color: var(--bb-text-muted);
    font-size: 13px;
    line-height: 1.5;
}

.bb-app .bb-top-list-detail { margin-top: 8px; }

/* Division facet chip row. */
.bb-app .bb-facet-nav { margin: 28px 0 8px; }
.bb-app .bb-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}
.bb-app .bb-chip {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    padding: 6px 14px;
    border: 1px solid var(--bb-border);
    border-radius: 999px;
    background: var(--bb-surface, #fff);
    color: var(--bb-text-secondary);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.bb-app .bb-chip:hover {
    border-color: var(--bb-primary);
    color: var(--bb-primary);
    background: var(--bb-primary-light, rgba(178, 58, 53, 0.08));
}

/* Hub: reuse the existing card grid; just give the wrapper rhythm. */
.bb-app .bb-top-lists-hub { margin-top: 8px; }

/* =========================================================================
   Shared Trust Block (.bb-trust)
   Confidence badge (.bb-confidence, styled above) + accuracy rating widget
   (.bb-rating) + report button (.bb-report-btn, styled above). One component
   reused across every data page type. Light theme only (no dark mode).
   ========================================================================= */

.bb-trust {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin: 0.5rem 0;
}

/* Community-review status chip (automated data-flag system). Subtle editorial
   treatment: hairline border, muted amber dot, small text. Rendered SSR by
   Bodybuilding_Review_Queue::status_chip() inside the trust block, on the
   athlete SSR summary, and in the event-detail facts rail. */
.bb-review-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    padding: 0.15em 0.6em;
    border: 1px solid var(--bb-border, #e2e2dc);
    border-radius: var(--bb-radius-full, 999px);
    background: transparent;
    font-family: var(--bb-font-body);
    font-size: var(--bb-fs-xs);
    font-weight: var(--bb-weight-semibold, 600);
    line-height: 1.4;
    color: var(--bb-text-secondary, #555);
    white-space: nowrap;
    vertical-align: middle;
    cursor: help;
}

.bb-review-chip__dot {
    flex: 0 0 auto;
    width: 0.5em;
    height: 0.5em;
    border-radius: 50%;
    background: var(--bb-amber-deep); /* muted amber */
    opacity: 0.75;
}

.bb-rating {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-family: var(--bb-font-body);
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-secondary, #555);
}

.bb-rating__q {
    font-weight: var(--bb-weight-semibold);
}

.bb-rating__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    padding: 0.45em 0.65em;
    min-height: 44px;
    min-width: 44px;
    border: 1px solid var(--bb-border, #dcdcdc);
    border-radius: var(--bb-radius-full, 999px);
    background: #fff;
    color: var(--bb-text-secondary, #555);
    font: inherit;
    line-height: 1.3;
    cursor: pointer;
    transition: background-color var(--bb-transition), border-color var(--bb-transition), color var(--bb-transition);
}

.bb-rating__btn:hover {
    border-color: var(--bb-accent, #b23a35);
    color: var(--bb-text-primary, #1a1a1a);
}

.bb-rating__btn:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset, 2px);
}

.bb-rating__icon {
    font-size: 0.85em;
    line-height: 1;
}

.bb-rating__btn--up[aria-pressed="true"] {
    border-color: rgba(69, 114, 63, 0.5);
    background: var(--bb-success-light);
    color: var(--bb-green-700);
}

.bb-rating__btn--down[aria-pressed="true"] {
    border-color: rgba(217, 139, 74, 0.5);
    background: rgba(217, 139, 74, 0.1);
    color: var(--bb-amber-deep);
}

.bb-rating__count {
    font-variant-numeric: tabular-nums;
    min-width: 1ch;
    text-align: right;
}

.bb-rating__msg {
    font-size: var(--bb-fs-xs);
}

.bb-rating__msg--ok {
    color: var(--bb-green-700);
}

.bb-rating__msg--error {
    color: var(--bb-amber-deep);
}

/* Report-issue trigger. The trigger has no plugin background rule, so the host
   theme's loud pink button style (main.css var(--btn-primary)) bleeds in. Give
   it an explicit quiet, restrained appearance so it reads as a minor secondary
   action and never the loud theme red. Sits on the dark profile hero, so use a
   translucent light outline. */
.bb-app .bb-report-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 32px;
    padding: 0.3em 0.75em;
    font: inherit;
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    line-height: 1.3;
    color: rgba(255, 253, 248, 0.82);
    background: rgba(255, 253, 248, 0.08);
    border: 1px solid rgba(255, 253, 248, 0.28);
    border-radius: var(--bb-radius);
    cursor: pointer;
    transition: background-color var(--bb-transition), border-color var(--bb-transition), color var(--bb-transition);
}

.bb-app .bb-report-btn:hover {
    color: var(--bb-on-dark);
    background: rgba(255, 253, 248, 0.14);
    border-color: rgba(255, 253, 248, 0.45);
}

.bb-app .bb-report-btn:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid rgba(255, 253, 248, 0.8);
    outline-offset: var(--bb-focus-ring-offset, 2px);
}

/*
 * The visually-hidden utility is `.bb-sr-only` (defined above, 41 uses). A second
 * name for the same thing, `.bb-screen-reader-text`, used to live here with a
 * byte-equivalent body (`border: 0` against `border-width: 0`) and four uses across
 * the athlete profile and the shared trust block. Those are now on `.bb-sr-only` and
 * this rule is gone.
 *
 * It was not only a naming inconsistency. Clip-detection guards exclude `.bb-sr-only`
 * because it clips by design, so any page rendering the trust block reported two
 * false "clipped text" hits for its "accurate" / "inaccurate" labels. One name means
 * the existing guards cover these elements correctly.
 */

@media (prefers-reduced-motion: reduce) {
    .bb-rating__btn {
        transition: none;
    }
}

/* ==========================================================================
   Stat-Finder (/bodybuilding/stats/) - Wave 3
   boards are server-rendered, so these styles only control layout/active state.
   Theme boundary respected: every selector is scoped under .bb-app.
   ========================================================================== */
.bb-app .bb-statfinder {
    max-width: 1040px;
    margin: 0 auto;
    padding: 0 var(--bb-space-4);
}
.bb-app .bb-statfinder-intro {
    color: var(--bb-text-secondary);
    font-size: 15px;
    line-height: 1.6;
    margin: var(--bb-space-4) 0 var(--bb-space-6);
}
.bb-app .bb-statfinder-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 var(--bb-space-8);
    padding-bottom: var(--bb-space-5);
    border-bottom: 1px solid var(--bb-border);
}
.bb-app .bb-statfinder-tab {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 7px 16px;
    border: 1px solid var(--bb-border);
    border-radius: 999px;
    background: var(--bb-surface, #fff);
    color: var(--bb-text-secondary);
    font-size: 13px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.bb-app .bb-statfinder-tab:hover {
    border-color: var(--bb-primary);
    color: var(--bb-text-primary);
}
.bb-app .bb-statfinder-tab.is-active {
    background: var(--bb-primary);
    border-color: var(--bb-primary);
    color: #fff;
}
.bb-app .bb-statfinder-tab:focus-visible {
    outline: 2px solid var(--bb-primary);
    outline-offset: 2px;
}
.bb-app .bb-statfinder-board {
    margin-bottom: var(--bb-space-10);
}
.bb-app .bb-statfinder-board-head {
    margin-bottom: var(--bb-space-4);
}
.bb-app .bb-statfinder-board-desc {
    color: var(--bb-text-secondary);
    font-size: 14px;
    line-height: 1.6;
    margin: var(--bb-space-2) 0 0;
}
.bb-app .bb-statfinder .bb-th-detail,
.bb-app .bb-statfinder .bb-td-detail {
    color: var(--bb-text-secondary);
    font-size: 13px;
}
/* The header is a label and takes the label size; the cell below it is data
   and keeps 13px. They shared a rule and so shared a size. */
.bb-app .bb-statfinder .bb-th-detail { font-size: var(--bb-fs-2xs); }
@media (max-width: 640px) {
    /* The Detail value is load-bearing for several boards (year won, span,
       debut contest, division name), so instead of hiding it we reflow each
       row into a grid: Rank pins to the left across all lines, Athlete + Value
       sit on the top line, and Country then Detail drop to muted sub-lines
       under the athlete name. We first decouple from table layout (mirroring
       the .bb-table--responsive scaffold above) so the grid rows size reliably;
       the column-label thead is dropped (the metric name is carried by the
       board heading + lead sentence above the table). */
    .bb-app .bb-statfinder .bb-rankings-table { display: block; }
    .bb-app .bb-statfinder .bb-rankings-table thead { display: none; }
    .bb-app .bb-statfinder .bb-rankings-table tbody { display: block; }
    .bb-app .bb-statfinder .bb-rankings-table tbody tr {
        display: grid;
        grid-template-columns: auto 1fr auto;
        grid-template-areas:
            "rank athlete value"
            "rank country country"
            "rank detail  detail";
        align-items: center;
        column-gap: 10px;
        row-gap: 2px;
        padding: 10px 0;
    }
    .bb-app .bb-statfinder .bb-rankings-table tbody td {
        padding: 0;
        border: 0;
    }
    .bb-app .bb-statfinder .bb-rankings-table tbody td.bb-td-rank { grid-area: rank; }
    .bb-app .bb-statfinder .bb-rankings-table tbody td.bb-td-athlete { grid-area: athlete; }
    .bb-app .bb-statfinder .bb-rankings-table tbody td.bb-td-num {
        grid-area: value;
        text-align: right;
    }
    .bb-app .bb-statfinder .bb-rankings-table tbody td.bb-td-country {
        grid-area: country;
        font-size: 12px;
        color: var(--bb-text-secondary);
    }
    .bb-app .bb-statfinder .bb-rankings-table tbody td.bb-td-detail {
        grid-area: detail;
        font-size: 12px;
        color: var(--bb-text-secondary);
        white-space: normal;
    }
}

/* ==========================================================================
   CHART KIT (Wave 1 viz foundation - see UI-REVAMP plan 2.2 + 4)
   One reusable .bb-chart component on vendored Chart.js (no build step).
   Honest-confidence: the SSR fallback is visible by DEFAULT; the canvas is
   hidden by DEFAULT. bb-charts.js adds `.bb-chart-ready` to the container
   ONLY after new Chart() succeeds, which flips the two. A crawler / no-JS /
   load-failure client therefore always sees the truthful number-or-table and
   never an empty canvas.
   ========================================================================== */

.bb-app .bb-chart {
    margin: 0 0 var(--bb-space-4);
    padding: 0;
    border: 0;
}

.bb-app .bb-chart__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-sm);
    font-weight: var(--bb-weight-semibold);
    color: var(--bb-text-primary);
    margin: 0 0 var(--bb-space-3);
    letter-spacing: 0.01em;
}

.bb-app .bb-chart__note {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    margin: var(--bb-space-2) 0 0;
}

/* Canvas wrap: hidden until the chart paints. The inline height set by the
   PHP partial governs the canvas box (Chart.js maintainAspectRatio:false). */
.bb-app .bb-chart__canvas-wrap {
    position: relative;
    width: 100%;
    display: none;
}

.bb-app .bb-chart__canvas {
    display: block;
    width: 100% !important;
    height: 100% !important;
}

/* Truthful fallback: visible by default (the honest-confidence anchor). */
.bb-app .bb-chart__fallback {
    display: block;
}

/* Per-chart JS success flip. Scoped to the container so a failed chart on the
   same page keeps ITS own fallback. */
.bb-app .bb-chart-ready .bb-chart__canvas-wrap {
    display: block;
}

.bb-app .bb-chart-ready .bb-chart__fallback {
    display: none;
}

/* Single-value fallback (one data point reads as a headline number). */
.bb-app .bb-chart__single {
    margin: 0;
    display: flex;
    align-items: baseline;
    gap: var(--bb-space-2);
}

.bb-app .bb-chart__single-value {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-2xl);
    font-weight: var(--bb-weight-extrabold);
    color: var(--bb-chart-series-2);
    line-height: 1;
}

.bb-app .bb-chart__single-label {
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
}

/* Tabular fallback: a compact, on-brand table (reuses the data-table look). */
.bb-app .bb-chart__table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--bb-fs-sm);
}

/*
 * The zebra stripe on chart fallback tables was rgba(136,136,136,0.07), a
 * neutral grey that appears nowhere in this palette. It is not ours: it comes
 * from the Foxiz rule `tbody tr:nth-child(2n+1) { background: var(--flex-gray-7) }`
 * at (0,1,2), confirmed against matched styles rather than guessed.
 *
 * Scoped to chart tables on purpose. That theme rule stripes EVERY table in the
 * plugin, so replacing it globally is a change to every data surface and wants
 * the owner's eye first. This fixes the one place the grey was reported and
 * leaves the wider question open rather than quietly answering it.
 */
.bb-app .bb-chart__table tbody tr:nth-child(2n+1) {
    background: var(--bb-surface-sunken, var(--bb-bone));
}

.bb-app .bb-chart__table th,
.bb-app .bb-chart__table td {
    padding: var(--bb-space-2) var(--bb-space-3);
    text-align: left;
    border-bottom: 1px solid var(--bb-border);
}

.bb-app .bb-chart__table thead th {
    font-weight: var(--bb-weight-semibold);
    color: var(--bb-text-secondary);
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.bb-app .bb-chart__table tbody th[scope="row"] {
    font-weight: var(--bb-weight-medium);
    color: var(--bb-text-primary);
}

.bb-app .bb-chart__table tbody td {
    color: var(--bb-text-secondary);
    font-variant-numeric: tabular-nums;
}

.bb-app .bb-chart__table tbody tr:last-child th,
.bb-app .bb-chart__table tbody tr:last-child td {
    border-bottom: 0;
}

/* Inline "dominance bar" usable inside any data-table metric cell so a
   10-vs-8-vs-1 reads at a glance (plan 2.2 "Data table"). Honest: width is set
   inline by the caller from a real ratio; with no width it renders nothing. */
.bb-app .bb-dom-bar {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    min-width: 96px;
    vertical-align: middle;
}

.bb-app .bb-dom-bar__track {
    position: relative;
    flex: 1 1 auto;
    height: 8px;
    background: var(--bb-chart-track);
    border-radius: var(--bb-radius-full);
    overflow: hidden;
}

.bb-app .bb-dom-bar__fill {
    position: absolute;
    inset: 0 auto 0 0;
    height: 100%;
    background: var(--bb-chart-series-2);
    border-radius: var(--bb-radius-full);
}

.bb-app .bb-dom-bar--gold .bb-dom-bar__fill {
    background: var(--bb-chart-gold);
}

.bb-app .bb-dom-bar__value {
    font-variant-numeric: tabular-nums;
    font-weight: var(--bb-weight-semibold);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-primary);
}

@media (max-width: 480px) {
    .bb-app .bb-chart__single-value {
        font-size: var(--bb-fs-xl);
    }
}

/* ==========================================================================
   EVENT DETAIL (Wave 4) - one champion-forward layout for contests / Olympia
   / Arnold year pages. Reuses the consolidated .bb-page-header--dark hero,
   .bb-tab-bar / .bb-tab--active, .bb-goat-podium, .bb-card, and .bb-table--results.
   Adds only: the champion-forward hero treatment, the two-column layout with a
   sticky facts/lineage rail, and the champion-lineage strip. Gold is reserved
   for the champion so it consistently means "winner".
   ========================================================================== */
.bb-app .bb-event-source-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--bb-space-3);
    margin-bottom: var(--bb-space-4);
    padding: var(--bb-space-3) var(--bb-space-4);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    background: var(--bb-surface);
}
.bb-app .bb-event-source-summary__status,
.bb-app .bb-event-source-summary__source {
    margin: 0;
    color: var(--bb-text-secondary);
    font-size: var(--bb-fs-sm);
    line-height: 1.5;
}
.bb-app .bb-event-source-summary__label {
    display: inline-flex;
    align-items: center;
    min-height: 26px;
    padding: 4px 9px;
    border-radius: var(--bb-radius-full);
    background: var(--bb-primary-light);
    color: var(--bb-primary-hover);
    font-size: var(--bb-fs-xs);
    font-weight: 700;
}
.bb-app .bb-event-source-summary[data-show-state="complete"] .bb-event-source-summary__label {
    background: var(--bb-success-light);
    color: var(--bb-text-primary);
}
@media (max-width: 640px) {
    .bb-app .bb-event-source-summary {
        align-items: flex-start;
        flex-direction: column;
    }
}

/* --- Champion-forward hero ------------------------------------------------ */
.bb-app .bb-event-hero {
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
}
.bb-app .bb-event-hero__main {
    display: flex;
    align-items: center;
    gap: var(--bb-space-5);
    min-width: 0;
    flex: 1 1 420px;
}
.bb-app .bb-event-hero__portrait {
    flex: 0 0 auto;
    width: 96px;
    height: 96px;
    border-radius: 50%;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.06);
    border: 2px solid var(--bb-gold);
    box-shadow: 0 0 0 4px rgba(217, 139, 74, 0.16);
}
.bb-app .bb-event-hero__img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.bb-app .bb-event-hero__monogram {
    width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.75rem; font-weight: 800; letter-spacing: -0.02em;
    color: var(--bb-gold);
    background: linear-gradient(135deg, var(--bb-navy-mid), var(--bb-navy));
}
.bb-app .bb-event-hero__body { min-width: 0; }
/* Higher specificity (0,3,0) than the shared .bb-page-title (0,2,0) the hero
   title also carries, so the cap actually applies. Responsive + capped so long
   show names do not blow the hero up. */
.bb-app .bb-event-hero .bb-event-hero__title {
    margin: 0 0 6px;
    font-size: var(--bb-fs-page-title);
    line-height: 1.18;
    overflow-wrap: anywhere;
}
.bb-app .bb-event-hero__champion {
    display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
    margin-bottom: 6px;
}
.bb-app .bb-event-hero__crown { display: inline-flex; color: var(--bb-gold); }
.bb-app .bb-event-hero__champion-name {
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    /* On-dark amber. --bb-gold holds the ON-LIGHT value (#8f5a1e) because most of
       its consumers sit on paper; this one is on the dark event hero, where that
       measured 2.93:1 against the 3:1 floor for text this size. */
    color: var(--bb-amber-on-dark);
    letter-spacing: -0.01em;
}
/* Hover goes to bone rather than the old #ffe082 - a pale yellow that exists
   nowhere else in the palette - so the affordance is a clear brightening within
   the two colours this band already uses. */
.bb-app .bb-event-hero__champion-name:hover { color: var(--bb-bone); text-decoration: underline; }
/* Answer-first lede inside the dark contest hero (the contest-detail TL;DR fix).
   Light muted text for readability on the dark hero background. */
.bb-app .bb-event-hero__tldr {
    margin: 10px 0 0;
    max-width: 64ch;
    color: rgba(255, 255, 255, 0.82);
    font-size: var(--bb-fs-sm);
    line-height: 1.55;
}
.bb-app .bb-event-hero__credential {
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(255, 255, 255, 0.78);
}
/* Defending-champion line. Sits on the light body directly under the dark hero,
   so it takes ink on tint rather than the hero's reversed palette. */
.bb-app .bb-defence-line {
    margin: 0 0 20px;
    padding: 12px 16px;
    border-left: 3px solid var(--bb-amber-on-light);
    background: var(--bb-tint);
    color: var(--bb-ink);
    font-size: var(--bb-fs-sm);
    line-height: 1.5;
}
.bb-app .bb-defence-line a {
    color: var(--bb-ink);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.bb-app .bb-defence-line a:hover,
.bb-app .bb-defence-line a:focus-visible {
    color: var(--bb-amber-on-light);
}
.bb-app .bb-event-hero__meta {
    display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
    margin: 0;
    color: rgba(255, 255, 255, 0.72);
    font-size: var(--bb-fs-sm);
}
.bb-app .bb-event-hero__meta .bb-sep { opacity: 0.5; }
.bb-app .bb-event-hero__nav {
    display: flex; flex-direction: column; gap: 8px;
    flex: 0 0 auto;
    align-items: stretch;
}
.bb-app .bb-event-hero__arrows { display: flex; flex-direction: column; gap: 8px; }
.bb-app .bb-event-hero__follow { display: inline-flex; }
.bb-app .bb-event-hero__follow .bb-btn { width: 100%; justify-content: center; }
.bb-app .bb-event-hero__arrow {
    display: inline-flex; align-items: center; gap: 6px;
    min-height: 40px;
    padding: 6px 14px;
    border-radius: var(--bb-radius-md);
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.06);
    color: #fff;
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    white-space: nowrap;
}
.bb-app .bb-event-hero__arrow:hover { background: rgba(255, 255, 255, 0.14); border-color: rgba(255, 255, 255, 0.4); }
.bb-app .bb-event-hero__arrow--next { justify-content: flex-end; }

/* --- Two-column layout: results main + sticky rail ------------------------ */
.bb-app .bb-event-layout {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--bb-space-6);
    align-items: start;
}
@media (min-width: 1024px) {
    .bb-app .bb-event-layout {
        grid-template-columns: minmax(0, 1fr) minmax(280px, 0.42fr);
    }
}
.bb-app .bb-event-main { min-width: 0; }
.bb-app .bb-event-rail { display: flex; flex-direction: column; gap: var(--bb-space-5); min-width: 0; }
@media (min-width: 1024px) {
    .bb-app .bb-event-rail { position: sticky; top: var(--bb-space-6); }
}
.bb-app .bb-event-rail__title {
    /* --bb-fs-base is 16px and sits on no H2 tier. It read as body copy set in
       caps rather than as the heading of the rail it opens, at every width. */
    font-size: var(--bb-fs-22);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--bb-navy);
    margin: 0 0 var(--bb-space-3);
}

/* Event Facts card */
.bb-app .bb-event-facts { padding: var(--bb-space-5); }
.bb-app .bb-event-facts__list { margin: 0; }
.bb-app .bb-event-facts__row {
    display: flex; justify-content: space-between; gap: var(--bb-space-3);
    padding: 8px 0;
    border-bottom: 1px solid var(--bb-border-soft);
}
.bb-app .bb-event-facts__row:last-of-type { border-bottom: 0; }
/* A fact list's term is an eyebrow label: 11px / 400 / 0.16em, not 14 / 600 / 0.16. */
.bb-app .bb-event-facts__row dt { color: var(--bb-text-muted); font-family: var(--bb-font-mono); font-size: var(--bb-fs-2xs); font-weight: 400; letter-spacing: 0.16em; text-transform: uppercase; }
.bb-app .bb-event-facts__row dd { margin: 0; text-align: right; font-weight: 700; color: var(--bb-text-primary); }
.bb-app .bb-event-facts__share { margin-top: var(--bb-space-4); }

/* --- Podium (reuse .bb-goat-podium; tune the bare <img> + spacing) -------- */
.bb-app .bb-event-podium-wrap { margin-bottom: var(--bb-space-5); }
.bb-app .bb-event-podium { margin-bottom: 0; }
.bb-app .bb-event-podium-card .bb-goat-podium-avatar img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.bb-app .bb-event-podium-card .bb-goat-podium-avatar svg { width: 40px; height: 40px; color: var(--bb-text-tertiary); }
.bb-app .bb-event-podium-card .bb-goat-podium-division { display: flex; justify-content: center; }

/* --- Results -------------------------------------------------------------- */
/* Division selector on event pages: wrapping PILLS, not a single scrolling row.
   The base .bb-tab-bar is overflow-x:auto with the scrollbar hidden, so on a
   contest with many divisions (Olympia has 11+) the tabs past the fold were
   invisible and unreachable. Pills wrap onto multiple rows so every division
   is reachable without scrolling.

   This comment was left unterminated, and a CSS comment runs to the next `*​/`
   anywhere in the file - which was 40 lines below, at the "Champion lineage"
   header. So every rule in between was commented out and silently did nothing:
   all four .bb-event-tabs rules plus .bb-event-results__title and
   .bb-event-showall. The fix described here was written and then disabled by its
   own comment, and the bug it fixes came straight back unnoticed.

   Measured on /olympia/2025/ (11 divisions) while the rules were dead:
   flex-wrap:nowrap, overflow-x:auto, gap:0, border-radius:0, transparent tabs,
   and 10 of the 11 tabs sitting outside the container box at 390px, 7 of 11 at
   1440px - exactly the unreachable-tabs symptom described above. */
.bb-app .bb-event-tabs {
    margin-bottom: var(--bb-space-4);
    flex-wrap: wrap;
    gap: 8px;
    overflow-x: visible;
    border-bottom: none;
    padding-bottom: var(--bb-space-2);
}
.bb-app .bb-event-tabs .bb-tab {
    border: 1px solid var(--bb-border);
    border-radius: 999px;
    padding: 7px 16px;
    background: var(--bb-surface);
    color: var(--bb-text-secondary);
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.bb-app .bb-event-tabs .bb-tab:hover:not(.bb-tab--active) {
    border-color: var(--bb-primary);
    color: var(--bb-primary);
}
.bb-app .bb-event-tabs .bb-tab--active {
    background: var(--bb-primary);
    border-color: var(--bb-primary);
    color: #fff;
}
.bb-app .bb-event-results__title {
    display: flex; align-items: center; gap: 10px;
    font-size: var(--bb-fs-xl);
    margin: 0 0 var(--bb-space-3);
}
.bb-app .bb-event-showall { margin-top: var(--bb-space-3); text-align: center; }

/* --- Champion lineage strip (signature element) --------------------------- */
.bb-app .bb-event-lineage { padding: var(--bb-space-5); }
.bb-app .bb-event-lineage__strip {
    list-style: none;
    margin: 0; padding: 0;
    display: flex; flex-direction: column;
    gap: 2px;
    max-height: 360px;
    overflow-y: auto;
}
@media (min-width: 1024px) { .bb-app .bb-event-lineage__strip { max-height: 420px; } }
.bb-app .bb-event-lineage__item { margin: 0; }
.bb-app .bb-event-lineage__link {
    display: flex; align-items: baseline; gap: 10px;
    min-height: 36px;
    padding: 6px 10px;
    border-radius: var(--bb-radius-sm);
    border-left: 3px solid transparent;
    color: var(--bb-text-primary);
}
.bb-app .bb-event-lineage__link:hover { background: var(--bb-gray-50, rgba(0,0,0,0.03)); }
.bb-app .bb-event-lineage__item--current .bb-event-lineage__link {
    background: var(--bb-accent-light);
    border-left-color: var(--bb-gold);
    font-weight: 700;
}
.bb-app .bb-event-lineage__year {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--bb-text-muted);
    min-width: 3.2em;
}
.bb-app .bb-event-lineage__item--current .bb-event-lineage__year { color: #8a5a00; }
.bb-app .bb-event-lineage__name {
    min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- Mobile ---------------------------------------------------------------- */
@media (max-width: 640px) {
    .bb-app .bb-event-hero { display: flex; flex-direction: column; align-items: flex-start; gap: var(--bb-space-4); }
    .bb-app .bb-event-hero__main { flex: 1 1 auto; width: 100%; gap: var(--bb-space-4); }
    .bb-app .bb-event-hero__portrait { width: 72px; height: 72px; }
    .bb-app .bb-event-hero__champion-name { font-size: var(--bb-fs-lg); }
    .bb-app .bb-event-hero__nav { width: 100%; }
    .bb-app .bb-event-hero__arrows { flex-direction: row; }
    .bb-app .bb-event-hero__arrow { flex: 1 1 0; justify-content: center; }
    .bb-app .bb-event-podium { grid-template-columns: 1fr; }
}

/* =========================================================================
   WAVE 5 - Category pages (divisions + countries, hub + detail)
   Plan 3.4. A persistent server-rendered navy/gold hero with oversized
   gold stat tiles; a leaderboard component (rank medals, monogram avatars,
   selective top-3 emphasis); honest history viz (strongest-division bars +
   era champion strip). Built on the Phase-0 hero gradient + the Phase-1
   champions-board medal palette so this stays ONE component language.
   ========================================================================= */

/* --- Persistent category hero --------------------------------------------
   Server-rendered outside .bb-ssr-summary, so hydration never hides this
   single visible category hero. */
.bb-app .bb-cat-hero {
    position: relative;
    overflow: hidden;
    margin: 0 0 var(--bb-space-6);
    padding: var(--bb-space-8) var(--bb-space-6);
    border-radius: var(--bb-radius-lg);
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    color: #fff;
}
.bb-app .bb-cat-hero::before {
    content: '';
    position: absolute;
    top: -55%; right: -12%;
    width: 480px; height: 480px;
    background: radial-gradient(circle, rgba(217, 139, 74,0.12) 0%, transparent 70%);
    pointer-events: none;
}
.bb-app .bb-cat-hero__inner {
    position: relative;
    z-index: 1;
    max-width: var(--bb-container);
    margin: 0 auto;
}
.bb-app .bb-cat-hero__silhouette {
    position: absolute;
    right: clamp(8px, 2vw, 40px);
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
    height: 94%;
    width: auto;
    max-width: 40%;
    object-fit: contain;
    object-position: center; /* whole figure, vertically centered - never feet-only */
    opacity: 0.12;
    z-index: 0;
    pointer-events: none;
    user-select: none;
    filter: brightness(0) invert(1);
}
@media (max-width: 720px) {
    .bb-app .bb-cat-hero__silhouette { display: none; }
}
.bb-app .bb-cat-hero__top {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    margin-bottom: var(--bb-space-5);
}
.bb-app .bb-cat-hero__flag {
    /* height:auto for the same reason as .bb-flag-img: a fixed 4:3 box with
       object-fit:cover cropped Nepal, Switzerland, the Vatican and Qatar. At hero
       size the crop was obvious. */
    width: 64px; height: auto;
    border-radius: 6px;
    flex-shrink: 0;
    box-shadow: 0 2px 8px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.12);
}
.bb-app .bb-cat-hero__eyebrow {
    display: inline-block;
    font-size: var(--bb-fs-xs);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bb-gold-champion);
    margin-bottom: 4px;
}
.bb-app .bb-cat-hero__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-page-title);
    font-weight: 900;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: #fff;
    margin: 0;
}
.bb-app .bb-cat-hero__lead {
    margin: var(--bb-space-3) 0 0;
    font-size: var(--bb-fs-md);
    line-height: 1.55;
    color: rgba(255,255,255,0.78);
    max-width: 60ch;
}

/* Oversized headline stat tiles - gold numerals on the navy hero */
.bb-app .bb-cat-hero__tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-6);
}
.bb-app .bb-cat-tile {
    padding: var(--bb-space-4) var(--bb-space-4);
    border-radius: var(--bb-radius-md);
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.1);
}
.bb-app .bb-cat-tile__value {
    display: block;
    font-family: var(--bb-font-heading);
    font-size: clamp(1.8rem, 4vw, 2.6rem);
    font-weight: 900;
    line-height: 1;
    color: var(--bb-gold-champion);
    font-variant-numeric: tabular-nums;
}
.bb-app .bb-cat-tile--span .bb-cat-tile__value { font-size: clamp(1.2rem, 3vw, 1.7rem); }
.bb-app .bb-cat-tile__label {
    display: block;
    margin-top: 6px;
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.6);
}

@media (max-width: 480px) {
    .bb-app .bb-cat-hero { padding: var(--bb-space-6) var(--bb-space-4); }
    .bb-app .bb-cat-hero__tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .bb-app .bb-cat-hero__flag { width: 48px; height: auto; }
}

/* --- Leaderboard component (shared) --------------------------------------
   A true ranked list: rank medals for the top 3 (gold/silver/bronze, same
   palette as .bb-champions-board), monogram or flag avatar, a primary metric,
   and a subtle champion tint reserved for genuine title-holders. Replaces the
   "star on every row" anti-pattern with selective emphasis. */
.bb-app .bb-leaderboard {
    margin: 0 0 var(--bb-space-6);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    background: var(--bb-surface);
    overflow: hidden;
    box-shadow: var(--bb-shadow-sm, 0 1px 2px rgba(34, 28, 24,0.04));
}
.bb-app .bb-leaderboard__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--bb-space-3);
    flex-wrap: wrap;
    padding: var(--bb-space-4) var(--bb-space-5);
    border-bottom: 1px solid var(--bb-gray-200);
    background: var(--bb-gray-50);
}
.bb-app .bb-leaderboard__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
    font-weight: 800;
    color: var(--bb-text-primary);
    margin: 0;
}
.bb-app .bb-leaderboard__basis {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    line-height: 1.4;
}
.bb-app .bb-leaderboard__list {
    list-style: none !important;
    margin: 0;
    padding: 0;
}
.bb-app .bb-leaderboard__row {
    list-style: none !important;
    margin: 0;
    border-top: 1px solid var(--bb-gray-100);
}
.bb-app .bb-leaderboard__row:first-child { border-top: 0; }
.bb-app .bb-leaderboard__row--champion { background: rgba(217, 139, 74,0.07); }
.bb-app .bb-leaderboard__link,
.bb-app .bb-leaderboard__link:link,
.bb-app .bb-leaderboard__link:visited {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: 10px var(--bb-space-5);
    min-height: 56px;
    text-decoration: none;
    color: var(--bb-text-primary);
    transition: background 0.15s ease;
}
.bb-app .bb-leaderboard__link:hover,
.bb-app .bb-leaderboard__link:focus-visible {
    background: var(--bb-primary-light, rgba(178, 58, 53,0.06));
}
.bb-app .bb-leaderboard__link:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-primary);
    outline-offset: -2px;
}
.bb-app .bb-leaderboard__rank {
    flex-shrink: 0;
    width: 30px; height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-size: var(--bb-fs-sm);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--bb-text-muted);
    background: var(--bb-gray-100);
}
.bb-app .bb-leaderboard__rank--1 { background: linear-gradient(135deg, var(--bb-gold-champion), var(--bb-gold-end)); color: var(--bb-gold-text); }
/* Warm silver. Rank 1 runs on the gold tokens and rank 3 on amber, so this was
   the last rung still on the cool ramp - a blue-grey medal between two warm
   ones. */
.bb-app .bb-leaderboard__rank--2 { background: linear-gradient(135deg, var(--bb-gray-200), var(--bb-gray-300)); color: var(--bb-gray-700); }
.bb-app .bb-leaderboard__rank--3 { background: linear-gradient(135deg, var(--bb-amber), #c07e44); color: #3a2a17; }
.bb-app .bb-leaderboard__avatar {
    flex-shrink: 0;
    width: 40px; height: 40px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--bb-gray-100);
}
.bb-app .bb-leaderboard__monogram {
    flex-shrink: 0;
    width: 40px; height: 40px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--bb-font-heading);
    font-weight: 800;
    font-size: var(--bb-fs-sm);
    color: #fff;
    background: linear-gradient(135deg, var(--bb-navy), var(--bb-navy-mid));
}
.bb-app .bb-leaderboard__body { flex: 1; min-width: 0; }
.bb-app .bb-leaderboard__name {
    display: block;
    font-weight: 700;
    color: var(--bb-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-decoration: underline;
    text-decoration-color: var(--bb-gray-200);
    text-underline-offset: 3px;
}
.bb-app .bb-leaderboard__link:hover .bb-leaderboard__name,
.bb-app .bb-leaderboard__link:focus-visible .bb-leaderboard__name { text-decoration-color: var(--bb-primary); }
.bb-app .bb-leaderboard__sub {
    display: block;
    margin-top: 2px;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bb-app .bb-leaderboard__crown {
    display: inline-flex;
    margin-left: 6px;
    color: var(--bb-gold-champion);
    vertical-align: -2px;
}
.bb-app .bb-leaderboard__metric {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1;
}
.bb-app .bb-leaderboard__count {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--bb-text-primary);
}
.bb-app .bb-leaderboard__row--champion .bb-leaderboard__count { color: var(--bb-gold-text); }
.bb-app .bb-leaderboard__unit {
    margin-top: 3px;
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}
.bb-app .bb-leaderboard__foot {
    display: block;
    padding: var(--bb-space-3) var(--bb-space-5);
    border-top: 1px solid var(--bb-gray-200);
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-primary);
    /* Rest-state underline so the CTA is distinguishable without color (P2-13),
       consistent with the other contextual link rules. */
    text-decoration: underline;
    background: var(--bb-gray-50);
}
.bb-app .bb-leaderboard__foot:hover { text-decoration: underline; }

@media (max-width: 480px) {
    .bb-app .bb-leaderboard__link { padding-left: var(--bb-space-3); padding-right: var(--bb-space-3); gap: var(--bb-space-2); }
    .bb-app .bb-leaderboard__avatar,
    .bb-app .bb-leaderboard__monogram { width: 34px; height: 34px; }
}

/* --- Differentiated card families ----------------------------------------
   Country cards are flag-anchored (a strong flag tile leads the card);
   division cards are identity-anchored (the gender glyph leads). Both reuse
   the .bb-card resting shadow + hover lift from the system. */
.bb-app .bb-country-card { box-shadow: var(--bb-shadow-sm, 0 1px 2px rgba(34, 28, 24,0.05)); }
.bb-app .bb-country-card__flag {
    box-shadow: 0 1px 3px rgba(34, 28, 24,0.25);
}
.bb-app .bb-country-card__header { align-items: center; }
.bb-app .bb-division-card { box-shadow: var(--bb-shadow-sm, 0 1px 2px rgba(34, 28, 24,0.05)); }

/* --- Strongest-divisions proportional bars (detail) ----------------------
   Replaces the inline "Strongest divisions: X (n wins)" text run. Honest:
   the bar widths are proportions of the leader, the real number is always
   printed, and the whole block is suppressed when fewer than 2 divisions
   have wins (handled template-side). */
.bb-app .bb-strength-bars {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
    margin: 0 0 var(--bb-space-5);
}
.bb-app .bb-strength-bar__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--bb-space-2);
    margin-bottom: 5px;
}
.bb-app .bb-strength-bar__name { font-size: var(--bb-fs-sm); font-weight: 600; color: var(--bb-text-primary); }
.bb-app .bb-strength-bar__val { font-size: var(--bb-fs-xs); font-weight: 700; color: var(--bb-text-secondary); font-variant-numeric: tabular-nums; }
.bb-app .bb-strength-bar__track {
    height: 10px;
    background: var(--bb-gray-100);
    border-radius: 999px;
    overflow: hidden;
}
.bb-app .bb-strength-bar__fill {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--bb-primary), var(--bb-accent));
}
.bb-app .bb-strength-bar:first-child .bb-strength-bar__fill {
    background: linear-gradient(90deg, var(--bb-gold-end), var(--bb-gold-champion));
}

/* --- Era champion strip (detail) -----------------------------------------
   The year->champion lineage rendered as a horizontal scrollable strip
   (NOT forced into a numeric line chart, which would misrepresent a
   categorical series). Degrades to a plain list when JS is off. */
.bb-app .bb-era-strip {
    display: flex;
    gap: var(--bb-space-2);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding: var(--bb-space-2) 0 var(--bb-space-3);
    margin: 0 0 var(--bb-space-5);
    scrollbar-width: thin;
}
.bb-app .bb-era-chip {
    flex: 0 0 auto;
    min-width: 132px;
    padding: var(--bb-space-3);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-md);
    background: var(--bb-surface);
    text-decoration: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.bb-app .bb-era-chip:hover { border-color: var(--bb-gold-champion); box-shadow: var(--bb-shadow-sm, 0 2px 6px rgba(34, 28, 24,0.08)); }
.bb-app .bb-era-chip__year {
    display: block;
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-md);
    font-weight: 800;
    color: var(--bb-gold-text);
}
.bb-app .bb-era-chip__name {
    display: block;
    margin-top: 3px;
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bb-app .bb-era-chip__country { display: block; margin-top: 1px; font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

/* Section heading shared by the detail history blocks */
.bb-app .bb-cat-section { margin: 0 0 var(--bb-space-8); }
.bb-app .bb-cat-section__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-xl);
    font-weight: 800;
    color: var(--bb-text-primary);
    margin: 0 0 var(--bb-space-4);
}
/* Top-margin variant for a section title that follows the persistent hero
   (replaces an inline style on countries/detail.php). */
.bb-app .bb-cat-section__title--mt {
    margin-top: var(--bb-space-2);
}

/* ==========================================================================
   WAVE 6 - RECORDS (3.5) + HEAD-TO-HEAD (3.6)
   Scorecard kit, champion-anchor + podium + coverage badge (top-lists),
   study charts, rivalry tiers + contested meter, VS hero, attribute
   tug-of-war (replaces the dishonest radar), compare discovery surface.
   All .bb-* scoped, no dark mode, tokens only.
   ========================================================================== */

/* --- Scorecard kit: replaces the studies' bespoke inline <style> blocks --- */
.bb-app .bb-scorecard {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    background: var(--bb-text-primary);
    color: #fff;
    border-radius: var(--bb-radius-lg, 12px);
    padding: var(--bb-space-4) var(--bb-space-6);
}
.bb-app .bb-scorecard__value {
    font-family: var(--bb-font-heading);
    font-size: 40px;
    font-weight: var(--bb-weight-extrabold, 800);
    line-height: 1;
    color: var(--bb-gold-champion);
}
.bb-app .bb-scorecard__label {
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: .04em;
    opacity: .85;
    margin-top: var(--bb-space-2);
}
.bb-app .bb-scorecard--feature { margin: 0 0 var(--bb-space-6); }
.bb-app .bb-scorecard--inline {
    display: flex;
    background: transparent;
    color: inherit;
    padding: 0;
    margin: 0 0 var(--bb-space-2);
}
.bb-app .bb-scorecard--inline .bb-scorecard__value { font-size: 30px; color: var(--bb-primary); }
.bb-app .bb-scorecard--inline .bb-scorecard__label { opacity: 1; color: var(--bb-text-muted); }

/* --- Studies hub + detail (moved off inline <style>) --- */
.bb-app .bb-study { max-width: 900px; margin: 0 auto; padding-top: var(--bb-space-2); }
.bb-app .bb-study h1 { margin: 0 0 var(--bb-space-2); }
.bb-app .bb-study__question { font-size: var(--bb-fs-md, 16px); color: var(--bb-text-secondary); margin: 0 0 var(--bb-space-5); }
.bb-app .bb-study__lede { font-size: var(--bb-fs-lg, 18px); line-height: 1.7; color: var(--bb-text-secondary); margin: 0 0 var(--bb-space-6); }
.bb-app .bb-study h2 { font-size: var(--bb-fs-xl, 22px); margin: var(--bb-space-8) 0 var(--bb-space-4); }
.bb-app .bb-study p { line-height: 1.7; color: var(--bb-text-secondary); margin: 0 0 var(--bb-space-4); }
.bb-app .bb-study__chart { margin: var(--bb-space-6) 0 var(--bb-space-8); }

/* Study data tables: scannability polish for the long ranked lists, scoped to
   /studies/ so the global data-authority table style stays untouched. */
.bb-app .bb-study .bb-table-container {
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius, 8px);
    overflow: hidden;
}
.bb-app .bb-study .bb-table th {
    background: var(--bb-gray-50);
    border-bottom: 2px solid var(--bb-border);
}
.bb-app .bb-study .bb-table tbody tr:nth-child(even) { background: rgba(34, 28, 24, 0.022); }
.bb-app .bb-study .bb-table tbody tr:hover { background: var(--bb-gray-100); }
.bb-app .bb-study .bb-table tbody tr:first-child { background: rgba(217, 139, 74, 0.08); }
.bb-app .bb-study .bb-table tbody tr:first-child td { font-weight: 600; color: var(--bb-text-primary); }
.bb-app .bb-study__note {
    font-size: var(--bb-fs-sm);
    line-height: 1.65;
    color: var(--bb-text-secondary);
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
    padding: var(--bb-space-4);
    margin: var(--bb-space-8) 0 var(--bb-space-2);
}
.bb-app .bb-study__note strong { color: var(--bb-text-primary); }

.bb-app .bb-study__grid { display: grid; gap: var(--bb-space-5); grid-template-columns: 1fr; }
@media (min-width: 768px) { .bb-app .bb-study__grid { grid-template-columns: 1fr 1fr; } }
.bb-app .bb-study__card {
    display: flex;
    flex-direction: column;
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg, 12px);
    padding: var(--bb-space-6);
    text-decoration: none !important;
    color: inherit;
    box-shadow: var(--bb-shadow-sm, 0 1px 3px rgba(34, 28, 24,.06));
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.bb-app .bb-study__card:hover { border-color: var(--bb-primary); box-shadow: var(--bb-shadow-md, 0 8px 24px rgba(34, 28, 24,.10)); transform: translateY(-2px); }
.bb-app .bb-study__card h2 { font-size: var(--bb-fs-lg, 19px); margin: 0 0 var(--bb-space-2); color: var(--bb-text-primary); }
.bb-app .bb-study__card p { font-size: var(--bb-fs-sm); line-height: 1.6; color: var(--bb-text-secondary); margin: 0 0 var(--bb-space-3); }
.bb-app .bb-study__card-chart { margin: var(--bb-space-2) 0 var(--bb-space-3); }
.bb-app .bb-study__card-cta { display: inline-block; margin-top: auto; font-weight: var(--bb-weight-semibold); font-size: var(--bb-fs-sm); color: var(--bb-primary); }

/* Mini chart variant (hub previews): tighter, no title chrome. */
.bb-app .bb-chart--mini { margin: 0; }
.bb-app .bb-chart--mini .bb-chart__table { font-size: var(--bb-fs-xs); }

/* --- Champion-anchor hero (top-lists/detail) --- */
.bb-app .bb-champion-anchor__h1 { margin-bottom: var(--bb-space-3); }
.bb-app .bb-champion-anchor__card {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bb-space-5);
    margin-top: var(--bb-space-5);
    padding: var(--bb-space-4) var(--bb-space-5);
    background: rgba(255, 255, 255, 0.07);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--bb-radius-lg, 12px);
}
.bb-app .bb-champion-anchor__metric { display: flex; flex-direction: column; }
.bb-app .bb-champion-anchor__value {
    font-family: var(--bb-font-heading);
    font-size: 48px;
    font-weight: var(--bb-weight-extrabold, 800);
    line-height: 1;
    color: var(--bb-gold-champion);
}
.bb-app .bb-champion-anchor__metric-label {
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: .05em;
    color: rgba(255, 255, 255, 0.78);
    margin-top: var(--bb-space-1);
}
.bb-app .bb-champion-anchor__who { display: flex; flex-direction: column; gap: 4px; }
.bb-app .bb-champion-anchor__eyebrow {
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--bb-gold-champion);
    font-weight: var(--bb-weight-semibold);
}
.bb-app .bb-champion-anchor__name {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-xl, 22px);
    font-weight: 800;
    color: #fff !important;
}
.bb-app a.bb-champion-anchor__name:hover { color: var(--bb-gold-champion) !important; }
.bb-app .bb-champion-anchor__meta { display: flex; align-items: center; gap: var(--bb-space-2); color: rgba(255,255,255,0.85); font-size: var(--bb-fs-sm); }

/* --- Coverage badge (confident, replaces apologetic gray note) --- */
.bb-app .bb-coverage-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    padding: var(--bb-space-2) var(--bb-space-4);
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-full, 999px);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
    margin: 0 0 var(--bb-space-4);
}
.bb-app .bb-coverage-badge strong { color: var(--bb-text-primary); }
.bb-app .bb-coverage-badge__dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--bb-success);
    flex: 0 0 auto;
}

/* --- Mini podium (top 3) --- */
.bb-app .bb-podium {
    list-style: none;
    margin: 0 0 var(--bb-space-6);
    padding: 0;
    display: grid;
    grid-template-columns: 1fr 1.15fr 1fr;
    align-items: end;
    gap: var(--bb-space-3);
}
.bb-app .bb-podium__slot {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-align: center;
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
    padding: var(--bb-space-4) var(--bb-space-2) var(--bb-space-3);
    box-shadow: var(--bb-shadow-sm, 0 1px 3px rgba(34, 28, 24,.06));
}
.bb-app .bb-podium__slot--gold { border-color: var(--bb-gold-champion); padding-top: var(--bb-space-6); box-shadow: 0 6px 22px rgba(217, 139, 74,.18); }
.bb-app .bb-podium__rank { margin-bottom: 2px; }
.bb-app .bb-podium__name { font-weight: var(--bb-weight-bold, 700); font-size: var(--bb-fs-sm); color: var(--bb-text-primary) !important; line-height: 1.2; }
.bb-app a.bb-podium__name:hover { color: var(--bb-primary) !important; }
.bb-app .bb-podium__metric {
    font-family: var(--bb-font-heading);
    font-weight: 800;
    font-size: var(--bb-fs-lg, 18px);
    color: var(--bb-text-primary);
}
.bb-app .bb-podium__slot--gold .bb-podium__metric { color: var(--bb-gold-text, #7a5c00); }
.bb-app .bb-podium__country { display: flex; align-items: center; gap: 6px; font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }
@media (max-width: 480px) {
    .bb-app .bb-podium { grid-template-columns: 1fr; }
    .bb-app .bb-podium__slot--gold { padding-top: var(--bb-space-4); }
    .bb-app .bb-podium__slot { flex-direction: row; justify-content: flex-start; text-align: left; gap: var(--bb-space-3); }
}

/* --- Rivalry tiers + contested meter --- */
.bb-app .bb-rivalries { margin: var(--bb-space-8) 0 0; }
.bb-app .bb-rivalries__tier-head { margin: 0 0 var(--bb-space-4); }
.bb-app .bb-rivalries__tier-title { font-family: var(--bb-font-heading); font-size: var(--bb-fs-xl, 22px); font-weight: 800; margin: 0; display: flex; align-items: center; gap: var(--bb-space-3); }
.bb-app .bb-rivalries__tier-desc { margin: var(--bb-space-1) 0 0; color: var(--bb-text-secondary); font-size: var(--bb-fs-sm); }
.bb-app .bb-tier-pill {
    display: inline-block;
    padding: 4px 12px;
    border-radius: var(--bb-radius-full, 999px);
    font-size: var(--bb-fs-sm);
    font-weight: var(--bb-weight-bold, 700);
    letter-spacing: .01em;
}
.bb-app .bb-tier-pill--legendary { background: linear-gradient(135deg, var(--bb-gold), var(--bb-gold-end)); color: var(--bb-gold-text); }
.bb-app .bb-tier-pill--classic { background: var(--bb-navy-mid); color: #fff; }
.bb-app .bb-tier-pill--notable { background: var(--bb-gray-100); color: var(--bb-text-primary); }
.bb-app .bb-rivalries-grid { list-style: none; margin: 0; padding: 0; }
.bb-app .bb-rivalry-card { padding: 0; overflow: hidden; }
.bb-app .bb-rivalry-card__link { display: flex; flex-direction: column; gap: 10px; padding: var(--bb-space-5); text-decoration: none !important; color: inherit; height: 100%; }
.bb-app .bb-rivalry-card__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.bb-app .bb-rivalry-card__side { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
.bb-app .bb-rivalry-card__side--b { justify-content: flex-end; text-align: right; }
.bb-app .bb-rivalry-card__name { font-weight: 700; font-size: var(--bb-fs-md, 15px); color: var(--bb-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bb-app .bb-rivalry-card__vs { font-size: var(--bb-fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--bb-text-muted); flex: 0 0 auto; }
.bb-app .bb-rivalry-card__score { display: flex; align-items: center; justify-content: center; gap: 10px; font-family: var(--bb-font-heading); font-size: 30px; font-weight: 800; line-height: 1; }
.bb-app .bb-rivalry-card__score-num--a { color: var(--bb-primary); }
.bb-app .bb-rivalry-card__score-num--b { color: var(--bb-navy-mid); }
.bb-app .bb-rivalry-card__score-sep { color: var(--bb-text-muted); font-weight: 400; }
.bb-app .bb-rivalry-card__score-label { margin: 0; text-align: center; font-size: var(--bb-fs-sm); color: var(--bb-text-secondary); }
.bb-app .bb-rivalry-meter { display: flex; flex-direction: column; gap: 4px; }
.bb-app .bb-rivalry-meter__track { position: relative; height: 8px; background: var(--bb-chart-track, var(--bb-gray-100)); border-radius: var(--bb-radius-full, 999px); overflow: hidden; }
.bb-app .bb-rivalry-meter__fill { position: absolute; inset: 0 auto 0 0; height: 100%; background: linear-gradient(90deg, var(--bb-primary), var(--bb-gold-champion)); border-radius: var(--bb-radius-full, 999px); }
.bb-app .bb-rivalry-meter__label { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); text-align: center; }
.bb-app .bb-rivalry-card__meta { list-style: none; margin: 0; padding: var(--bb-space-2) 0 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 14px; border-top: 1px solid var(--bb-border); font-size: 12.5px; color: var(--bb-text-muted); }
.bb-app .bb-rivalry-card__meta strong { color: var(--bb-text-primary); }
.bb-app .bb-rivalries--frequent { border-top: 1px solid var(--bb-border); padding-top: var(--bb-space-6); margin-top: var(--bb-space-10, 48px); }

/* Phone: stack the two athletes so long names (e.g. "Nasser El Sonbaty")
   wrap in full instead of clipping to an ellipsis on a single nowrap row. */
@media (max-width: 480px) {
    .bb-app .bb-rivalry-card__head { flex-direction: column; align-items: stretch; gap: 6px; }
    .bb-app .bb-rivalry-card__side { justify-content: center; text-align: center; }
    .bb-app .bb-rivalry-card__side--b { justify-content: center; text-align: center; }
    .bb-app .bb-rivalry-card__name { white-space: normal; overflow: visible; text-overflow: clip; }
    .bb-app .bb-rivalry-card__vs { align-self: center; }
}

/* --- VS hero (compare page) --- */
.bb-app .bb-vs-hero__h1 { margin-bottom: var(--bb-space-4); }
.bb-app .bb-vs-hero__board {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--bb-space-4);
    margin-top: var(--bb-space-4);
}
.bb-app .bb-vs-hero__side { display: flex; flex-direction: column; align-items: center; gap: var(--bb-space-2); text-align: center; min-width: 0; }
.bb-app .bb-vs-hero__avatar {
    width: 72px; height: 72px; border-radius: 50%; overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255,255,255,0.12);
    border: 2px solid rgba(255,255,255,0.25);
}
.bb-app .bb-vs-hero__side--a .bb-vs-hero__avatar { border-color: var(--bb-primary); }
.bb-app .bb-vs-hero__side--b .bb-vs-hero__avatar { border-color: var(--bb-warm-grey); }
.bb-app .bb-vs-hero__avatar img { width: 100%; height: 100%; object-fit: cover; }
.bb-app .bb-vs-hero__initials { font-family: var(--bb-font-heading); font-weight: 800; font-size: 24px; color: #fff; }
.bb-app .bb-vs-hero__name { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: var(--bb-fs-md, 15px); color: #fff; justify-content: center; flex-wrap: wrap; }
.bb-app .bb-vs-hero__center { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.bb-app .bb-vs-hero__score { display: flex; align-items: center; gap: var(--bb-space-3); font-family: var(--bb-font-heading); font-size: clamp(1.75rem, 8vw, 3.5rem); font-weight: 800; line-height: 1; }
.bb-app .bb-vs-hero__score-num--a { color: var(--bb-primary); }
.bb-app .bb-vs-hero__score-num--b { color: var(--bb-warm-grey); }
.bb-app .bb-vs-hero__score-sep { color: rgba(255,255,255,0.4); font-weight: 400; }
.bb-app .bb-vs-hero__vs { font-family: var(--bb-font-heading); font-size: clamp(1.25rem, 5vw, 2.5rem); font-weight: 800; color: rgba(255,255,255,0.55); }
.bb-app .bb-vs-hero__score-label { font-size: var(--bb-fs-xs); text-transform: uppercase; letter-spacing: .05em; color: rgba(255,255,255,0.78); }
@media (max-width: 480px) {
    .bb-app .bb-vs-hero__board { grid-template-columns: 1fr; gap: var(--bb-space-3); }
}

/* --- Attribute tug-of-war (replaces the radar) --- */
.bb-app .bb-compare-tug-box .bb-tug { margin-top: var(--bb-space-3); }
.bb-app .bb-tug__legend { display: flex; justify-content: space-between; font-size: var(--bb-fs-sm); font-weight: 700; color: var(--bb-text-secondary); margin-bottom: var(--bb-space-3); }
.bb-app .bb-tug__legend-item { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.bb-app .bb-tug__swatch { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 auto; }
.bb-app .bb-tug__legend-item--a .bb-tug__swatch { background: var(--bb-primary); }
.bb-app .bb-tug__legend-item--b .bb-tug__swatch { background: var(--bb-navy-mid); }
.bb-app .bb-tug__row { margin: 0 0 var(--bb-space-4); }
.bb-app .bb-tug__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--bb-space-2); margin-bottom: 5px; }
.bb-app .bb-tug__label { font-size: var(--bb-fs-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--bb-text-muted); text-align: center; flex: 1; }
.bb-app .bb-tug__val { font-family: var(--bb-font-heading); font-weight: 800; font-size: var(--bb-fs-md, 15px); font-variant-numeric: tabular-nums; }
.bb-app .bb-tug__val--a { color: var(--bb-primary); }
.bb-app .bb-tug__val--b { color: var(--bb-navy-mid); }
.bb-app .bb-tug__bar { display: flex; align-items: stretch; height: 14px; border-radius: var(--bb-radius-full, 999px); overflow: hidden; background: var(--bb-gray-100); }
.bb-app .bb-tug__fill { height: 100%; transition: width .35s ease; }
.bb-app .bb-tug__fill--a { background: var(--bb-primary); border-radius: var(--bb-radius-full, 999px) 0 0 var(--bb-radius-full, 999px); }
.bb-app .bb-tug__fill--b { background: var(--bb-navy-mid); border-radius: 0 var(--bb-radius-full, 999px) var(--bb-radius-full, 999px) 0; margin-left: auto; }
.bb-app .bb-tug__center { width: 2px; background: rgba(255,255,255,0.85); flex: 0 0 auto; }
.bb-app .bb-tug__note { margin: var(--bb-space-3) 0 0; font-size: var(--bb-fs-xs); color: var(--bb-text-muted); }

/* --- Compare discovery surface (cold open) --- */
.bb-app .bb-compare-discover { display: flex; flex-direction: column; gap: var(--bb-space-6); }
.bb-app .bb-compare-examples { background: var(--bb-gray-50); border: 1px solid var(--bb-border); border-radius: var(--bb-radius-lg, 12px); padding: var(--bb-space-6); }
.bb-app .bb-compare-examples__head { display: flex; align-items: center; justify-content: space-between; gap: var(--bb-space-3); flex-wrap: wrap; margin-bottom: var(--bb-space-4); }
.bb-app .bb-compare-examples__title { font-family: var(--bb-font-heading); font-size: var(--bb-fs-lg, 18px); font-weight: 800; margin: 0; }
.bb-app .bb-compare-examples__grid { display: grid; grid-template-columns: 1fr; gap: var(--bb-space-3); }
@media (min-width: 480px) { .bb-app .bb-compare-examples__grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .bb-app .bb-compare-examples__grid { grid-template-columns: 1fr 1fr 1fr; } }
.bb-app .bb-compare-example {
    display: flex; flex-direction: column; gap: 2px;
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
    padding: var(--bb-space-3) var(--bb-space-4);
    text-decoration: none !important;
    transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.bb-app .bb-compare-example:hover { border-color: var(--bb-primary); box-shadow: var(--bb-shadow-md, 0 8px 24px rgba(34, 28, 24,.10)); transform: translateY(-2px); }
.bb-app .bb-compare-example__label { font-weight: 700; font-size: var(--bb-fs-sm); color: var(--bb-text-primary); }
.bb-app .bb-compare-example__meta { font-size: var(--bb-fs-xs); color: var(--bb-text-muted); font-variant-numeric: tabular-nums; }
.bb-app .bb-compare-examples__more { margin: var(--bb-space-4) 0 0; font-size: var(--bb-fs-sm); font-weight: 600; }

/* ==========================================================================
   TOOLS / CALCULATOR SUITE  (Wave 7, plan 3.7)
   One shared .bb-calc-* component set reused across the four DB-benchmarked
   tools (ffmi / lean-mass / genetic-potential / grecian-ideal). Replaces the
   repeated inline-style recipes (unit toggle, stat-card cluster, share bar,
   eyebrow label, result callout) and adds the result-screen visualization
   family (gauge / progress bar / proportion dial / composition bar) plus the
   champion comparison card. SVG-only viz: declarative, crisp, no new lib.
   Brand result-state mapping: positive/within-natural = gold, beyond-ceiling/
   enhanced = crimson, neutral/in-progress = navy.
   ========================================================================== */

/* ---- result-state palette helpers (on-brand, replaces #22c55e/#f97316 etc) ---- */
.bb-app .bb-calc-state--gold   { --bb-calc-color: var(--bb-gold-champion); --bb-calc-ink: var(--bb-gold-text); }
.bb-app .bb-calc-state--crimson{ --bb-calc-color: var(--bb-primary, #b23a35);      --bb-calc-ink: var(--bb-primary-hover, #8f2e2a); }
.bb-app .bb-calc-state--navy   { --bb-calc-color: var(--bb-navy-mid);      --bb-calc-ink: var(--bb-navy); }

/* ---- shared eyebrow label ---- */
.bb-app .bb-calc-eyebrow {
    font-size: var(--bb-fs-xs, 12px);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-muted);
    margin: 0 0 var(--bb-space-3, 12px);
}

/* ---- unit toggle (segmented) ---- */
.bb-app .bb-calc-units { display: flex; justify-content: flex-end; margin-bottom: var(--bb-space-4, 16px); }
.bb-app .bb-calc-units__group { display: inline-flex; border: 2px solid var(--bb-border); border-radius: var(--bb-radius); overflow: hidden; }
.bb-app .bb-calc-units__btn { border-radius: 0 !important; border: none !important; min-width: 80px; }

/* ---- centered stat cluster ---- */
.bb-app .bb-calc-stats { margin-bottom: var(--bb-space-6, 24px); }
.bb-app .bb-calc-stats .bb-stat-card { text-align: center; }
.bb-app .bb-calc-stats .bb-stat-card-value { font-size: 2rem; font-weight: 800; }
.bb-app .bb-calc-stat--primary .bb-stat-card-value { color: var(--bb-primary); }
.bb-app .bb-calc-stat--navy .bb-stat-card-value { color: var(--bb-navy); }

/* =========================================================================
   Result visualization family (one canvas-free kit, SVG + CSS bars)
   ========================================================================= */
.bb-app .bb-calc-viz {
    margin-bottom: var(--bb-space-6, 24px);
    padding: var(--bb-space-5, 20px);
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg, 14px);
}
.bb-app .bb-calc-viz__caption {
    margin: var(--bb-space-3, 12px) 0 0;
    font-size: var(--bb-fs-xs, 12px);
    color: var(--bb-text-muted);
    text-align: center;
}

/* ---- FFMI gauge (SVG arc with zones + needle + champion ticks) ---- */
.bb-app .bb-gauge { display: block; width: 100%; max-width: 460px; margin: 0 auto; height: auto; }
.bb-app .bb-gauge__track { fill: none; stroke: var(--bb-gray-200); stroke-width: 18; stroke-linecap: round; }
.bb-app .bb-gauge__zone { fill: none; stroke-width: 18; }
.bb-app .bb-gauge__zone--natural { stroke: var(--bb-gold-champion); }
.bb-app .bb-gauge__zone--ceiling  { stroke: var(--bb-navy-mid); }
.bb-app .bb-gauge__zone--elite    { stroke: var(--bb-primary, #b23a35); }
.bb-app .bb-gauge__needle { stroke: var(--bb-navy); stroke-width: 3; stroke-linecap: round; }
.bb-app .bb-gauge__hub { fill: var(--bb-navy); }
.bb-app .bb-gauge__tick { stroke: var(--bb-text-secondary); stroke-width: 2; opacity: 0.7; }
.bb-app .bb-gauge__value { font-family: var(--bb-font-heading); font-weight: 800; fill: var(--bb-navy); }
.bb-app .bb-gauge__label { font-family: var(--bb-font-body); font-weight: 600; fill: var(--bb-text-muted); text-transform: uppercase; letter-spacing: 0.05em; }
.bb-app .bb-gauge-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--bb-space-2) var(--bb-space-5); margin: var(--bb-space-3) 0 0; font-size: var(--bb-fs-xs, 12px); color: var(--bb-text-secondary); }
.bb-app .bb-gauge-legend__item { display: inline-flex; align-items: center; gap: 6px; }
.bb-app .bb-gauge-legend__swatch { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 auto; }
.bb-app .bb-gauge-legend__swatch--natural { background: var(--bb-gold-champion); }
.bb-app .bb-gauge-legend__swatch--ceiling { background: var(--bb-navy-mid); }
.bb-app .bb-gauge-legend__swatch--elite { background: var(--bb-primary, #b23a35); }

/* ---- progress-to-ceiling bar (genetic potential) ---- */
.bb-app .bb-progbar { position: relative; }
.bb-app .bb-progbar__track {
    position: relative;
    height: 28px;
    background: var(--bb-gray-100);
    border-radius: var(--bb-radius-full, 999px);
    overflow: hidden;
}
.bb-app .bb-progbar__fill {
    position: absolute; inset: 0 auto 0 0;
    background: var(--bb-calc-color, var(--bb-navy-mid));
    border-radius: var(--bb-radius-full, 999px);
    transition: width .45s var(--bb-ease-out, ease);
    min-width: 6px;
}
.bb-app .bb-progbar__ceiling {
    position: absolute; top: -4px; bottom: -4px;
    width: 3px; left: 100%;
    background: var(--bb-navy);
    transform: translateX(-3px);
}
.bb-app .bb-progbar__scale { display: flex; justify-content: space-between; margin-top: var(--bb-space-2, 8px); font-size: var(--bb-fs-xs, 12px); color: var(--bb-text-muted); }
.bb-app .bb-progbar__pct { font-family: var(--bb-font-heading); font-weight: 800; font-size: 1.4rem; color: var(--bb-calc-ink, var(--bb-navy)); text-align: center; margin-bottom: var(--bb-space-2, 8px); }

/* ---- proportion dial (grecian ideal: ratio vs 1.618) ---- */
.bb-app .bb-dial { display: block; width: 100%; max-width: 320px; margin: 0 auto; height: auto; }
.bb-app .bb-dial__track { fill: none; stroke: var(--bb-gray-200); stroke-width: 16; stroke-linecap: round; }
.bb-app .bb-dial__progress { fill: none; stroke: var(--bb-calc-color, var(--bb-gold-champion)); stroke-width: 16; stroke-linecap: round; transition: stroke-dashoffset .45s var(--bb-ease-out, ease); }
.bb-app .bb-dial__target { fill: none; stroke: var(--bb-navy); stroke-width: 16; stroke-dasharray: 2 6; opacity: 0.45; }
.bb-app .bb-dial__value { font-family: var(--bb-font-heading); font-weight: 800; fill: var(--bb-navy); }
.bb-app .bb-dial__sub { font-family: var(--bb-font-body); font-weight: 600; fill: var(--bb-text-muted); }

/* ---- composition bar (lean-mass: lean vs fat) ---- */
.bb-app .bb-compbar { display: flex; height: 40px; border-radius: var(--bb-radius); overflow: hidden; border: 1px solid var(--bb-border); }
.bb-app .bb-compbar__seg { display: flex; align-items: center; justify-content: center; font-size: var(--bb-fs-sm, 14px); font-weight: 700; color: #fff; white-space: nowrap; transition: width .45s var(--bb-ease-out, ease); min-width: 0; overflow: hidden; }
.bb-app .bb-compbar__seg--lean { background: var(--bb-gold-champion); color: var(--bb-gold-text); }
.bb-app .bb-compbar__seg--fat { background: var(--bb-navy-mid); }
.bb-app .bb-compbar__key { display: flex; flex-wrap: wrap; gap: var(--bb-space-2) var(--bb-space-5); margin-top: var(--bb-space-3, 12px); font-size: var(--bb-fs-xs, 12px); color: var(--bb-text-secondary); }
.bb-app .bb-compbar__key-item { display: inline-flex; align-items: center; gap: 6px; }
.bb-app .bb-compbar__key-swatch { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 auto; }
.bb-app .bb-compbar__key-swatch--lean { background: var(--bb-gold-champion); }
.bb-app .bb-compbar__key-swatch--fat { background: var(--bb-navy-mid); }

/* =========================================================================
   Champion comparison card (the signature hook) - monogram + delta bar
   ========================================================================= */
.bb-app .bb-champ-card {
    display: flex;
    gap: var(--bb-space-4, 16px);
    align-items: center;
    padding: var(--bb-space-5, 20px);
    background: linear-gradient(135deg, var(--bb-navy), var(--bb-navy-mid));
    border-radius: var(--bb-radius-lg, 14px);
    color: #fff;
}
.bb-app .bb-champ-card__monogram {
    flex: 0 0 auto;
    width: 58px; height: 58px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.08);
    border: 2px solid var(--bb-gold-champion);
    font-family: var(--bb-font-heading);
    font-weight: 800;
    font-size: 1.25rem;
    color: var(--bb-gold-champion);
    letter-spacing: 0.02em;
}
.bb-app .bb-champ-card__body { flex: 1 1 auto; min-width: 0; }
.bb-app .bb-champ-card__name { font-family: var(--bb-font-heading); font-weight: 800; font-size: var(--bb-fs-lg, 18px); line-height: 1.2; color: #fff; }
.bb-app .bb-champ-card__cred { font-size: var(--bb-fs-xs, 12px); color: var(--bb-gold-champion); font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; margin-top: 2px; }
.bb-app .bb-champ-card__nums { display: flex; align-items: baseline; gap: var(--bb-space-5, 20px); margin-top: var(--bb-space-3, 12px); }
.bb-app .bb-champ-card__num { display: flex; flex-direction: column; gap: 2px; }
.bb-app .bb-champ-card__num-label { font-size: var(--bb-fs-2xs, 11px); text-transform: uppercase; letter-spacing: 0.05em; color: rgba(255,255,255,0.65); }
.bb-app .bb-champ-card__num-value { font-family: var(--bb-font-heading); font-weight: 800; font-size: 1.45rem; line-height: 1; }
.bb-app .bb-champ-card__num--you .bb-champ-card__num-value { color: var(--bb-primary, #b23a35); }
.bb-app .bb-champ-card__num--them .bb-champ-card__num-value { color: var(--bb-gold-champion); }
.bb-app .bb-champ-card__delta { display: flex; align-items: center; gap: var(--bb-space-3, 12px); margin-top: var(--bb-space-3, 12px); }
.bb-app .bb-champ-card__delta-track { position: relative; flex: 1 1 auto; height: 6px; border-radius: var(--bb-radius-full, 999px); background: rgba(255,255,255,0.16); overflow: hidden; }
.bb-app .bb-champ-card__delta-fill { position: absolute; top: 0; bottom: 0; background: var(--bb-primary, #b23a35); border-radius: var(--bb-radius-full, 999px); transition: left .4s var(--bb-ease-out, ease), width .4s var(--bb-ease-out, ease); }
.bb-app .bb-champ-card__delta-text { flex: 0 0 auto; font-size: var(--bb-fs-xs, 12px); font-weight: 700; color: rgba(255,255,255,0.92); white-space: nowrap; }
.bb-app .bb-champ-card__cta {
    flex: 0 0 auto;
    align-self: stretch;
    display: inline-flex; align-items: center;
    padding: 0 var(--bb-space-4, 16px);
    border-radius: var(--bb-radius);
    background: var(--bb-gold-champion);
    color: var(--bb-gold-text) !important;
    font-weight: 700;
    font-size: var(--bb-fs-sm, 14px);
    text-decoration: none !important;
    white-space: nowrap;
    transition: filter .15s ease, transform .15s ease;
}
.bb-app .bb-champ-card__cta:hover { filter: brightness(1.06); transform: translateY(-1px); }
@media (max-width: 560px) {
    .bb-app .bb-champ-card { flex-wrap: wrap; }
    .bb-app .bb-champ-card__cta { width: 100%; justify-content: center; padding: var(--bb-space-3) var(--bb-space-4); margin-top: var(--bb-space-2); }
}

/* =========================================================================
   Share bar with real SVG brand icons (replaces "X" / "FB" text buttons)
   ========================================================================= */
.bb-app .bb-calc-share { display: flex; gap: var(--bb-space-2, 8px); align-items: center; flex-wrap: wrap; margin-bottom: var(--bb-space-6, 24px); padding-top: var(--bb-space-4, 16px); border-top: 1px solid var(--bb-border); }
.bb-app .bb-calc-share__label { font-size: var(--bb-fs-sm, 14px); color: var(--bb-text-muted); }
.bb-app .bb-share-btn {
    display: inline-flex; align-items: center; gap: 6px;
    min-height: 38px; padding: 0 var(--bb-space-3, 12px);
    border: 1px solid var(--bb-border-strong, #cfc4b6);
    border-radius: var(--bb-radius);
    background: var(--bb-surface, #fff);
    color: var(--bb-text-secondary);
    font-size: var(--bb-fs-sm, 14px);
    font-weight: 600;
    cursor: pointer;
    transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.bb-app .bb-share-btn:hover { border-color: var(--bb-primary); color: var(--bb-primary); }
.bb-app .bb-share-btn svg { width: 16px; height: 16px; flex: 0 0 auto; fill: currentColor; }

/* =========================================================================
   Tools hub: SVG feature icons + suite trust strip
   ========================================================================= */
.bb-app .bb-tools-trust {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--bb-space-3) var(--bb-space-6);
    margin: 0 0 var(--bb-space-8, 32px);
    padding: var(--bb-space-4, 16px) var(--bb-space-5, 20px);
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-border);
    border-left: 4px solid var(--bb-gold-champion);
    border-radius: var(--bb-radius-lg, 14px);
}
.bb-app .bb-tools-trust__stat { display: flex; flex-direction: column; }
.bb-app .bb-tools-trust__num { font-family: var(--bb-font-heading); font-weight: 800; font-size: 1.5rem; color: var(--bb-navy); line-height: 1; }
.bb-app .bb-tools-trust__label { font-size: var(--bb-fs-xs, 12px); color: var(--bb-text-muted); margin-top: 2px; }
.bb-app .bb-tools-trust__copy { flex: 1 1 220px; font-size: var(--bb-fs-sm, 14px); color: var(--bb-text-secondary); margin: 0; min-width: 0; }

/* =========================================================================
   Athlete directory (moved from template)
   Relocated verbatim from the in-file <style> block in
   public/templates/athletes/index.php: champion-row texture, sortable-header
   focus rings, .bb-state-copied, button.bb-state-chip tokens, mobile rules.
   ========================================================================= */
/* Single keyboard stop per athlete row: the name link is the focus target. */
.bb-app .bb-athlete-row .bb-athlete-link:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color, var(--bb-primary));
    outline-offset: var(--bb-focus-ring-offset, 2px);
    border-radius: 3px;
}
/* Sortable column headers are keyboard-operable (tabindex + Enter/Space), so they
   need a visible focus ring; the implicit columnheader role + aria-sort stay intact. */
.bb-app th.bb-sortable:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color, var(--bb-primary));
    outline-offset: -2px;
}
/* Persistent underline on the name link: affordance not by color alone. */
.bb-app .bb-athlete-row .bb-athlete-link {
    text-decoration: underline;
    text-decoration-color: var(--bb-gray-300);
    text-underline-offset: 2px;
    font-weight: 600;
    color: var(--bb-text-primary);
}
.bb-app .bb-athlete-row .bb-athlete-link:hover {
    text-decoration-color: var(--bb-primary);
}
/* Champion texture: real Olympia title-holders get a subtle gold tint + a gold
   left marker so the legends read at a glance among high-volume competitors.
   Keyed on a real champion signal (olympia_titles > 0), never on wins, so the
   emphasis stays selective rather than lighting up every row. */
.bb-app .bb-athlete-row--champion > td:first-child {
    box-shadow: inset 3px 0 0 0 var(--bb-gold-champion);
}
.bb-app .bb-athlete-row--champion {
    background: linear-gradient(90deg, rgba(217, 139, 74, 0.07) 0%, transparent 60%);
}
.bb-app .bb-athlete-row--champion:hover {
    background: linear-gradient(90deg, rgba(217, 139, 74, 0.12) 0%, transparent 60%);
}
.bb-app .bb-champ-marker {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-right: 6px;
    padding: 1px 5px 1px 4px;
    border-radius: 10px;
    background: var(--bb-gold-champion);
    color: var(--bb-gold-text);
    font-size: 11px;
    font-weight: 800;
    line-height: 1;
    vertical-align: middle;
}
.bb-app .bb-champ-marker svg { display: block; }
.bb-app .bb-champ-marker__n { font-size: 11px; }
/* On the stacked-card mobile view the marker sits inline before the name; keep it
   from pushing the name to a second line awkwardly. */
@media (max-width: 768px) {
    .bb-app .bb-athlete-row--champion > td:first-child { box-shadow: inset 0 3px 0 0 var(--bb-gold-champion); }
}
/* Trim the mobile control fold so an actual athlete shows in the first screen:
   the stats-strip compresses so the search and first rows surface sooner.
   Desktop is unchanged.

   The subtitle used to be hidden here too. That reasoning only held for the one
   page it was written for: the athletes directory, where the comment noted "the
   SEO copy lower down carries the same content". But the selector is the bare
   .bb-page-header--dark class, which 27 templates carry, so it deleted the
   subtitle from all of them. Measured at 390px: 13 of 13 routes with a subtitle
   lost it, 0 kept it - including "Complete results from 1965 to present. Every
   year, every division, every champion." on /olympia/, and equivalents on
   /arnold/, /contests/, /countries/, /divisions/, /rankings/, /compare/,
   /fantasy/, /widgets/, /calculators/, /tools/ and /rivalries/, none of which
   repeat that copy lower down.

   Losing a page's own description on 12 routes to save about 40px of fold on one
   is the wrong trade, and on mobile the sentence explaining what the page is
   matters more, not less. Line-clamping it instead was considered and rejected:
   a truncated subtitle with no way to read the rest is the same defect in a
   quieter form. If the athletes directory specifically needs a tighter fold, the
   fix is a modifier on that template, not a rule aimed at every dark header. */
@media (max-width: 640px) {
    .bb-app .bb-stats-strip { padding: 12px 10px; margin-bottom: 14px; }
    .bb-app .bb-stats-strip .bb-stat-label { font-size: var(--bb-fs-2xs); }
    .bb-app .bb-page-header.bb-page-header--dark { padding: 16px; margin-bottom: 14px; }
    .bb-app .bb-stats-strip {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 0;
    }
    .bb-app .bb-stats-strip .bb-stat-item {
        min-width: 0;
        padding: 0 var(--bb-space-1);
    }
    .bb-app .bb-directory-container .bb-filter-bar {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .bb-app .bb-directory-container .bb-division-filter,
    .bb-app .bb-directory-container .bb-toolbar-search {
        grid-column: 1 / -1;
    }
    .bb-app .bb-directory-container .bb-division-filter {
        flex-wrap: nowrap;
        gap: 0;
        overflow-x: auto;
    }
    .bb-app .bb-directory-container .bb-division-filter .bb-toolbar-tab {
        flex: 0 0 auto;
        padding-inline: var(--bb-space-3);
        white-space: nowrap;
    }
}
/* Removable filter tokens reuse the .bb-state-chip pill (authored for spans),
   so reset the default <button> chrome and add the close-glyph spacing. */
.bb-app button.bb-state-chip {
    border: 0;
    font: inherit;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    gap: 6px;
}
.bb-app button.bb-state-chip:hover { background: rgba(34, 28, 24, 0.16); }
.bb-app button.bb-state-chip:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color, var(--bb-primary));
    outline-offset: var(--bb-focus-ring-offset, 2px);
}
/* Transient "Link copied" confirmation beside the Share button. Sits inside the
   .bb-filter-state aria-live region so it is announced as well as shown. */
.bb-app .bb-state-copied {
    display: inline-flex;
    align-items: center;
    min-height: 30px;
    padding: 6px 10px;
    font-size: 12px;
    font-weight: 700;
    color: var(--bb-success);
}
.bb-app .bb-state-copied[hidden] {
    display: none;
}

/* ==========================================================================
   Hub Mr-Olympia widget
   De-inlined from hub.php (the front-door countdown/leaderboard promo).

   LIGHT CARD, GOLD TOP RULE (brief §7). This was a dark espresso gradient band -
   a deliberate choice at the time, and the comment that used to sit here said so.
   The brief overrides it: the hub has one dark element, the hero, and a second
   dark band directly beneath it made the countdown compete with the headline
   instead of sitting under it. The gold now arrives as a 3px top rule rather than
   as glowing numerals on black.

   Gold on light is --bb-amber-on-light (#8f5a1e), never --bb-amber (#d98b4a):
   #d98b4a on bone measures about 2.4:1, which fails at any text size.
   ========================================================================== */
.bb-app .bb-olympia-hub-widget { margin-bottom: 32px; }

.bb-app .bb-olympia-hub-card {
    background: var(--bb-surface-raised);
    border: 1px solid var(--bb-border);
    border-top: 3px solid var(--bb-amber-on-light);
    border-radius: 6px;
    overflow: hidden;
    position: relative;
    padding: 28px clamp(18px, 4.4vw, 32px);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
    box-shadow: none;
}

/* The two decorative rings were white-tint circles that only read on the dark
   band; on paper they were invisible. Kept as a faint ink hairline so the card
   has some depth at the top right, where the CTA is not. */
.bb-app .bb-olympia-hub-ring {
    position: absolute;
    border-radius: 50%;
    pointer-events: none;
}
.bb-app .bb-olympia-hub-ring--lg {
    right: -60px;
    top: -60px;
    width: 260px;
    height: 260px;
    border: 1px solid rgba(34, 28, 24, 0.06);
}
.bb-app .bb-olympia-hub-ring--sm {
    right: -20px;
    top: -20px;
    width: 160px;
    height: 160px;
    border: 1px solid rgba(34, 28, 24, 0.05);
}

.bb-app .bb-olympia-hub-info {
    flex: 1;
    min-width: 220px;
    position: relative;
    z-index: 1;
}

.bb-app .bb-olympia-hub-eyebrow {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}
.bb-app .bb-olympia-hub-status {
    /* POLISH PASS 3: filled status chip carries the one oxblood accent (the old
       gold chip was a dead-selector leak from the de-inlining). */
    background: var(--bb-primary);
    color: #fff;
    font-size: var(--bb-fs-2xs);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 3px 10px;
    border-radius: 20px;
}
.bb-app .bb-olympia-hub-year {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}

.bb-app .bb-olympia-hub-headline {
    color: var(--bb-ink);
    font-family: var(--bb-font-heading);
    font-size: 1.55rem;
    font-weight: 700;
    font-stretch: 88%;
    letter-spacing: -0.015em;
    margin: 0 0 8px;
    line-height: 1.2;
}
.bb-app .bb-olympia-hub-tagline {
    color: var(--bb-text-secondary);
    font-size: 0.9rem;
    margin: 0 0 16px;
    line-height: 1.5;
}

.bb-app .bb-olympia-hub-countdown {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

/* The row wraps instead of overflowing. With the colon cells gone there are four
   equal children and nothing that has to stay on one line. */
.bb-app .bb-olympia-hub-countdown-inner {
    display: flex;
    gap: 10px 14px;
    flex-wrap: wrap;
}
.bb-app .bb-olympia-hub-unit {
    text-align: center;
    min-width: 62px;
    padding: 10px 12px;
    background: var(--bb-surface-sunken);
    border-radius: 4px;
}
.bb-app .bb-olympia-hub-unit-value {
    /* §7: clamp(30px, 7vw, 46px). Mono, because every figure in the design is
       mono - and on a ticking clock tabular-nums is what stops the digits
       jiggling once per second. */
    font-family: var(--bb-font-mono);
    font-size: clamp(30px, 7vw, 46px);
    font-weight: 600;
    color: var(--bb-ink);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}
.bb-app .bb-olympia-hub-unit-label {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-top: 4px;
}
.bb-app .bb-olympia-hub-expired {
    font-family: var(--bb-font-heading);
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--bb-primary);
}

.bb-app .bb-olympia-hub-cta,
.bb-app .bb-olympia-hub-cta:link,
.bb-app .bb-olympia-hub-cta:visited {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    /* POLISH PASS 3: primary action = the one oxblood accent (matches every
       other .bb-btn-primary), not a second gold button competing with the
       countdown. Gold stays on the numerals only. */
    background: linear-gradient(135deg, var(--bb-primary), var(--bb-primary-hover));
    color: var(--bb-on-dark);
    font-weight: 700;
    font-size: 0.9rem;
    padding: 10px 22px;
    border-radius: 8px;
    text-decoration: none;
    transition: background 0.15s, transform 0.15s;
}
.bb-app .bb-olympia-hub-cta:hover,
.bb-app .bb-olympia-hub-cta:focus-visible {
    background: var(--bb-primary-hover);
    color: var(--bb-on-dark);
    transform: translateY(-1px);
}
.bb-app .bb-olympia-hub-cta-icon { flex-shrink: 0; }

.bb-app .bb-olympia-hub-stats {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 160px;
    position: relative;
    z-index: 1;
}
.bb-app .bb-olympia-hub-pill {
    background: var(--bb-surface-sunken);
    border-radius: 4px;
    padding: 12px 16px;
    text-align: center;
    border: 1px solid var(--bb-border);
}
.bb-app .bb-olympia-hub-pill-value {
    font-family: var(--bb-font-mono);
    font-size: 1.4rem;
    font-weight: 600;
    color: var(--bb-ink);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}
/* --gold on a light pill has to be the on-light amber. The old value was
   --bb-amber, which is the on-dark one and only passed against the espresso
   band this card no longer has. */
.bb-app .bb-olympia-hub-pill-value--gold { color: var(--bb-amber-on-light); }
.bb-app .bb-olympia-hub-pill-label {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    color: var(--bb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-top: 3px;
}

/* ==========================================================================
   Latest Coverage (editorial <-> data flywheel, bb_latest_coverage())
   Links data pages to FitnessVolt editorial posts sharing the same post_tag.
   Editorial-archive theme: hairline borders, no shadows, oxblood accent.
   ========================================================================== */
.bb-app .bb-coverage {
    margin: var(--bb-space-10) 0 var(--bb-space-6);
    padding-top: var(--bb-space-5);
    border-top: 1px solid var(--bb-border);
}
.bb-app .bb-coverage-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: var(--bb-space-2);
}
.bb-app .bb-coverage-item {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--bb-space-3);
    border-bottom: 1px solid var(--bb-border);
    padding-bottom: var(--bb-space-2);
}
.bb-app .bb-coverage-item:last-child {
    border-bottom: none;
    padding-bottom: 0;
}
.bb-app .bb-coverage-link {
    font-weight: 600;
    color: var(--bb-text-primary);
    text-decoration: none;
}
.bb-app .bb-coverage-link:hover {
    color: var(--bb-primary);
}
.bb-app .bb-coverage-date {
    font-size: 0.8rem;
    color: var(--bb-text-muted);
    white-space: nowrap;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}
.bb-app .bb-coverage-all {
    display: inline-block;
    margin-top: var(--bb-space-3);
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--bb-primary);
    text-decoration: none;
}
.bb-app .bb-coverage-all:hover {
    text-decoration: underline;
}

/* ---------------------------------------------------------------
 * Source attribution line (partials/source-line.php)
 * This is not an SSR-summary child and remains visible after hydration.
 * --------------------------------------------------------------- */
.bb-source-line {
    margin: 12px 0 24px;
    padding-top: 10px;
    border-top: 1px solid var(--bb-border);
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--bb-text-muted);
}
.bb-source-line a {
    color: var(--bb-text-secondary);
    font-weight: 600;
    text-decoration: none;
}
.bb-source-line a:hover {
    color: var(--bb-primary);
    text-decoration: underline;
}

/*
 * The attribution line in its one fixed home: last thing in the content,
 * directly above the section footer.
 *
 * It used to print wherever each of sixteen templates happened to include the
 * partial, anywhere from 30% to 99% down the page, so a bottom margin that
 * suited mid-article spacing was all it could ask for. Now that it always sits
 * against the footer, it gets more room above it to read as a closing statement
 * and none below, because the footer supplies its own.
 */
.bb-source-line--footer {
    margin: 32px 0 0;
    padding-top: 14px;
}

/* ---------------------------------------------------------------
 * Consolidated Data-Trust Bar (.bb-data-trust-bar)
 * Slim horizontal strip rendered ONCE in the hydrated Alpine
 * template, directly under the .bb-profile-header hero. Shows:
 *   confidence badge | Updated <date> | Accurate? thumbs |
 *   Report an issue | Help improve this data [expand toggle]
 *
 * Light theme only. The bar sits on the white page background,
 * NOT the dark hero, so .bb-report-btn needs light-context styles.
 * --------------------------------------------------------------- */
.bb-data-trust-bar {
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    background: var(--bb-surface, #fafafa);
    padding: 0.55rem var(--bb-space-4, 1.25rem);
    margin: 0 0 var(--bb-space-5, 1.5rem);
}

.bb-data-trust-bar__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0;
    font-family: var(--bb-font-body);
    font-size: var(--bb-fs-xs, 0.78rem);
    color: var(--bb-text-secondary, #555);
    min-height: 36px;
}

/* Dot separator between segments */
.bb-data-trust-bar__sep {
    display: inline-block;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: var(--bb-text-muted);
    margin: 0 0.6rem;
    flex-shrink: 0;
    vertical-align: middle;
}

.bb-data-trust-bar__badge {
    flex-shrink: 0;
}

.bb-data-trust-bar__date {
    color: var(--bb-text-muted);
    white-space: nowrap;
    flex-shrink: 0;
}

.bb-data-trust-bar__rating {
    flex-shrink: 0;
}

/* Report button -- light-background context override.
   The hero-scoped .bb-app .bb-report-btn rule uses translucent
   white colours suited for the dark hero. Here the bar sits on
   a light surface so we need a restrained dark-text ghost style. */
.bb-data-trust-bar .bb-data-trust-bar__report {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.45em 0.75em;
    min-height: 44px;
    font: inherit;
    font-size: var(--bb-fs-xs, 0.78rem);
    font-weight: 600;
    color: var(--bb-text-secondary);
    background: transparent;
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius, 4px);
    cursor: pointer;
    transition: background-color var(--bb-transition, 0.15s), border-color var(--bb-transition, 0.15s), color var(--bb-transition, 0.15s);
    white-space: nowrap;
    flex-shrink: 0;
}

.bb-data-trust-bar .bb-data-trust-bar__report:hover {
    color: var(--bb-text-primary, #1a1a1a);
    border-color: var(--bb-text-secondary);
    background: var(--bb-surface-hover, #f3f4f6);
}

.bb-data-trust-bar .bb-data-trust-bar__report:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset, 2px);
}

/* "Help improve" toggle button */
.bb-data-trust-bar__improve-wrap {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

.bb-data-trust-bar__improve-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2em 0;
    min-height: 44px;
    font: inherit;
    font-size: var(--bb-fs-xs, 0.78rem);
    font-weight: 600;
    color: var(--bb-accent, #b23a35);
    background: none;
    border: none;
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: color var(--bb-transition, 0.15s);
}

.bb-data-trust-bar__improve-btn:hover {
    color: var(--bb-accent-dark, #8c1f1b);
    text-decoration: underline;
}

.bb-data-trust-bar__improve-btn:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset, 2px);
}

/* Chevron icon that rotates when panel is open */
.bb-data-trust-bar__chevron {
    transition: transform var(--bb-transition, 0.15s);
    flex-shrink: 0;
}

.bb-data-trust-bar__chevron--open {
    transform: rotate(180deg);
}

/* Expand panel containing verify prompts + bio-submit form */
.bb-data-trust-bar__improve-panel {
    border-top: 1px solid var(--bb-border);
    padding: 0.9rem var(--bb-space-4, 1.25rem);
    background: var(--bb-surface, #fafafa);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: flex-start;
}

/* The .bb-athlete-bio-trigger buttons inside the expand panel */
.bb-data-trust-bar__improve-panel .bb-athlete-bio-trigger {
    display: inline-flex;
    align-items: center;
    padding: 0.3em 0.8em;
    font: inherit;
    font-size: var(--bb-fs-xs, 0.78rem);
    font-weight: 600;
    color: var(--bb-accent, #b23a35);
    background: transparent;
    border: 1px solid var(--bb-accent, #b23a35);
    border-radius: var(--bb-radius-full, 999px);
    cursor: pointer;
    transition: background-color var(--bb-transition, 0.15s), color var(--bb-transition, 0.15s);
    white-space: nowrap;
}

.bb-data-trust-bar__improve-panel .bb-athlete-bio-trigger:hover {
    background: var(--bb-accent, #b23a35);
    color: #fff;
}

.bb-data-trust-bar__improve-panel .bb-athlete-bio-trigger:focus-visible {
    outline: var(--bb-focus-ring-width, 2px) solid var(--bb-focus-ring-color);
    outline-offset: var(--bb-focus-ring-offset, 2px);
}

/* Alpine enter/leave transitions for the improve panel */
.bb-expand-enter,
.bb-expand-leave {
    transition: opacity 0.18s ease, transform 0.18s ease;
}
.bb-expand-enter-start,
.bb-expand-leave-end {
    opacity: 0;
    transform: translateY(-4px);
}
.bb-expand-enter-end,
.bb-expand-leave-start {
    opacity: 1;
    transform: translateY(0);
}

/* Mobile: stack the row items vertically on narrow screens */
@media (max-width: 600px) {
    .bb-data-trust-bar__sep {
        display: none;
    }
    .bb-data-trust-bar__row {
        gap: 0.5rem 0.6rem;
    }
    .bb-data-trust-bar {
        padding: 0.55rem var(--bb-space-3, 1rem);
    }
}

/* ---------------------------------------------------------------
 * About the Database page (about-the-database.php)
 * Mirrors the data-quality editorial layout: narrow measure,
 * intro card, accent-bordered corrections callout, citation block.
 * --------------------------------------------------------------- */
.bb-about-db { max-width: 860px; margin: 0 auto; padding-top: 8px; }
.bb-about-db h1 { margin: 0 0 12px; }
.bb-about-db h2 {
    font-size: 22px;
    margin: 40px 0 14px;
    padding-top: 8px;
    scroll-margin-top: 90px;
}
.bb-about-db p {
    line-height: 1.7;
    color: var(--bb-text-secondary);
    margin: 0 0 14px;
}
.bb-about-db ul {
    line-height: 1.7;
    color: var(--bb-text-secondary);
    margin: 0 0 16px;
    padding-left: 20px;
}
.bb-about-db li { margin-bottom: 8px; }
.bb-about-db strong { color: var(--bb-text-primary); }
.bb-about-db__intro-card {
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius, 12px);
    padding: 24px 26px;
    margin: 0 0 8px;
}
.bb-about-db__intro-head { margin-top: 0; }
.bb-about-db__lede {
    font-size: 18px;
    line-height: 1.7;
    color: var(--bb-text-secondary);
    margin: 0 0 12px;
}
.bb-about-db__counts {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 10px 24px;
    margin: 0 0 10px;
    padding: 0;
}
.bb-about-db__counts li { margin: 0; }
.bb-about-db__counts strong {
    font-variant-numeric: tabular-nums;
    color: var(--bb-text-primary);
}
.bb-about-db__counts-note {
    font-size: 0.8rem;
    color: var(--bb-text-muted);
    margin-bottom: 0;
}
.bb-about-db__cta {
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-border);
    border-left: 4px solid var(--bb-primary);
    border-radius: var(--bb-radius, 12px);
    padding: 22px 24px;
    margin: 16px 0 8px;
}
.bb-about-db__cta p:last-child { margin-bottom: 0; }
.bb-about-db__citation {
    margin: 0 0 14px;
    padding: 16px 20px;
    background: var(--bb-surface, #fff);
    border: 1px solid var(--bb-border);
    border-left: 4px solid var(--bb-primary);
    border-radius: var(--bb-radius, 12px);
    font-size: 15px;
    line-height: 1.7;
    color: var(--bb-text-secondary);
}

/* ---------------------------------------------------------------
 * Olympia upcoming-year page (olympia/detail.php scheduled state).
 * Fully server-rendered outside the hydration hide selectors.
 * --------------------------------------------------------------- */
.bb-olympia-upcoming__facts {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 20px;
    margin: 0 0 18px;
}
.bb-olympia-upcoming section {
    margin: 0 0 28px;
}
.bb-olympia-upcoming__links {
    margin: 8px 0 24px;
    font-size: 0.95rem;
}
.bb-olympia-upcoming__links a {
    color: var(--bb-primary);
    text-decoration: none;
}
.bb-olympia-upcoming__links a:hover { text-decoration: underline; }

/* =========================================================================
   Profile hero action polish (Lane B)
   One 44px action scale for Compare / Follow / Share. Compare is filled;
   secondary actions use translucent light hairlines on the dark hero.
   ========================================================================= */

/* Shared compact visual scale with accessible touch targets. */
.bb-app .bb-action-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: var(--bb-space-4, 1rem);
}

.bb-app .bb-action-row .bb-btn,
.bb-app .bb-action-row .bb-share-btn {
    min-height: 44px;
    margin: 0;
    padding: 0 14px;
    gap: 6px;
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    line-height: 1;
    border: 1px solid rgba(255, 253, 248, 0.32);
    border-radius: var(--bb-radius);
    background: rgba(255, 253, 248, 0.06);
    color: rgba(255, 253, 248, 0.92) !important;
    box-shadow: none;
}

.bb-app .bb-action-row .bb-btn:hover:not(:disabled),
.bb-app .bb-action-row .bb-share-btn:hover {
    background: rgba(255, 253, 248, 0.14);
    border-color: rgba(255, 253, 248, 0.55);
    color: var(--bb-on-dark) !important;
    transform: none;
}

.bb-app .bb-action-row .bb-btn svg,
.bb-app .bb-action-row .bb-share-btn svg {
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
}

/* Primary action: filled oxblood, identical height to the secondaries. */
.bb-app .bb-action-row .bb-btn-compare {
    background: var(--bb-primary);
    border-color: var(--bb-primary);
    color: #fff !important;
}

.bb-app .bb-action-row .bb-btn-compare:hover:not(:disabled) {
    background: var(--bb-primary-hover);
    border-color: var(--bb-primary-hover);
    color: #fff !important;
}

@media (max-width: 640px) {
    .bb-app .bb-action-row {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        width: 100%;
    }

    .bb-app .bb-action-row > .bb-btn-compare,
    .bb-app .bb-action-row > .bb-share-wrap:last-child {
        grid-column: 1 / -1;
    }

    .bb-app .bb-action-row > .bb-follow-wrap,
    .bb-app .bb-action-row > .bb-share-wrap {
        display: flex !important;
        width: 100%;
    }

    .bb-app .bb-action-row .bb-btn,
    .bb-app .bb-action-row .bb-share-btn {
        width: 100%;
        justify-content: center;
    }
}

/* ==========================================================================
   ATHLETE PROFILE BODY - per-section polish pass 2 (2026-06-09)
   Measured fixes against the editorial-data-authority language: hairline
   rules, warm ink, tabular numerals, one accent, consistent 16px rhythm.
   ========================================================================== */

/* FBref-density results table: 56px rows were bloated for a 50-row data
   table. 10px block padding lands rows at 48px with the same 14px type. */
.bb-athlete-profile-page .bb-table th {
    padding: 10px 16px;
}
.bb-athlete-profile-page .bb-table td {
    padding: 10px 16px;
}

/* Hairline language: the Compare chip carried a 2px border (button default). */
.bb-app .bb-rival-compare-btn {
    border-width: 1px;
}

/* Section rhythm: every profile section stacks at one 16px beat; Related
   Athletes alone jumped in with an extra 48px top margin. */
.bb-athlete-profile-page .bb-related-section {
    margin-top: 0;
}

/* Numerals in stat positions read in columns: tabular figures. */
.bb-app .bb-rival-record,
.bb-app .bb-rival-meta,
.bb-app .bb-related-stat,
.bb-app .bb-profile-glance-value {
    font-variant-numeric: tabular-nums;
}

/* --- Pass-2 completion (2026-06-09, measured on /athletes/ronnie-coleman/) --- */

/* Timeline year row is a stat axis: tabular figures so 18 year labels align
   on one optical grid (measured font-variant-numeric: normal). */
.bb-athlete-profile-page .bb-career-timeline-year-label {
    font-variant-numeric: tabular-nums;
}

/* One card radius on the profile body. Rival cards (12px via --bb-radius-md)
   and the sparkline figure (12px) sat next to 8px sections/related cards;
   the inner element can't be rounder than its container. */
.bb-athlete-profile-page .bb-rival-card,
.bb-athlete-profile-page .bb-chart {
    border-radius: var(--bb-radius-lg);
}

/* Hairline language: the Load More chip carried the 2px button-default border
   and a stray 10px radius (every neighbour control is 1px / 8px). */
.bb-athlete-profile-page .bb-btn-secondary {
    border-width: 1px;
    border-radius: var(--bb-radius-lg);
}

/* The timeline track scrolls horizontally on long careers (scrollWidth 1464
   vs 1102 visible) but gave no affordance - the last column just looked cut
   off. Thin persistent scrollbar + a breath of bottom padding signal it. */
.bb-athlete-profile-page .bb-career-timeline {
    scrollbar-width: thin;
    scrollbar-color: var(--bb-gray-300) transparent;
}

/* ==========================================================================
   POLISH PASS 3 - THE HUB (2026-06-09)
   Front-door pass against the editorial-data-authority language: warm paper,
   near-black ink, ONE oxblood accent, hairline rules not shadow blooms,
   tabular numerals, gold only where it means trophy. Measured via computed
   styles on http://localhost:8080/wpx/bodybuilding/ before and after.
   ========================================================================== */

/* -- Hero band ------------------------------------------------------------ */

/* Band radius parity: the hero sat at 8px while the two sibling dark bands
   (Olympia widget, Road-to-Olympia CTA) sit at 10px. One radius per tier:
   bands = --bb-radius-xl, cards = --bb-radius-lg. */
.bb-app .bb-hero {
    border-radius: var(--bb-radius-xl);
}

/* -- Section labels on paper ----------------------------------------------- */

/* The on-dark pill treatment (white-tint bg + white-tint border) is invisible
   on the white page sections, but its 12px padding indented every section
   eyebrow off the left edge of its own H2. On paper the label is a plain
   uppercase oxblood eyebrow, flush with the heading. */
.bb-app .bb-section-header .bb-section-label {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
}

/* -- News grid ------------------------------------------------------------- */

/* Radius parity with every other card surface (12px was the lone outlier
   against the 8px division/athlete/contest/data/OTD cards). */
.bb-app .bb-news-card {
    border-radius: var(--bb-radius-lg);
}

.bb-app .bb-news-date {
    font-variant-numeric: tabular-nums;
}

/* -- Database feature cards ------------------------------------------------ */

/* Hairline hover like every other retheme card: accent hairline, no lift,
   no shadow bloom (the cards still had the pre-retheme -2px translate +
   --bb-shadow-md treatment). */
.bb-app .bb-data-card:hover {
    transform: none;
    border-color: rgba(178, 58, 53, 0.34);
    box-shadow: 0 1px 2px rgba(34, 28, 24, 0.07);
}

/* -- Divisions grid -------------------------------------------------------- */

/* The male gender glyph still carried the retired electric-navy
   (rgba(34, 28, 24, .1) + --bb-navy-mid). The mars/venus glyph already encodes
   gender; ink-neutral male + oxblood female keeps scanning contrast on the
   one-accent palette. */
.bb-app .bb-division-gender-icon--male {
    background: var(--bb-gray-100);
    color: var(--bb-text-secondary);
}

.bb-app .bb-division-count {
    font-variant-numeric: tabular-nums;
}

/* -- Greatest athletes / recent shows numerals ----------------------------- */

.bb-app .bb-athlete-rank,
.bb-app .bb-athlete-wins,
.bb-app .bb-contest-meta {
    font-variant-numeric: tabular-nums;
}

/* -- FAQ ------------------------------------------------------------------- */

/* The open question was a solid oxblood slab with white text - the loudest
   element on the page for a disclosure state. Editorial: a quiet oxblood-tint
   wash with oxblood ink (7:1 on the tint), the chevron inherits the accent. */
.bb-app .bb-faq-question[aria-expanded="true"] {
    background: var(--bb-primary-light);
    color: var(--bb-primary-hover);
}

/* Honest freshness line (rankings trust panel, top-lists hero):
   the date is real MAX(results.updated_at), refreshed by nightly sync. */
.bb-app .bb-data-freshness {
    margin: 10px 0 0;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted);
}
.bb-page-header--dark .bb-data-freshness { color: rgba(255, 255, 255, 0.68); }
.bb-page-hero .bb-data-freshness { color: rgba(255, 253, 248, 0.6); }

/* ==========================================================================
   DESIGN SYSTEM COMPONENT LIBRARY (2026-06-20)
   Canonical component classes that replace hand-rolled inline-styled one-offs.
   See DESIGN-SYSTEM.md. Scoped under .bb-app and placed last so they win
   the cascade exactly as the inline styles they replace did (value-preserving).
   ========================================================================== */

/* Segmented unit toggle (imperial/metric): the bordered segmented control used
   on the calculator/tool pages. Named .bb-seg-toggle to avoid colliding with the
   legacy pill .bb-unit-toggle (defined far above): the old inline-styled copies
   reused the .bb-unit-toggle class but overrode only display/border/radius/overflow
   inline, so they silently inherited the pill's gray frame + 3px padding + center
   alignment. This self-contained block reproduces that exact computed result, so
   migrating the copies onto it is value-preserving. Replaces ~8 inline copies.
   Render via partials/bb-unit-toggle.php (bb_unit_toggle()); the segment buttons
   keep .bb-btn .bb-btn-sm, and the vanilla controller applies .bb-btn-primary. */
.bb-app .bb-seg-toggle-row {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--bb-space-4); /* = 16px */
}
.bb-app .bb-seg-toggle {
    display: flex;
    align-items: center;
    background: var(--bb-gray-100);
    border: 2px solid var(--bb-border);
    border-radius: var(--bb-radius);
    padding: 3px;
    overflow: hidden;
}
.bb-app .bb-seg-toggle .bb-btn {
    border-radius: 0;
    border: none;
    min-width: 80px;
}

/* Arnold Classic editions hub - edition cards + shows-by-year table */
.bb-app .bb-edition-section { margin: 0 0 var(--bb-space-8); }
.bb-app .bb-edition-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
    gap: var(--bb-space-4);
    margin-top: var(--bb-space-4);
}
.bb-app .bb-edition-card {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
    padding: var(--bb-space-5);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-sm);
    text-decoration: none;
    transition: box-shadow .15s ease, border-color .15s ease, transform .15s ease;
}
.bb-app .bb-edition-card:hover,
.bb-app .bb-edition-card:focus-visible {
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-md);
    transform: translateY(-2px);
}
.bb-app .bb-edition-card__name {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--bb-text-primary);
}
.bb-app .bb-edition-card__region {
    font-size: .85rem;
    color: var(--bb-text-muted);
}
.bb-app .bb-edition-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-1) var(--bb-space-4);
    margin-top: var(--bb-space-2);
    font-size: .82rem;
    color: var(--bb-text-secondary);
}
.bb-app .bb-edition-card__stat strong { color: var(--bb-text-primary); }
.bb-app .bb-back-link {
    margin: var(--bb-space-4) 0;
    font-size: .9rem;
}
.bb-app .bb-edition-table td,
.bb-app .bb-edition-table th { vertical-align: middle; }
.bb-app .bb-edition-year-link { font-weight: 700; }

/* ==========================================================================
   Embeddable widgets configurator
   --------------------------------------------------------------------------
   All seventeen bb-widget-* classes had no rule in any stylesheet, so the whole
   configurator rendered as bare stacked labels and inputs: no panel, no card,
   no two-column split, no preview frame, and the embed snippet as raw
   full-width text. The markup was already correct; only the CSS was missing.

   Structure this matches:
     section.bb-widget-section
       .bb-widget-section-header      title + description
       .bb-widget-config-row          two columns: config | preview
         .bb-widget-config-panel      search, size inputs, embed code
         .bb-widget-preview           label, iframe frame, placeholder
   ========================================================================== */

.bb-app .bb-widget-section {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    padding: var(--bb-space-6);
    margin-bottom: var(--bb-space-6);
}

.bb-app .bb-widget-section-header {
    margin-bottom: var(--bb-space-5);
}

.bb-app .bb-widget-section-header > :last-child {
    margin-bottom: 0;
}

/* Config beside preview on desktop, stacked below it. */
.bb-app .bb-widget-config-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--bb-space-6);
    align-items: start;
}

@media (min-width: 900px) {
    .bb-app .bb-widget-config-row {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
}

.bb-app .bb-widget-config-panel {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-4);
    background: var(--bb-gray-50);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
    padding: var(--bb-space-5);
    min-width: 0;
}

/* A label, not a run of body text: it was rendering display:inline at 15px. */
.bb-app .bb-widget-label {
    display: block;
    margin-bottom: var(--bb-space-1-5);
    font-size: var(--bb-fs-label);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}

.bb-app .bb-widget-input {
    width: 100%;
    max-width: 100%;
}

/* Width and height are two-to-four digit numbers; a full-width field for them
   read as a mistake next to the search field. */
.bb-app .bb-widget-input-sm {
    width: 100%;
    max-width: 8rem;
    font-variant-numeric: tabular-nums;
}

.bb-app .bb-widget-size-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-4);
}

.bb-app .bb-widget-size-row > * {
    min-width: 0;
}

.bb-app .bb-widget-selected {
    padding: var(--bb-space-2-5) var(--bb-space-3);
    border: 1px solid var(--bb-primary-light);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    font-size: var(--bb-fs-sm);
}

/* Search results panel, matching the other autocompletes. The options
   themselves are role="option" and inherit the shared reset. */
.bb-app .bb-widget-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 260px;
    overflow-y: auto;
    background: var(--bb-surface);
    border: 1px solid var(--bb-gray-200);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-lg);
}

.bb-app .bb-widget-dropdown-item--active {
    background: var(--bb-gray-50);
    color: var(--bb-primary-hover);
}

/* Embed snippet. It was raw text running the full content width in the theme's
   body font, wrapping mid-attribute. */
.bb-app .bb-widget-code-wrap {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
    align-items: flex-start;
}

.bb-app .bb-widget-code {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    padding: var(--bb-space-4);
    border-radius: var(--bb-radius);
    background: var(--bb-navy);
    color: var(--bb-on-dark);
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-xs);
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-all;
}

.bb-app .bb-widget-preview {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-3);
    min-width: 0;
}

.bb-app .bb-widget-preview-label {
    font-size: var(--bb-fs-label);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}

/* Dashed so an empty preview reads as a slot waiting to be filled rather than
   as a broken card. */
.bb-app .bb-widget-preview-frame,
.bb-app .bb-widget-preview-placeholder {
    display: grid;
    place-items: center;
    min-height: 200px;
    padding: var(--bb-space-4);
    border: 1px dashed var(--bb-gray-200);
    border-radius: var(--bb-radius);
    background: var(--bb-gray-50);
}

.bb-app .bb-widget-preview-placeholder {
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-sm);
    text-align: center;
}

.bb-app .bb-widget-preview-frame iframe {
    max-width: 100%;
    border: 0;
}

/* ==========================================================================
   Page title, single scale
   --------------------------------------------------------------------------
   Placed last on purpose. Thirteen h1 classes across the templates were sized
   by competing rules at different specificities, so the same role rendered at
   32.8px, 60.5px or 72px depending on which ancestor matched. Rather than
   untangle every historical selector, this is the one authoritative rule:
   .bb-app prefixed for specificity, last in the file so it wins.

   Excluded deliberately: .bb-hub-welcome-title and .bb-hub-welcome-greeting.
   Those are the logged-in hub's compact personalised greeting band, not a hero
   title, and 56px would break that band. The hub gets its own pass.
   ========================================================================== */
.bb-app .bb-page-title,
.bb-app .bb-page-hero-title,
.bb-app .bb-profile-name,
.bb-app .bb-cat-hero__title,
.bb-app .bb-vs-hero__h1,
.bb-app .bb-event-hero__title,
.bb-app .bb-ssr-summary__name,
.bb-app .bb-heading-hero,
.bb-app .bb-odds-title,
.bb-app .bb-game-title,
.bb-app .bb-champion-anchor__h1 {
    font-size: var(--bb-fs-page-title);
    line-height: 1.08;
    letter-spacing: -0.02em;
    text-wrap: balance;
}

/* ==========================================================================
   Card heading tier
   --------------------------------------------------------------------------
   .bb-card__title and .bb-card__body had no rule in any stylesheet, so the
   theme's bare h2 styling applied and the card title rendered at 28px while the
   plugin's own section heading sits at 26px: a card heading outshouting the
   section that contains it. It looked like a deliberate size choice in the
   source, because there was no source to look at.

   One step below the section tier, so the hierarchy reads
   page title > section heading > card title > body.
   ========================================================================== */
.bb-app .bb-card__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-lg);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -0.01em;
    color: var(--bb-text-primary);
    margin: 0 0 var(--bb-space-3);
}

.bb-app .bb-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--bb-space-2);
    font-size: var(--bb-fs-15);
    line-height: 1.65;
    color: var(--bb-text-secondary);
}

.bb-app .bb-card__body > :last-child {
    margin-bottom: 0;
}

/* Filter chip clear control.
   A bare <button type="submit">&times;</button> with no other class, used five
   times on the athlete directory (gender, active, division, country, query). With
   no plugin rule the theme's button styling applied and it rendered as an 86x15px
   slab in the theme's pink rgb(255,24,78) with padding:0 40px, instead of a small
   dismiss affordance inside the chip. It inherits the chip's own colour now, so it
   reads as part of the chip rather than a foreign control. */
.bb-app .bb-state-chip-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    min-height: 0;
    margin-left: var(--bb-space-1);
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: inherit;
    font-size: var(--bb-fs-label);
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    opacity: 0.65;
    transition: opacity 0.12s ease, background-color 0.12s ease;
}

.bb-app .bb-state-chip-clear:hover,
.bb-app .bb-state-chip-clear:focus-visible {
    opacity: 1;
    background: rgba(0, 0, 0, 0.08);
}

/* The chip wraps a form per filter; keep it on the chip's baseline. */
.bb-app .bb-state-chip form {
    display: inline-flex;
    align-items: center;
    margin: 0;
}

/* ==========================================================================
   Sort Icon - Accessibility Fix
   --------------------------------------------------------------------------
   .bb-sort-icon had font-size: 10px, below the 11px floor.
   The accompanying ::after pseudo-element uses 8px for unicode arrow symbols,
   which are decorative iconography and excluded from legibility requirements.
   ========================================================================== */
.bb-sort-icon {
    font-size: var(--bb-fs-2xs);
}

/* ==========================================================================
   Rival Verdict Badge - Accessibility Fix
   --------------------------------------------------------------------------
   .bb-rival-verdict-badge had font-size: 10px, below the 11px floor.
   ========================================================================== */
.bb-rival-verdict-badge {
    font-size: var(--bb-fs-2xs);
}

/* ==========================================================================
   Rival Record Label - Accessibility Fix
   --------------------------------------------------------------------------
   .bb-rival-record-label had font-size: 10px, below the 11px floor.
   ========================================================================== */
.bb-rival-record-label {
    font-size: var(--bb-fs-2xs);
}

/* ==========================================================================
   IRON & BONE PRIMITIVES
   Design project 426d8189, adopted 2026-07-29. See DESIGN-IRON-AND-BONE.md.

   These are the six shapes every page in the prototype is built from. They
   are applied to the class names the templates ALREADY use, so a route picks
   the design up without template surgery. Last in the file so they win on
   order rather than on !important.

   Why this section exists at all: the token layer landed first and changed
   almost nothing anyone could see, because the old palette was already warm
   cream with an oxblood accent (the body-text shift measured dE 0.84, below
   the just-noticeable threshold). The design's actual signature is not its
   colour, it is condensed uppercase display type, mono tabular figures, and
   a 2px rule under every section heading. That is what lives here.
   ========================================================================== */

/* ---- 1. Display type -----------------------------------------------------
   The single most recognisable thing about this design. Archivo's width axis
   is doing the work: font-stretch 84-90% on caps, tight negative tracking,
   line-height under 1. A static font would render these at 100% and the
   headline would lose its whole character, which is why the variable cut is
   the one that ships. */
.bb-app .bb-page-hero-title,
.bb-app .bb-hero__title,
.bb-app .bb-profile-header__name,
.bb-app .bb-event-hero__title,
.bb-app .bb-cat-hero__title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-page-title);
    font-weight: 700;
    font-stretch: 84%;
    line-height: 0.98;
    letter-spacing: -0.012em;
    /* Token, so the mobile override reaches this family too. This is the twin of
       the .bb-page-title rule: same five declarations, five different h1
       classes. Fixing one and not the other left /best/, /womens/,
       /peak-window/ and /rankings/goat/ still uppercase at 0.98 leading while
       every .bb-page-title route was already fixed. */
    text-transform: var(--bb-page-title-transform);
    text-wrap: balance;
    margin: 0;
}

/* ---- 2. Section header ---------------------------------------------------
   Title left, meta right, 2px ink rule beneath. Used on every section of
   every page in the prototype; it is what gives the pages their spine.

   .bb-section-heading / .bb-goat-section-heading are the <h2> ITSELF, holding
   the title text plus a __meta span. Row flex with a flex-end baseline is what
   puts the meta on the right, aligned to the title's baseline.

   .bb-section-header is NOT that. It is a <div> WRAPPER around three stacked
   children (a .bb-section-label eyebrow, the <h2>, and a lede <p>). It was in
   this selector list, so it inherited the row flex: the eyebrow and the h2 sat
   side by side on line one, the eyebrow shoved down to the h2's baseline by
   align-items:flex-end, and the lede wrapped to line two beside nothing. The
   kicker rendered BELOW its own heading on every section of the hub. Same
   declaration block, two unrelated structures - it needs its own rule. */
.bb-app .bb-goat-section-heading,
.bb-app .bb-section-heading {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 16px 20px;
    margin: 0 0 26px;
    padding-bottom: 20px;
    border-bottom: 2px solid var(--bb-ink);
    font-family: var(--bb-font-heading);
    font-size: clamp(24px, 2.8vw, 32px);
    font-weight: 700;
    font-stretch: 88%;
    line-height: 1.08;
    letter-spacing: -0.02em;
    color: var(--bb-ink);
    text-transform: none;
}

/* The wrapper keeps the spine (2px ink rule, same rhythm) and drops the row
   layout. Left-aligned: the eyebrow is only legible as an eyebrow when it
   shares the heading's left edge, and the centred inherit from :13021 fought
   the rule beneath it. */
.bb-app .bb-section-header {
    display: block;
    margin: 0 0 26px;
    padding-bottom: 20px;
    border-bottom: 2px solid var(--bb-ink);
    text-align: left;
    color: var(--bb-ink);
}

.bb-app .bb-section-header > * + * {
    margin-top: 8px;
}

.bb-app .bb-section-header .bb-section-label {
    display: block;
}

/* The lede is body copy, not heading copy - it inherited the heading family and
   the -0.02em tracking from the old shared block. */
.bb-app .bb-section-header > p {
    max-width: 68ch;
    font-family: var(--bb-font-body);
    font-size: 15px;
    font-weight: 400;
    font-stretch: normal;
    line-height: 1.6;
    letter-spacing: normal;
    color: var(--bb-text-secondary);
    text-wrap: pretty;
}

/* ---- 3. Figures ----------------------------------------------------------
   Every number in IBM Plex Mono with tabular figures. This is why a column
   of placements reads as a record instead of as prose: the digits share an
   advance width, so 1st and 11th align on the same axis. */
/* Scoped to the cells that actually hold figures. The first cut of this rule
   said `.bb-rankings-table td` and put every athlete name and division label
   into mono as well - the design uses Archivo semibold for names and reserves
   mono for numbers, and a table of names in monospace reads like a terminal
   dump. The templates already tag numeric cells .bb-td-num, so the narrower
   selector was available the whole time. Caught in the browser. */
.bb-app .bb-goat-stat-value,
.bb-app .bb-goat-score-num,
.bb-app .bb-goat-podium-rank,
.bb-app .bb-stat-value,
.bb-app .bb-rankings-table .bb-td-num,
.bb-app .bb-rankings-table .bb-td-rank,
.bb-app .bb-content-table .bb-td-num,
.bb-app .bb-table--figures .bb-td-num {
    font-family: var(--bb-font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

/* Names stay in the text face, semibold, tight. */
.bb-app .bb-rankings-table .bb-td-athlete,
.bb-app .bb-content-table .bb-td-athlete {
    font-family: var(--bb-font-heading);
    font-size: 15.5px;
    font-weight: 600;
    letter-spacing: -0.008em;
}

.bb-app .bb-goat-score-num {
    font-size: 38px;
    font-weight: 500;
    line-height: 1;
    color: var(--bb-oxblood);
}

/* ---- 4. Eyebrow ----------------------------------------------------------
   11px, not the prototype's 10px: owner deviation A. The wide tracking is
   what makes it legible at this size, so it is not optional here. */
.bb-app .bb-goat-stat-label,
.bb-app .bb-goat-score-label,
.bb-app .bb-eyebrow,
.bb-app .bb-stat-label {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    line-height: 1.3;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-warm-grey-2);
}

/* ---- 5. Table shell ------------------------------------------------------
   Tinted head strip, tracked mono column labels, hairline rows. */
.bb-app .bb-rankings-table thead th,
.bb-app .bb-content-table thead th {
    background: var(--bb-tint);
    border-bottom: 1px solid var(--bb-border);
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-warm-grey-2);
}

.bb-app .bb-rankings-table tbody tr,
.bb-app .bb-content-table tbody tr {
    border-bottom: 1px solid rgba(34, 28, 24, 0.1);
}

/* ---- 6. Disclosure card --------------------------------------------------
   The amber top rule. In the prototype every page ends with one of these -
   "How these titles are counted", "This is a model, not a tip sheet". It is
   the shape the product's honesty work has been missing a home for. */
.bb-app .bb-trust-panel,
.bb-app .bb-methodology,
.bb-app .bb-ssr-summary,
.bb-app .bb-disclosure {
    background: var(--bb-paper);
    border: 1px solid var(--bb-border);
    border-top: 3px solid var(--bb-amber-dark);
    border-radius: 0 0 6px 6px;
}

/* ---- Hero shell ----------------------------------------------------------
   Full-bleed flat ink, square. The prototype's hero has no radius and no
   gradient; the ruled texture comes from --bb-dark-wash. */
.bb-app .bb-page-hero {
    border-radius: 0;
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
}

.bb-app .bb-hero-badge {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    background: rgba(217, 139, 74, 0.14);
    border: 1px solid rgba(217, 139, 74, 0.42);
    border-radius: 999px;
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-amber);
}

/* ---- Podium ---------------------------------------------------------------
   The prototype does NOT use medal colours. First place is an inverted ink
   card with an amber rank chip and an amber score; second and third are plain
   paper with a hairline rule and an ink chip. Rank is carried by the card's
   weight and its number, never by a gold/silver/bronze hue.

   That matters beyond taste: var(--bb-amber) / #c0c0c0 / #cd7f32 are three saturated
   colours that appear nowhere else in the system, and gold on cream is the
   worst contrast pair on the page. The token comment at --bb-accent has said
   "gold retired" since 2026-06-20; it was retired from the accent and left
   running the podium. */
.bb-app .bb-goat-podium-card--gold,
.bb-app .bb-goat-podium-card--silver,
.bb-app .bb-goat-podium-card--bronze {
    background: var(--bb-paper);
    background-image: none;
    border: 1px solid var(--bb-border);
    border-radius: 6px;
}

.bb-app .bb-goat-podium-card--gold {
    background: var(--bb-ink);
    border-color: var(--bb-ink);
    /* The card sets its own text colour so EVERY descendant inherits a legible
       one. It used to darken the background and then light up a hand-listed set of
       children (.bb-goat-podium-name, .bb-goat-stat-value, .bb-goat-stat-label,
       .bb-goat-score-label), which works only for the page those class names came
       from. The event podium on /olympia/<year>/ reuses this same card with
       different children, so .bb-country-cell inherited ink onto ink and the
       podium athletes' countries were invisible - measured 1.0:1, not low
       contrast, literally the same colour. An allowlist of descendants cannot
       survive being reused; inheritance can. */
    color: var(--bb-bone);
}

.bb-app .bb-goat-podium-card--gold .bb-goat-podium-name,
.bb-app .bb-goat-podium-card--gold .bb-goat-stat-value {
    color: var(--bb-bone);
}

.bb-app .bb-goat-podium-card--gold .bb-goat-stat-label,
.bb-app .bb-goat-podium-card--gold .bb-goat-score-label {
    color: rgba(250, 246, 239, 0.62);
}

.bb-app .bb-goat-podium-card--gold .bb-goat-score-num {
    color: var(--bb-amber);
}

/* Rank chip: filled, not tinted text. */
.bb-app .bb-goat-podium-rank,
.bb-app .bb-goat-podium-card--gold .bb-goat-podium-rank,
.bb-app .bb-goat-podium-card--silver .bb-goat-podium-rank,
.bb-app .bb-goat-podium-card--bronze .bb-goat-podium-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    padding: 7px 10px;
    border-radius: 3px;
    background: var(--bb-ink);
    color: var(--bb-bone);
    font-family: var(--bb-font-mono);
    font-size: 13px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.06em;
}

.bb-app .bb-goat-podium-card--gold .bb-goat-podium-rank {
    background: var(--bb-amber);
    color: var(--bb-ink);
}

/* ---- Hero anchor links ----------------------------------------------------
   Underlined in amber at 60% rather than set as buttons: the prototype keeps
   the hero to one action weight and lets these read as jumps, not CTAs. */
.bb-app .bb-hero-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 24px;
    margin-top: 26px;
}

.bb-app .bb-hero-link {
    padding-bottom: 3px;
    border-bottom: 1px solid rgba(217, 139, 74, 0.6);
    font-family: var(--bb-font-heading);
    font-size: 15px;
    font-weight: 500;
    color: var(--bb-bone);
    text-decoration: none;
}

.bb-app .bb-hero-link:hover {
    border-bottom-color: var(--bb-amber);
    color: var(--bb-amber);
    text-decoration: none;
}

/* ---- Section heading meta -------------------------------------------------
   The right-hand half of the section header: pushed away from the title so
   the 2px rule runs the full width with the label sitting on its end. */
.bb-app .bb-section-heading__meta {
    margin-left: auto;
    font-family: var(--bb-font-mono);
    font-size: 12px;
    font-weight: 400;
    letter-spacing: 0.08em;
    color: var(--bb-warm-grey-2);
    text-transform: none;
}

/* ---- Methodology weights --------------------------------------------------
   The percentage leads as a mono badge instead of being buried mid-sentence
   in bold, so the six weights can be compared down the left edge. */
.bb-app .bb-methodology-lede {
    margin: 0 0 20px;
    max-width: 74ch;
    font-size: 15px;
    line-height: 1.7;
    color: var(--bb-text-secondary);
}

.bb-app .bb-weight-list {
    margin: 0 0 22px;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.bb-app .bb-weight-item {
    display: flex;
    gap: 14px;
    align-items: baseline;
}

.bb-app .bb-weight-badge {
    flex: 0 0 auto;
    min-width: 44px;
    font-family: var(--bb-font-mono);
    font-size: 13px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    color: var(--bb-oxblood);
}

.bb-app .bb-weight-text {
    font-size: 14px;
    line-height: 1.6;
    color: var(--bb-text-secondary);
}

.bb-app .bb-method-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: 10px;
}

.bb-app .bb-method-card {
    padding: 18px 20px;
    background: var(--bb-bone);
    border: 1px solid var(--bb-border);
    border-radius: 4px;
}

.bb-app .bb-method-card__label {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-amber-dark);
}

.bb-app .bb-method-card__text {
    margin: 10px 0 0;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--bb-text-secondary);
    text-wrap: pretty;
}

/* ---- FAQ grid -------------------------------------------------------------
   1px gap over a rule-coloured background, so the dividers ARE the gaps and
   the four cards read as one block rather than four floating boxes. This is
   the prototype's trick for a set of things that belong together. */
.bb-app .bb-goat-faq {
    padding: clamp(36px, 4.5vw, 56px) 0 0;
}

/*
 * Fixed column counts, not auto-fit.
 *
 * The prototype uses auto-fit with a 288px floor and gets away with it because
 * its canvas is 1240px, so four cards land in one row. This container is
 * narrower, auto-fit resolved to THREE columns, and the fourth card orphaned
 * onto a second row - leaving two empty tracks showing the grey gap colour as
 * a dead block, because in this technique the container background IS the
 * grid lines and it paints wherever a card is not.
 *
 * 1 / 2 / 4 all divide four exactly, so there is no arrangement that orphans.
 * A count that divides the card count is the fix; a smaller auto-fit floor
 * would only move the width at which it breaks.
 */
.bb-app .bb-faq-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1px;
    background: var(--bb-border);
    border: 1px solid var(--bb-border);
    border-radius: 6px;
    overflow: hidden;
}

@media (min-width: 620px) {
    .bb-app .bb-faq-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1080px) {
    .bb-app .bb-faq-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.bb-app .bb-faq-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 22px 24px;
    background: var(--bb-paper);
}

.bb-app .bb-faq-card__q {
    margin: 0;
    font-family: var(--bb-font-heading);
    font-size: 17px;
    font-weight: 700;
    line-height: 1.28;
    letter-spacing: -0.012em;
    color: var(--bb-ink);
    text-wrap: pretty;
}

.bb-app .bb-faq-card__a {
    margin: 0;
    font-size: 14px;
    line-height: 1.65;
    color: var(--bb-text-secondary);
    text-wrap: pretty;
}

.bb-app .bb-faq-card__cta {
    margin-top: auto;
    font-family: var(--bb-font-heading);
    font-size: 12.5px;
    font-weight: 500;
    color: var(--bb-oxblood);
}

/* ==========================================================================
   PRIMITIVES - FULL COVERAGE

   The first cut of the primitives above named only the classes the GOAT page
   happened to use. A census of all 80 templates found the real spread, and it
   is much wider: bb-section-title appears in 31 templates against
   bb-section-heading's 21, bb-table in 38 against bb-rankings-table's 7, and
   bb-td-num carries 33 of the numeric cells. Styling the narrow set meant one
   page looked designed and fifteen did not.

   Every selector below is a name already in the markup. No template changes.
   ========================================================================== */

/* Section header, everywhere it is spelled. */
.bb-app .bb-section-title,
.bb-app .bb-heading-section,
.bb-app .bb-divisions-section-title,
.bb-app .bb-cat-section__title {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 16px 20px;
    margin: 0 0 26px;
    padding-bottom: 20px;
    border-bottom: 2px solid var(--bb-ink);
    font-family: var(--bb-font-heading);
    font-size: clamp(24px, 2.8vw, 32px);
    font-weight: 700;
    font-stretch: 88%;
    line-height: 1.08;
    letter-spacing: -0.02em;
    color: var(--bb-ink);
}

/* The on-this-day archive heading needs air above it, and this is the first
   point in the file where saying so works: the block above matches the same
   element at the same specificity, so the declaration has to come after it.
   Written next to the rule it overrides rather than beside the other archive
   styles, because the reason it lives here is that rule. */
.bb-app .bb-otd-archive-title {
    margin-top: 40px;
}

/* One spine per section, and the WRAPPER owns it.
   The rule above gives every spelling of a section title its own 2px ink rule,
   which is right when the title element IS the section header. On the hub the
   <h2> sits inside a .bb-section-header wrapper that already draws the spine, so
   both fired and the section rendered two horizontal rules: one under the
   heading, one under the lede. The heading keeps the type and loses the rule and
   the row layout, which belong to the standalone case. */
.bb-app .bb-section-header .bb-section-title,
.bb-app .bb-section-header .bb-heading-section,
.bb-app .bb-section-header .bb-divisions-section-title,
.bb-app .bb-section-header .bb-cat-section__title {
    display: block;
    margin: 0;
    padding-bottom: 0;
    border-bottom: 0;
}

/* Card titles sit INSIDE a card, so they take the type but never the rule -
   a 2px ink rule inside a bordered card reads as a second frame. This is the
   hierarchy inversion the audit flagged: bb-card-title was 28px inside a 26px
   section heading. */
.bb-app .bb-card-title,
.bb-app .bb-stats-box-title,
.bb-app .bb-content-card__title,
.bb-app .bb-analytics-chart-title {
    font-family: var(--bb-font-heading);
    /*
     * Floor 22, not 18. 1.9vw only exceeds 18px above a 947px viewport, so the
     * floor WAS the phone size, and 18 is on no tier: measured 18px card titles
     * on the hub, /tools/, /fantasy/, /game/ and /odds/ at 375px while the same
     * elements read a correct 22 at 1280. Same defect as the H1 clamp floors,
     * one level down.
     */
    font-size: clamp(var(--bb-fs-22), 1.9vw, var(--bb-fs-22));
    font-weight: 700;
    line-height: 1.16;
    letter-spacing: -0.016em;
    color: var(--bb-ink);
    border-bottom: 0;
}

/* Every table, not just the rankings one. */
.bb-app .bb-table thead th {
    background: var(--bb-tint);
    border-bottom: 1px solid var(--bb-border);
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-warm-grey-2);
}

.bb-app .bb-table tbody tr {
    border-bottom: 1px solid rgba(34, 28, 24, 0.1);
}

/* Every numeric cell, wherever it lives. */
.bb-app .bb-td-num,
.bb-app .bb-td-rank,
.bb-app .bb-td-score,
.bb-app .bb-td-breakdown {
    font-family: var(--bb-font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

.bb-app .bb-td-athlete {
    font-family: var(--bb-font-heading);
    font-weight: 600;
    letter-spacing: -0.008em;
}

/* Dark page headers share the hero treatment: flat ink, ruled, square. */
.bb-app .bb-page-header--dark,
.bb-app .bb-olympia-hero,
.bb-app .bb-arnold-hero {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border-radius: 0;
}

/* ---- Ledger strip ---------------------------------------------------------
   The row of figures under a hero, divided by hairlines rather than spaced
   apart. It is the prototype's most repeated hero component - Olympia,
   Athlete Directory and Road to Olympia all end their hero on one - and the
   markup for it already existed here as bb-olympia-hero-stat. */
.bb-app .bb-olympia-hero-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    margin-top: clamp(26px, 3.4vw, 40px);
    border-top: 1px solid rgba(250, 246, 239, 0.14);
}

.bb-app .bb-olympia-hero-stat {
    padding: 24px 22px;
    border-left: 1px solid rgba(250, 246, 239, 0.14);
}

/*
 * Phone override, and it has to live HERE rather than in the @media block at L14198.
 *
 * That block already asks for 8px 12px, matches the element, and reports
 * applies:true - and has never once taken effect, because a media query adds no
 * specificity and 0,1,0 there loses to 0,2,0 above. Moving the same declaration
 * below the rule it needs to beat settles it on source order, with no escalation and
 * no !important.
 *
 * What it was costing, measured on the hub at 390x844: 48px of vertical padding per
 * stacked stat instead of 16px, so the stat band alone was 342px of an 839px hero on
 * an 844px viewport. The hero was the entire first screen and everything below it
 * began off-screen.
 *
 * The grid above collapses to one column on a phone, so the border-left that divides
 * the cells side by side becomes a stray vertical line under each figure. It becomes a
 * top border instead, which is what a divided stack wants, and the first cell drops it.
 */
@media (max-width: 540px) {
    .bb-app .bb-olympia-hero-stat {
        padding: 10px 14px;
        border-left: 0;
        border-top: 1px solid rgba(250, 246, 239, 0.14);
    }

    .bb-app .bb-olympia-hero-stats > .bb-app .bb-olympia-hero-stat:first-child,
    .bb-app .bb-olympia-hero-stat:first-child {
        border-top: 0;
    }
}

.bb-app .bb-olympia-hero-stat-num {
    display: block;
    font-family: var(--bb-font-mono);
    font-size: clamp(26px, 2.4vw, 36px);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--bb-bone);
}

.bb-app .bb-olympia-hero-stat-label {
    display: block;
    margin-top: 9px;
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    line-height: 1.4;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(250, 246, 239, 0.62);
}

/* The hairline dividers ARE the border-left above, so the spacer elements the
   old layout needed are now redundant and would double the rule. */
.bb-app .bb-olympia-hero-stat-divider {
    display: none;
}

.bb-app .bb-olympia-hero-eyebrow {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--bb-amber);
}

/* ---- Specificity corrections ---------------------------------------------
   Being last in the file only wins ties. Three rules above lost outright:

   - .bb-app .bb-page-header.bb-page-header--dark  is (0,3,0) and beat the
     (0,2,0) border-radius:0, so every dark hero kept its 10px corners.
   - .bb-app .bb-page-header.bb-page-header--dark .bb-page-title is (0,4,0),
     so the display-type rule never reached the one title that needed it most.
   - .bb-olympia-hero-stats set border-radius:var(--bb-radius-full). The grid
     rule above won on specificity but only for the properties it declared;
     radius was never mentioned, so the pill survived under a grid layout.

   The last one is the more useful lesson: overriding a component means
   naming every property the old rule set, not just the ones being changed. */
.bb-app .bb-page-header.bb-page-header--dark,
.bb-app .bb-page-header.bb-page-header--dark.bb-olympia-hero,
.bb-app .bb-page-header.bb-page-header--dark.bb-arnold-hero {
    border-radius: 0;
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
}

.bb-app .bb-page-header .bb-page-title,
.bb-app .bb-page-header.bb-page-header--dark .bb-page-title,
.bb-app .bb-page-title {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-page-title);
    font-weight: 700;
    font-stretch: 84%;
    line-height: 0.98;
    letter-spacing: -0.012em;
    text-transform: var(--bb-page-title-transform);
    text-wrap: balance;
}

/*
 * The mobile title. Five settings above are correct for a one-line desktop hero
 * and every one of them is wrong once the title wraps.
 *
 * line-height 0.98 is the important one: it is BELOW 1, so on 41 of 42 routes
 * the computed leading was smaller than the type and wrapped lines physically
 * closed up into a block. Invisible at one line, which is why it survived since
 * the ladder shipped. 1.06 opens it without giving up the display feel.
 *
 * Tracking goes to zero: -0.012em tightens a large desktop headline and works
 * against legibility at 26 to 34px on a phone.
 *
 * Uppercase narrows to the two hero ancestors. It is about 12% wider than
 * sentence case and removes the word shapes a reader scans by, and dropping it
 * on the other tiers is what takes the long directory and index titles from
 * three lines to two. Heroes keep it because they are one short line and the
 * shout is the point.
 *
 * 640px matches the breakpoint the page-header rules in this file already use.
 */
@media (max-width: 640px) {
    .bb-app {
        --bb-page-title-transform: none;
    }
    .bb-app .bb-hero,
    .bb-app .bb-olympia-hero {
        --bb-page-title-transform: uppercase;
    }
}

.bb-app .bb-olympia-hero-stats {
    background: none;
    border: 0;
    border-top: 1px solid rgba(250, 246, 239, 0.14);
    border-radius: 0;
}

/* ---- Remaining title classes ---------------------------------------------
   A second census, this time of the templates that still picked up NOTHING,
   found the page titles and section titles those routes actually use. Every
   name below already exists in markup; none is invented. Without these the
   hub, athlete profile, odds and game pages kept theme-default headings while
   every other route had the design.

   Card titles (bb-card-title, bb-stats-box-title, bb-content-card__title) are
   deliberately NOT here: they sit inside a bordered card, and a 2px ink rule
   inside a card reads as a second frame. They take the type, not the rule. */
.bb-app .bb-heading-hero,
.bb-app .bb-profile-name,
.bb-app .bb-game-title,
.bb-app .bb-hub-welcome-title,
.bb-app .bb-odds-title,
.bb-app .bb-ssr-summary__name {
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-page-title);
    font-weight: 700;
    font-stretch: 86%;
    line-height: 0.99;
    letter-spacing: -0.014em;
    text-wrap: balance;
}

/* ---- Uppercase belongs to the hero H1 only (brief §2) --------------------
   It had spread to every page title in the plugin. Three rule groups were
   applying it: the hero group above, the naked `.bb-app .bb-page-title`, and
   this display group. The brief is specific - "uppercase only on the hero H1"
   - so it is granted here by enumeration rather than inherited by anything
   that happens to be styled like a title.

   .bb-ssr-summary__name is excluded on purpose: it is the athlete name inside
   the quick-answer card, not a hero heading, and setting a sentence's subject
   in caps mid-paragraph reads as shouting rather than as a title. */
.bb-app .bb-page-hero-title,
.bb-app .bb-hero__title,
.bb-app .bb-heading-hero,
.bb-app .bb-profile-header__name,
.bb-app .bb-profile-name,
.bb-app .bb-event-hero__title,
.bb-app .bb-cat-hero__title,
.bb-app .bb-game-title,
.bb-app .bb-hub-welcome-title,
.bb-app .bb-odds-title,
.bb-app .bb-page-header--dark .bb-page-title {
    /* The token, not the literal, and this rule is why the token exists. This
       enumeration is the single place uppercase is granted, so pointing it at
       --bb-page-title-transform makes one declaration control every title class
       at once. Setting the literal here and overriding it elsewhere would mean
       out-specifying an eleven-selector group on every route, which is the
       whack-a-mole this rule was written to end. */
    text-transform: var(--bb-page-title-transform);
}

/* A page title outside a dark hero is a compact page header - Tools, Contests,
   Rankings - and the brief does not uppercase those. This has to come after
   the group above and match its specificity to win, which is why it repeats
   the selector rather than relying on order alone. */
.bb-app .bb-page-title:not(.bb-page-header--dark .bb-page-title),
.bb-app .bb-ssr-summary__name {
    text-transform: none;
}

/*
 * Two titles that wrap at EVERY width, so their leading cannot be left to the
 * mobile block below.
 *
 * Measured at 1440px: the hub headline is 72px type on 68.4px leading across
 * five lines, and the compare h1 is 64px on 62.7px across two. Tight leading
 * under 1.0 is a legitimate display choice for a headline that occupies one
 * line, which is why the rest of the desktop ladder keeps it. These two never
 * occupy one line, because one is a 47-character sentence and the other is
 * two athlete names joined by "vs", so for them it is the same defect the
 * phones had and not a style.
 *
 * 1.05 rather than the 1.06 used on mobile: at 72px that is the smallest step
 * that clears the type, and a display headline should stay tight.
 */
.bb-app .bb-hero .bb-heading-hero:not(.bb-hero-tagline),
.bb-app .bb-vs-hero__h1,
/* The compare h1 carries bb-page-title AND bb-vs-hero__h1, so the 0.98 rule
   reaches it through `.bb-app .bb-page-header.bb-page-header--dark
   .bb-page-title` at (0,4,1) and a (0,2,1) selector on the vs class loses.
   Repeated at the same shape rather than escalated. */
.bb-app .bb-page-header.bb-page-header--dark .bb-vs-hero__h1 {
    line-height: 1.05;
}

/* ---- The mobile page title ----------------------------------------------
 * Placed after every rule above that declares leading on a title class, and
 * that position is the whole point. Nine separate rules set a page-title
 * line-height in this file at values from 0.95 to 1.2, several of them at
 * (0,3,1), so a mobile override earlier in the file loses to whichever one
 * happens to match the route. Measured: an override placed beside the base
 * rule fixed 6 routes of 41 and left 35 crushed.
 *
 * WHY IT IS NEEDED. Every one of those leading values below 1.0 is correct for
 * a single-line desktop headline and wrong the moment the title wraps. At 375px
 * the computed leading came out SMALLER than the type on 41 of 42 routes, so
 * wrapped lines closed up into a solid block. That is the "big fat wall of
 * text" the owner reported, and it is arithmetic rather than taste.
 *
 * Tracking goes to zero for the same reason: -0.012em tightens a 64px desktop
 * headline and costs legibility at 26 to 34px on a handset.
 *
 * The .bb-hero descendant selector is repeated at (0,3,1) because
 * `.bb-app .bb-hero .bb-heading-hero` sets 0.95 and a (0,2,1) selector cannot
 * reach it.
 *
 * 768px here, against 640px for the uppercase change above, and the split is
 * deliberate. Crushed leading is a DEFECT and it appears wherever a title
 * wraps, which measurably includes 768px (the hub at 41px/39.4 and the athlete
 * hero at 35px/34.2 were both still crushed at that width). Uppercase is a
 * BRAND choice, so it narrows only on phones. Fix the bug wide, change the look
 * narrow.
 */
@media (max-width: 768px) {
    .bb-app .bb-page-title,
    .bb-app .bb-page-hero-title,
    .bb-app .bb-hero__title,
    .bb-app .bb-heading-hero,
    .bb-app .bb-profile-header__name,
    .bb-app .bb-profile-name,
    .bb-app .bb-event-hero__title,
    .bb-app .bb-cat-hero__title,
    .bb-app .bb-game-title,
    .bb-app .bb-hub-welcome-title,
    .bb-app .bb-odds-title,
    .bb-app .bb-ssr-summary__name,
    .bb-app .bb-hero .bb-heading-hero,
    .bb-app .bb-olympia-hero .bb-page-title,
    .bb-app .bb-page-header .bb-page-title,
    /*
     * The two selectors that actually decide it. Both are (0,4,1) - two classes
     * on one element, or a :not() - and a (0,3,1) override loses to them
     * silently on 18 routes. They are repeated verbatim rather than answered
     * with !important, because the next person to add a title rule should be
     * able to out-specify this the ordinary way.
     */
    .bb-app .bb-page-header.bb-page-header--dark .bb-page-title,
    .bb-app .bb-hero .bb-heading-hero:not(.bb-hero-tagline) {
        line-height: 1.06;
        letter-spacing: 0;
    }
}

.bb-app .bb-see-also-title,
.bb-app .bb-rivalries__tier-title,
.bb-app .bb-rto-division-name,
.bb-app .bb-odds-movers__title,
.bb-app .bb-olympia-year-heading,
.bb-app .bb-otd-event-title,
.bb-app .bb-analytics-division-name,
.bb-app .bb-divisions-section-title {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 16px 20px;
    margin: 0 0 26px;
    padding-bottom: 20px;
    border-bottom: 2px solid var(--bb-ink);
    font-family: var(--bb-font-heading);
    font-size: clamp(22px, 2.6vw, 30px);
    font-weight: 700;
    font-stretch: 88%;
    line-height: 1.08;
    letter-spacing: -0.02em;
    color: var(--bb-ink);
}

/* The athlete profile header is the design's record page hero: flat ink,
   square, full-bleed, with the ruled wash behind the name and the at-a-glance
   panel. It was transparent with an 8px radius, so the profile - the most
   linked page type in the plugin - was the one page with no hero at all. */
.bb-app .bb-profile-header,
.bb-app .bb-profile-header--champion,
.bb-app .bb-event-hero,
.bb-app .bb-cat-hero {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border-radius: 0;
}

/* bb-stats-category-title nests inside bb-stats-box-title on the athlete
   profile, so giving it the SECTION size put a 32px heading inside a 22px one
   - the exact hierarchy inversion this pass set out to remove, reintroduced by
   assuming a name with "category" in it was a top-level heading. It is a card
   subhead; sized below its container. Caught by test-type-scale-floor. */
.bb-app .bb-stats-category-title {
    font-family: var(--bb-font-heading);
    font-size: clamp(15px, 1.5vw, 17px);
    font-weight: 700;
    font-stretch: 100%;
    line-height: 1.2;
    letter-spacing: -0.01em;
    color: var(--bb-ink);
    border-bottom: 0;
    padding-bottom: 0;
    margin: 0 0 12px;
    display: block;
}

/* ==========================================================================
   SECTIONS FROM THE PARALLEL BUILD

   The build lanes were forbidden from touching this file, because eight agents
   appending to one 17.5k-line stylesheet would collide - and this session had
   already produced four separate "one value, two owners" bugs. So they added
   markup and returned the rules; these are applied centrally here.

   The ratchet named the nine classes that were genuinely unstyled, which is
   how these were scoped. Two lanes ALSO proposed !important overrides for the
   table head that contradicted each other, and those are not applied: GOAT
   already renders the tinted head with no !important, so the override was a
   guess about specificity rather than a measured need.
   ========================================================================== */

/* ---- Champion band (divisions/detail.php) --------------------------------
   The prototype's Division page puts the reigning champion in an inverted ink
   panel with the stat grid on paper beside it, so the champion reads as the
   answer to the page and the numbers as its supporting detail. One band, two
   surfaces, no card-in-card. */
.bb-app .bb-champ-band {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
    margin-top: clamp(24px, 3vw, 34px);
    border: 1px solid var(--bb-border);
    border-radius: 6px;
    overflow: hidden;
}

.bb-app .bb-champ-band__panel {
    flex: 1 1 340px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 28px 30px;
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
}

.bb-app .bb-champ-band__eyebrow {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(250, 246, 239, 0.58);
}

/* The year is a figure, so it is mono and tabular like every other figure. */
.bb-app .bb-champ-band__year {
    font-family: var(--bb-font-mono);
    font-size: clamp(22px, 2.2vw, 28px);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--bb-amber);
}

.bb-app .bb-champ-band__name {
    font-family: var(--bb-font-heading);
    font-size: clamp(24px, 2.6vw, 32px);
    font-weight: 700;
    font-stretch: 90%;
    line-height: 1.08;
    letter-spacing: -0.018em;
    color: var(--bb-bone);
    text-wrap: balance;
}

/* The name is a link on this surface, so it needs its own colour: the global
   a{color:oxblood} is unreadable on ink, and the theme's .rbct a is more
   specific than a flat class. */
.bb-app a.bb-champ-band__name,
.bb-app a.bb-champ-band__name:hover,
.bb-app a.bb-champ-band__name:focus-visible {
    color: var(--bb-bone);
    text-decoration: none;
}

.bb-app a.bb-champ-band__name:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-color: var(--bb-amber);
}

.bb-app .bb-champ-band__meta {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    line-height: 1.4;
    color: rgba(250, 246, 239, 0.66);
}

.bb-app .bb-champ-band__stats {
    flex: 1 1 320px;
    min-width: 0;
    margin: 0;
    padding: 1px;
    gap: 1px;
    background: var(--bb-border);
}

.bb-app .bb-champ-band__stats .bb-stat-card {
    margin: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: var(--bb-paper);
    padding: 20px 22px;
}

/* ---- Board directory cards (rankings/index.php) --------------------------
   The kind of board is carried by a 3px top rule and its eyebrow, matching the
   prototype's Rankings page: moss for boards that move with every result that
   lands, oxblood for the composites, amber for the head-to-head tools. Colour
   is doubled by the kind label, so it never carries the distinction alone. */
.bb-app .bb-board-card {
    border-top: 3px solid var(--bb-border);
}

.bb-app .bb-board-card--live { border-top-color: var(--bb-moss); }
.bb-app .bb-board-card--alltime { border-top-color: var(--bb-oxblood); }
.bb-app .bb-board-card--tool { border-top-color: var(--bb-amber-dark); }

.bb-app .bb-board-card--live .bb-eyebrow { color: var(--bb-moss); }
.bb-app .bb-board-card--alltime .bb-eyebrow { color: var(--bb-oxblood); }
.bb-app .bb-board-card--tool .bb-eyebrow { color: var(--bb-amber-dark); }

/* ---- Champion-by-year grid ------------------------------------------------
   The prototype lays a division's lineage out as a grid, not a horizontal
   scroller: a reader comparing 1965 to 2024 should be able to see both without
   dragging, and a scroll strip hides exactly the depth this page exists to
   show. The modifier shape is the template author's, and it is the right one -
   without this rule the markup still renders as the original strip, so the
   grid is an enhancement rather than a dependency.

   auto-fill, not auto-fit: with auto-fit a division that has only two recorded
   champions would stretch those two chips across the full width and imply the
   lineage is complete. auto-fill keeps the track width honest. */
.bb-app .bb-era-strip--grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(168px, 100%), 1fr));
    gap: 1px;
    padding: 1px;
    margin: 0 0 var(--bb-space-5);
    overflow-x: visible;
    background: var(--bb-border);
    border: 1px solid var(--bb-border);
    border-radius: 6px;
}

.bb-app .bb-era-strip--grid .bb-era-chip {
    flex: initial;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    padding: 14px 16px;
    background: var(--bb-paper);
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

.bb-app .bb-era-strip--grid .bb-era-chip__year {
    font-family: var(--bb-font-mono);
    font-size: 11.5px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.06em;
    color: var(--bb-warm-grey-2);
}

.bb-app .bb-era-strip--grid .bb-era-chip__name {
    font-family: var(--bb-font-heading);
    font-size: 14.5px;
    font-weight: 600;
    line-height: 1.28;
    letter-spacing: -0.008em;
    color: var(--bb-ink);
    overflow-wrap: anywhere;
}

.bb-app .bb-era-strip--grid .bb-era-chip__country {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    color: var(--bb-warm-grey-2);
}

/*
 * The 168px minimum column resolves to ONE column on a phone, not two.
 * auto-fill fits floor(322 / 168) = 1, and the leftover 154px is 14px short of
 * a second track, so each chip stretched to 320px to hold a year, a name and a
 * country that together need about 205px. Measured at 375px: 96px per chip, 61
 * of them, 5,874px of a 17,886px /divisions/mens-open/.
 *
 * 148px is the widest minimum that still fits two tracks at 375px, and the
 * padding comes in with it. A long name wraps to a second line at this width,
 * which overflow-wrap already handles and which costs 19px on the few rows it
 * happens to, against halving the row count on all of them.
 */
@media (max-width: 600px) {
    .bb-app .bb-era-strip--grid {
        grid-template-columns: repeat(auto-fill, minmax(min(148px, 100%), 1fr));
    }
    .bb-app .bb-era-strip--grid .bb-era-chip {
        gap: 3px;
        padding: 9px 11px;
    }
}

/* ---- Figures the conformance sweep found still in the text face ------------
   A sweep across all 16 prototype routes checked four design signatures per
   page. It flagged six gaps; two were the sweep's own regex being too narrow
   (Olympia carries its rule on bb-olympia-year-heading, Division has its dark
   header) and these three were real: the athlete profile's at-a-glance panel,
   the calculator result callout, and the game stats were all still rendering
   numbers in Archivo.

   Every one is a figure a reader compares against another figure, which is the
   whole reason this design puts numbers in a mono face with tabular widths. */
.bb-app .bb-profile-glance-value,
.bb-app .bb-result-callout .bb-result-value,
.bb-app .bb-result-callout strong,
.bb-app .bb-game-stats strong,
.bb-app .bb-stat-card-value {
    font-family: var(--bb-font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

/* Same type, two SURFACES - so the colour cannot be shared.
   .bb-stat-card-label sits on light calculator cards, where --bb-warm-grey-2 is
   7.66:1 and correct. .bb-profile-glance-label sits on the DARK profile header,
   where the same grey measured 2.82:1. Its own base rule already had
   rgba(255,255,255,0.72); this block overwrote it when the labels were converted
   to mono, because the two selectors were grouped by how they LOOK rather than by
   what they sit on. */
.bb-app .bb-profile-glance-label,
.bb-app .bb-stat-card-label {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}

/* Both label kinds now sit on LIGHT cards. The glance label used to take bone at
   72% because its panel was a dark overlay on the hero; when the panel became the
   claude-design light card, that on-dark colour rendered the labels invisible on
   white - the exact surface-follows-colour failure the comment above this block
   documents in the other direction. One surface again, so one colour:
   --bb-warm-grey-2 is 7.66:1 on white. */
.bb-app .bb-stat-card-label,
.bb-app .bb-profile-glance-label {
    color: var(--bb-warm-grey-2);
}
/* The glance cells are ~70px inside; at the shared 0.16em tracking the widest
   label ("WIN RATE") measures ~75px and wraps. Tightened only here - the
   calculator stat cards that share the type block are three times as wide. */
.bb-app .bb-profile-glance-label {
    letter-spacing: 0.08em;
}

/* The calculator result is the prototype's inverted panel: the number huge in
   amber mono on ink, with the plain-language reading beneath it. */
.bb-app .bb-result-callout {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border: 0;
    border-radius: 6px;
    color: var(--bb-bone);
}

.bb-app .bb-result-callout .bb-result-value,
.bb-app .bb-result-callout strong {
    font-size: clamp(38px, 5vw, 62px);
    font-weight: 500;
    line-height: 1;
    color: var(--bb-amber);
}

.bb-app .bb-result-callout p,
.bb-app .bb-result-callout .bb-result-read {
    color: rgba(250, 246, 239, 0.76);
}

/* ---- Hub hero + hub disclosure -------------------------------------------
   .bb-hero is the hub's visitor hero. It gets the flat ink surface and the
   ruled wash, which is purely a surface change: no height is added and no
   content moves, because that hero was deliberately reduced to one sentence,
   one search box and three routes after measuring at 831px on desktop and
   1327px on mobile. Restyling it is safe; refilling it would not be. */
.bb-app .bb-hero {
    background: var(--bb-navy);
    background-image: var(--bb-dark-wash);
    border-radius: 0;
}

.bb-app .bb-hero .bb-heading-hero {
    color: var(--bb-bone);
}

.bb-app .bb-hero p {
    color: rgba(250, 246, 239, 0.72);
}

/* Both closing disclosures share the standard shape: paper, hairline, amber
   top rule. The generic .bb-disclosure rule higher in this file supplies the
   surface; these two only need their measure and spacing. */
.bb-app .bb-hub-disclosure {
    margin: clamp(32px, 4vw, 48px) 0 0;
    padding: 26px 30px;
}

.bb-app .bb-hub-disclosure p {
    margin: 12px 0 0;
    max-width: 74ch;
    font-size: 14.5px;
    line-height: 1.65;
    color: var(--bb-text-secondary);
    text-wrap: pretty;
}

/* ==========================================================================
   INTERACTION STATES - brief §3

   The brief requires eight states on every control: default, hover, active,
   focus-visible, disabled, loading, error, empty. An audit of all 18,352 lines
   found three of them did not exist AT ALL:

     :active        - zero occurrences. No control in the plugin had a pressed
                      state, so every tap and click was visually inert until
                      the page responded.
     aria-busy      - zero occurrences. Loading existed only as opt-in
                      .bb-btn-loading / .bb-skeleton classes, which a control
                      has to be told to wear.
     aria-invalid   - zero occurrences. Same for errors: .bb-input-error had to
                      be added by hand.

   Attribute selectors rather than classes, deliberately. aria-busy and
   aria-invalid are what a control must set anyway for a screen reader to
   announce the state; keying the visual off the same attribute means the two
   cannot disagree. A class-based version lets a control look invalid without
   announcing it, which is the worse failure.

   The brief's prototype used an inset grey tint for hover because inline
   styles could not do anything better - one rule that lightens dark fills and
   darkens light ones. §3 says real CSS may use background/border instead, so
   the tint is kept only where a control's own background is unknown.
   ========================================================================== */

.bb-app button,
.bb-app select,
.bb-app summary,
.bb-app a {
    transition:
        box-shadow 130ms cubic-bezier(0.2, 0, 0.4, 1),
        color 130ms cubic-bezier(0.2, 0, 0.4, 1),
        border-color 130ms cubic-bezier(0.2, 0, 0.4, 1),
        transform 80ms cubic-bezier(0.2, 0, 0.4, 1);
}

/* ---- active: the missing pressed state ---------------------------------- */
.bb-app button:active:not(:disabled),
.bb-app select:active:not(:disabled),
.bb-app summary:active,
.bb-app [role="button"]:active:not([aria-disabled="true"]) {
    transform: translateY(1px);
    box-shadow: inset 0 0 0 999px rgba(34, 28, 24, 0.1);
}

/* A link is not a button: it gets the colour shift, not the 1px displacement,
   because nudging inline text moves the line it sits in. */
.bb-app a:active {
    color: var(--bb-primary-hover);
}

/* ---- loading ------------------------------------------------------------- */
.bb-app [aria-busy="true"] {
    cursor: progress;
    opacity: 0.68;
    pointer-events: none;
}

/* ---- error -------------------------------------------------------------- */
.bb-app [aria-invalid="true"],
.bb-app input[aria-invalid="true"],
.bb-app select[aria-invalid="true"],
.bb-app textarea[aria-invalid="true"] {
    border-color: var(--bb-danger);
    box-shadow: 0 0 0 2px rgba(143, 36, 32, 0.16);
}

/* ---- disabled: inputs and selects had no .bb-app-scoped rule ------------- */
.bb-app input:disabled,
.bb-app select:disabled,
.bb-app textarea:disabled,
.bb-app button:disabled,
.bb-app [aria-disabled="true"] {
    opacity: 0.42;
    cursor: not-allowed;
    filter: saturate(0.5);
}

/* Reduced motion has to reach the transform above, not just durations. The
   existing blanket rule zeroes animation/transition duration only, which
   leaves a 1px jump on every press. */
@media (prefers-reduced-motion: reduce) {
    .bb-app button:active:not(:disabled),
    .bb-app select:active:not(:disabled),
    .bb-app summary:active,
    .bb-app [role="button"]:active:not([aria-disabled="true"]) {
        transform: none;
    }
}

/* ==========================================================================
   RESPONSIVE ROOT CAUSES - brief §4

   §4 asks for root causes rather than guards, so these are stylesheet-level
   and sit here once instead of being repeated on fifteen pages.

   Three mechanical sweeps were applied above by rule, not by hand:
     - 18 auto-fit/auto-fill tracks got minmax(min(Npx, 100%), 1fr). A bare
       minmax(300px, 1fr) cannot shrink below 300px, so .bb-news-grid and
       .bb-divisions-grid overflowed a 320px viewport outright.
     - 37 repeat(N, 1fr) became repeat(N, minmax(0, 1fr)). A bare 1fr keeps an
       implicit min-content floor, so one long athlete name forces its column
       past its share. Purely protective - it can only allow narrower, never
       wider.
     - 11 symmetric gutters >= 32px became clamp(18px, 4.4vw, <original>),
       chosen so DESKTOP DOES NOT MOVE: 4.4vw at 1440px is 63px, which clamps
       back to the original. Only narrow viewports change.

   Asymmetric four-value paddings were deliberately skipped. `padding: 10px
   14px 10px 40px` has a 40px left because a glyph sits in it; that is an
   offset, not a gutter, and making it fluid slides the glyph.

   The five `overflow-x: visible` rules elsewhere in this file were reviewed and
   LEFT ALONE. An audit read them as defeating their own scroll wrapper, but
   each one replaces scrolling with something better at that breakpoint -
   .bb-career-timeline goes vertical, .bb-division-filter and .bb-event-tabs
   wrap, .bb-table-scroll-wrapper releases only when its table stacks into
   cards, .bb-era-strip--grid is a grid. Four carry comments naming the bug
   that motivated them. They are not defects.
   ========================================================================== */

/* ---- The container had no gutter at all ----------------------------------
   .bb-app .bb-container is max-width 1192px with zero horizontal padding, so
   below 1192px it sits flush to the viewport edge and every child's own
   padding is the only thing keeping text off the glass.

   Scoped to a media query on purpose. An unconditional padding-inline would
   inset content on desktop too and double up against the padding that cards,
   panels and section blocks already carry. Above 1240px the container is
   centred with room to spare and needs nothing. */
@media (max-width: 1240px) {
    .bb-app .bb-container {
        padding-inline: clamp(16px, 4vw, 24px);
    }
}

/* The comment above says the container "needs nothing" over 1240px, and that is
   right, but nothing ever said it. The base .bb-container rule sets
   padding-inline: var(--bb-space-6) from the 640px breakpoint up and keeps
   applying at every width above it, so every band rendered 1192 inside a 1240
   .bb-app - 48px narrower than claude-design draws it, on all 13 routes.
   Measured 2026-08-02: prototype bands 1240 flush, live 1192 at x=124. */
@media (min-width: 1241px) {
    .bb-app .bb-container {
        padding-inline: 0;
    }
}

/* ---- The chrome is not a content band ----------------------------------
   Both rules above are about content bands, which are meant to run flush to
   the 1240 edge so they line up with the design. The nav and the footer use
   the same .bb-container class and picked up the same zero gutter, but
   neither is a band. Each paints its own surface: .bb-app .bb-nav has a
   border, a bottom radius and a shadow, and .bb-footer is a dark slab with a
   top border. So their contents were sitting ON the edge they draw.

   Measured above 1240px, distance from the surface's own edge:
     nav     logo left and search right   1px
     footer  brand left and links right   0px

   Scoped to those two containers rather than relaxing the band rule, because
   the band behaviour is deliberate and was itself a fix - the bands used to
   render 1192 wide inside a 1240 shell.

   The floor matches what the sub-1240 rule already gives, so nothing narrows
   on mobile; it only grows once there is room for it. */
.bb-app .bb-nav > .bb-container,
.bb-app .bb-footer > .bb-container {
    padding-inline: clamp(16px, 1.8vw, 32px);
}

/* ---- Wide tables: one width for head and body ---------------------------
   §4 wants a wide table to keep a min-width inside its scroll wrapper so the
   header and body scroll together, and calls that deliberate horizontal
   scroll rather than a bug. Not one table in this file declared any width, so
   columns compressed instead of holding a floor.

   `width: max-content` with `min-width: 100%` does it without a magic number:
   the table becomes exactly as wide as its content needs - so head and body
   share one width and scroll as a unit - but never narrower than its wrapper,
   so a two-column table still fills the space instead of shrinking to its
   text. This is why no per-table pixel floor is invented here; a guessed
   560px would force scroll on tables that currently fit.

   .bb-table--responsive opts out: it stacks into cards at narrow widths, so
   it must not be forced wide. */
.bb-app .bb-table-wrapper > .bb-table,
.bb-app .bb-table-scroll-wrapper > .bb-table,
.bb-app .bb-table-container > .bb-table,
.bb-app .bb-content-table-wrapper > .bb-content-table,
.bb-app .bb-rankings-table-scroll > .bb-rankings-table,
.bb-app .bb-rto-table-wrap > .bb-rto-table {
    width: max-content;
    min-width: 100%;
}

/* The opt-out says "do not force me to max-content", not "do not fill". It was
   `width: auto`, which is shrink-to-fit: on the athlete directory the table came
   out 989px wide inside its 1140px wrapper, leaving a 151px strip of empty
   wrapper to the right of the STATUS column.

   `width: 100%` fills the wrapper and can never exceed it, so the stacking rules
   still take over at narrow widths and nothing overflows - it restores what
   `.bb-table { width: 100% }` always intended, while keeping min-width off so the
   table is not forced wider than its container. */
.bb-app .bb-table-scroll-wrapper > .bb-table--responsive {
    width: 100%;
    min-width: 0;
}

/* ---- Flex children that hold text must be allowed to shrink -------------
   §4's first rule. .bb-olympia-hub-card is flex-wrap with two children that
   set min-width 220px and 160px - the opposite of what §4 asks - so on a
   narrow viewport the card cannot reflow below 380px of content plus its own
   gutters. Both hold text, so both get the shrink permission instead. */
.bb-app .bb-olympia-hub-info,
.bb-app .bb-olympia-hub-stats {
    min-width: 0;
    flex-basis: auto;
}

/* ---- Hub data ledger (brief §7) ------------------------------------------
   Reuses .bb-olympia-hero-stats, the hairline-divided grid already built for
   the Olympia and Directory heroes, so the hub's band is the same component
   rather than a fourth variation on a row of figures.

   It is a <dl>, and the figure comes before its label in source order, so the
   markup reads value-then-name the way the eye does. dd/dt are reversed
   visually by the grid, not by DOM order, because a screen reader should hear
   "110,389 - athlete records", not the label first. */
.bb-app .bb-hero-ledger {
    margin: clamp(26px, 3.4vw, 40px) 0 0;
}

.bb-app .bb-hero-ledger .bb-olympia-hero-stat > dd {
    margin: 0;
}

/* Countries is the one accented cell in the prototype - the amber marks the
   end of the row rather than decorating an arbitrary figure. */
.bb-app .bb-hero-ledger__num--accent {
    color: var(--bb-amber-on-dark);
}

/* ---- Explore tiles: ten uniform (brief §7) --------------------------------
   .bb-data-grid--weighted and the --large/--small tile modifiers are no longer
   emitted. Their rules stay in place further up this file, harmless and unused,
   because deleting a block that other routes might still reference is a
   separate change from stopping the hub emitting it. If a later sweep confirms
   nothing uses them, they go.

   The grid is spelled out here rather than inherited so the tiles cannot pick
   up the weighted spans again by accident. */
/* Column counts that DIVIDE TEN, not auto-fit.
   auto-fit resolved to 4 columns for 10 tiles, so the last row held 2 tiles and
   2 empty cells - and because the grid paints the hairlines by showing its own
   background through 1px gaps, those empty cells rendered as two solid grey
   blocks. Exactly the orphan-row bug already fixed once on the FAQ grid; the
   auto-fit convenience causes it every time the item count is not a multiple of
   whatever width happens to resolve.
   10 = 5x2 = 2x5 = 1x10, so every breakpoint below fills its last row exactly.

   These counts are COUPLED to the ten tiles in $data_features (hub.php:279). The
   hairlines are the container background showing through 1px gaps, so an empty
   cell is a visible grey block, not whitespace - if a tile is ever added or
   removed, these three counts have to divide the new total. */
.bb-app .bb-data-section .bb-data-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    padding: 1px;
    background: var(--bb-border);
    border: 1px solid var(--bb-border);
    border-radius: 6px;
}

@media (min-width: 900px) {
    .bb-app .bb-data-section .bb-data-grid {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }
}

@media (max-width: 479px) {
    .bb-app .bb-data-section .bb-data-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.bb-app .bb-data-section .bb-data-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    margin: 0;
    padding: 20px 22px;
    background: var(--bb-surface-raised);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    grid-column: auto;
}

/* The mono kicker §7 asks for. Amber on light, so it reads as a category and
   not as a second link. */
.bb-app .bb-data-category {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-amber-on-light);
}

.bb-app .bb-data-section .bb-data-title {
    margin: 0;
    font-family: var(--bb-font-heading);
    font-size: 17px;
    font-weight: 700;
    line-height: 1.24;
    letter-spacing: -0.012em;
    color: var(--bb-ink);
}

.bb-app .bb-data-section .bb-data-description {
    margin: 0;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--bb-text-secondary);
    text-wrap: pretty;
}

.bb-app .bb-data-section .bb-data-link {
    margin-top: auto;
    padding-top: 4px;
    font-family: var(--bb-font-heading);
    font-size: 13px;
    font-weight: 500;
    color: var(--bb-primary);
}

/* Hover for the uniform tiles. The generic .bb-data-card:hover paints a
   border-color, which does nothing here (border: 0 - the 1px grid gap IS the
   rule), so the feedback has to be the surface instead. */
.bb-app .bb-data-section .bb-data-card:hover,
.bb-app .bb-data-section .bb-data-card:focus-visible {
    background: var(--bb-surface-sunken);
    box-shadow: none;
    transform: none;
}

.bb-app .bb-data-section .bb-data-card:hover .bb-data-link,
.bb-app .bb-data-section .bb-data-card:focus-visible .bb-data-link {
    color: var(--bb-primary-hover);
}

/* The whole tile is the link target, so the focus ring belongs on the tile and
   must sit above its neighbours' backgrounds to be fully visible. */
.bb-app .bb-data-section .bb-data-card:focus-visible {
    outline: 2px solid var(--bb-ink);
    outline-offset: -2px;
    position: relative;
    z-index: 1;
}

/* ==========================================================================
   Segmented tabs (Men's / Women's) - hub divisions grid + GOAT
   Brief §7 asks for tabs on both. Implemented as a radio group filtered with
   :has(), NOT as an ARIA tablist, because §1 requires the page to work with
   JavaScript off and a tablist's selected state is script-maintained by
   definition. Radios give keyboard navigation for free and need no script.
   ========================================================================== */
.bb-app .bb-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
    margin: 0 0 20px;
    border: 1px solid var(--bb-border-strong);
    border-radius: 4px;
    overflow: hidden;
    width: fit-content;
    max-width: 100%;
}

/* Visually hidden but still FOCUSABLE. display:none or visibility:hidden would
   take the radios out of the tab order and the control would be unreachable by
   keyboard - the usual way this pattern gets broken. */
.bb-app .bb-tabs__radio {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.bb-app .bb-tabs__tab {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--bb-touch-min);
    padding: 0 20px;
    font-family: var(--bb-font-mono);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bb-text-secondary);
    background: var(--bb-surface-raised);
    cursor: pointer;
    user-select: none;
}

.bb-app .bb-tabs__tab + .bb-tabs__radio + .bb-tabs__tab,
.bb-app .bb-tabs__radio + .bb-tabs__tab:not(:first-of-type) {
    border-left: 1px solid var(--bb-border);
}

.bb-app .bb-tabs__radio:checked + .bb-tabs__tab {
    color: var(--bb-bone);
    background: var(--bb-ink);
}

.bb-app .bb-tabs__radio:not(:checked) + .bb-tabs__tab:hover {
    background: var(--bb-surface-sunken);
    color: var(--bb-ink);
}

/* The ring goes on the LABEL, because the input it belongs to is clipped to a
   1px box and its own ring would be invisible. */
.bb-app .bb-tabs__radio:focus-visible + .bb-tabs__tab {
    outline: 2px solid var(--bb-ink);
    outline-offset: -3px;
}

/* Pressed state. §10 wants eight states on every control, and the global rule is
   `.bb-app button:active` - these tabs are <label> elements, so nothing matched
   them and they were the one control on the page with no pressed feedback. */
.bb-app .bb-tabs__tab:active {
    transform: translateY(1px);
}

.bb-app .bb-tabs__radio:not(:checked) + .bb-tabs__tab:active {
    background: var(--bb-tint);
}

/* ---- Divisions grid filtering ------------------------------------------- */

/* Unknown-gender cards (data-bb-gender="X") are deliberately NOT hidden by
   either rule, so a division with missing metadata stays visible in both tabs
   instead of disappearing from the page entirely. */
.bb-app .bb-divisions-section:has(#bb-div-gender-m:checked) .bb-division-card[data-bb-gender="F"],
.bb-app .bb-divisions-section:has(#bb-div-gender-f:checked) .bb-division-card[data-bb-gender="M"] {
    display: none;
}

/* ---- GOAT panel filtering ------------------------------------------------ */
.bb-app .bb-top-athletes-section:has(#bb-goat-gender-m:checked) [data-bb-goat-panel="f"],
.bb-app .bb-top-athletes-section:has(#bb-goat-gender-f:checked) [data-bb-goat-panel="m"] {
    display: none;
}

/* No :has() support: show every panel rather than hide all of them. A browser
   that cannot run the filter still gets the full list, which is the honest
   degradation - the alternative is a section that renders empty. */
@supports not selector(:has(*)) {
    .bb-app .bb-tabs { display: none; }
    .bb-app [data-bb-goat-panel] { display: grid; }
}

.bb-app .bb-goat-window-note {
    margin: 14px 0 0;
    font-family: var(--bb-font-mono);
    font-size: 12px;
    line-height: 1.5;
    color: var(--bb-text-muted);
}

/* ==========================================================================
   Hub masthead freshness line + closing status bar (§7 first and last items)
   ========================================================================== */
.bb-app .bb-hub-masthead {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 14px;
}

/* --bb-status-ok is the freshness dot in §2's token table. Moss, not amber:
   amber would read as a warning next to a date. */
.bb-app .bb-hub-masthead__dot,
.bb-app .bb-status-bar__dot {
    flex-shrink: 0;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--bb-status-ok);
}

.bb-app .bb-hub-masthead .bb-data-freshness {
    margin: 0;
    font-family: var(--bb-font-mono);
    font-size: 11.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}

.bb-app .bb-status-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    margin: 32px 0 0;
    padding: 14px 18px;
    border-top: 2px solid var(--bb-ink);
    background: var(--bb-surface-sunken);
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-text-secondary);
}

.bb-app .bb-status-bar__label {
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--bb-ink);
}

.bb-app .bb-status-bar__list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.bb-app .bb-status-bar__cell {
    font-variant-numeric: tabular-nums;
}

/* Separators as a pseudo-element, so they never appear before the first cell or
   after a cell the PHP dropped for a missing figure. A literal " - " in the
   markup would strand a dangling separator whenever a stat is unavailable. */
.bb-app .bb-status-bar__cell + .bb-status-bar__cell::before {
    content: "/";
    margin-right: 14px;
    color: var(--bb-border-strong);
}

.bb-app .bb-status-bar .bb-data-freshness {
    margin: 0 0 0 auto;
    font-size: 12px;
    color: var(--bb-text-muted);
}

/* ==========================================================================
   Settled by the record (§7 authority module)
   ========================================================================== */
.bb-app .bb-settle-section {
    margin-bottom: 40px;
}

.bb-app .bb-settle-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
    gap: 1px;
    margin: 0;
    padding: 1px;
    list-style: none;
    background: var(--bb-border);
    border: 1px solid var(--bb-border);
    border-radius: 6px;
}

.bb-app .bb-settle-item {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
    padding: 22px 24px;
    background: var(--bb-surface-raised);
}

.bb-app .bb-settle-question {
    margin: 0;
    font-family: var(--bb-font-heading);
    font-size: 17px;
    font-weight: 700;
    font-stretch: 92%;
    line-height: 1.28;
    letter-spacing: -0.012em;
    color: var(--bb-ink);
    text-wrap: pretty;
}

/* The verdict is the answer, so it carries the accent and the weight. */
.bb-app .bb-settle-verdict {
    margin: 0;
    font-family: var(--bb-font-mono);
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    color: var(--bb-primary);
    font-variant-numeric: tabular-nums;
}

.bb-app .bb-settle-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
    margin: 2px 0 0;
}

/* 11px, not 10.5px. The plugin has a hard 11px text floor (the label layer was
   lifted 10px -> 11px by owner decision) and test-type-scale-floor.mjs enforces
   it: nine of these dt cells at 10.5px were the only sub-floor text on the page. */
.bb-app .bb-settle-fact dt {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}

.bb-app .bb-settle-fact dd {
    margin: 2px 0 0;
    font-family: var(--bb-font-mono);
    font-size: 15px;
    font-weight: 600;
    line-height: 1;
    color: var(--bb-ink);
    font-variant-numeric: tabular-nums;
}

/* The concession. Set apart with a rule and the sunken surface so it reads as
   the module's own admission rather than as more marketing copy - if it looked
   like the rest of the card, it would not do its job. */
.bb-app .bb-settle-limit {
    margin: 4px 0 0;
    padding: 10px 12px;
    border-left: 2px solid var(--bb-border-strong);
    background: var(--bb-surface-sunken);
    font-size: 13px;
    line-height: 1.55;
    color: var(--bb-text-secondary);
    text-wrap: pretty;
}

.bb-app .bb-settle-link {
    margin-top: auto;
    padding-top: 6px;
    font-family: var(--bb-font-heading);
    font-size: 13px;
    font-weight: 500;
    color: var(--bb-primary);
}

.bb-app .bb-settle-footer {
    margin-top: 18px;
}

/* ---- Figures the mono conversion missed --------------------------------- */

/* §2: "All figures, dates, counts, labels: IBM Plex Mono with tabular-nums."
   These four still resolved to var(--bb-font-heading) from a rule that groups
   them with the heading tier, because the conversion was done class-by-class in
   this block and these were never reached: .bb-olympia-hero-stat-num and
   .bb-stat-card-value ARE here, their siblings were not. So the Olympia year
   cards rendered 1965 in Archivo next to hero stats in Plex Mono, on the same
   page.

   Names are deliberately NOT in this list. .bb-olympia-div-winner holds an
   athlete's name and stays in Archivo - putting names in monospace was a real
   mistake made earlier in this redesign and reverted. Mono is for things you
   compare down a column. */
.bb-app .bb-olympia-year-num,
.bb-app .bb-stat-number,
.bb-app .bb-rank-badge,
.bb-app .bb-placement {
    font-family: var(--bb-font-mono);
    font-variant-numeric: tabular-nums;
}

/* ---- Headings on dark surfaces must not be forced to ink ----------------- */

/* `.bb-app h1, .bb-app h2, ... { color: var(--bb-text-primary) }` has
   specificity 0,1,1 - one class plus one element - so it beats every
   single-class component rule, including `.bb-rto-cta-title { color: white }`
   (0,1,0). The dark surfaces set `color: #fffdf8` on themselves and rely on
   inheritance, but inheritance loses to ANY matching rule, so their headings went
   ink-on-ink. The hub's "Road to Olympia 2026" title was invisible.

   `color: inherit` rather than a literal: each surface already declares its own
   on-dark colour, and hardcoding a second copy here is how the two drift apart.
   Specificity is 0,2,1, which clears the global heading rule without !important. */
.bb-app .bb-page-header :is(h1, h2, h3, h4, h5, h6),
.bb-app .bb-hero :is(h1, h2, h3, h4, h5, h6),
.bb-app .bb-rto-cta-card :is(h1, h2, h3, h4, h5, h6),
.bb-app .bb-featured-card :is(h1, h2, h3, h4, h5, h6),
.bb-athlete-profile-page .bb-profile-header :is(h1, h2, h3, h4, h5, h6) {
    color: inherit;
}

/* Filter-state chip clear buttons.
   Each chip's "x" is a real submit inside its own GET form, which is what makes
   removing a filter work with JavaScript off. The five forms carried
   style="display:inline" inline; an inline declaration outranks every class rule,
   so the chips could not be restyled from the stylesheet at all. inline-flex
   rather than inline so the button aligns to the chip's text baseline instead of
   sitting on it. */
.bb-app .bb-state-chip-form {
    display: inline-flex;
    align-items: center;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
}

/* ---- Share menus: viewport-anchored on phones ----------------------------
   A STATIC anchor provably cannot keep this on screen. Measured on
   /athletes/ronnie-coleman/, share wrapper 90px wide, menu 210px:

     320px  wrapper at x=175  right:0 -> left  55  OK   left:0 -> right 385  OFF
     375px  wrapper at x=202  right:0 -> left  82  OK   left:0 -> right 412  OFF
     390px  wrapper at x=85   right:0 -> left -35  OFF  left:0 -> right 295  OK
     414px  wrapper at x=97   right:0 -> left -23  OFF  left:0 -> right 307  OK
     768px+ wrapper anywhere  both fit

   The profile header changes layout between 375 and 390, which moves the
   trigger, so whichever edge the menu hangs from is wrong at some phone width.
   That is why this has been "fixed" three times already by adding another
   per-consumer anchor class (.bb-share-dropdown right:0, .bb-share-menu left:0,
   .bb-share-dropdown--start) and kept coming back with a new broken route.

   Below 640px the menu stops being anchored to its trigger at all and is pinned
   to the viewport with equal gutters, so its position no longer depends on where
   the trigger landed. Above 640px both anchors fit and the existing behaviour is
   untouched. */
@media (max-width: 640px) {
    .bb-app .bb-share-dropdown,
    .bb-app .bb-share-menu {
        position: fixed;
        top: auto;
        right: 12px;
        bottom: 12px;
        left: 12px;
        min-width: 0;
        max-width: none;
        /* Above the sticky masthead, which sits at z-index 90. */
        z-index: 120;
        border-radius: 8px;
        box-shadow: 0 -6px 32px rgba(34, 28, 24, 0.28);
    }

    /* The odds board's left-anchored variant has nothing left to say once the
       menu is viewport-anchored; without this its left:0 / right:auto would
       reintroduce a trigger-relative edge. */
    .bb-app .bb-share-dropdown--start {
        right: 12px;
        left: 12px;
    }
}

/* Right-aligned share wrapper (the compare toolbar).
   .bb-share-wrap is inline-flex, so it shrinks to its trigger and sits wherever
   it lands in normal flow. This modifier makes it span its container and push the
   trigger to the trailing edge - what the removed inline
   `display:flex;justify-content:flex-end;margin-bottom:...` was doing, now
   reachable from the stylesheet. */
.bb-app .bb-share-wrap--end {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--bb-space-3);
}

/* ---- Dark surfaces set their own text colour ----------------------------- */

/* Every one of these paints a dark background, and each relied on lighting up a
   HAND-LISTED set of children (.bb-page-title, .bb-page-subtitle, .bb-page-desc,
   .bb-profile-name, and so on). Any other text inside them inherited the
   page-level ink and became invisible - not low-contrast, the identical colour.
   Found on three routes at once:

     /rivalries/  an <a> "How rivalry rankings work"      ink on ink, 183x16
     /rivalries/  a <strong> "Our highest-ranked rivalry" ink on ink, 684x17
     /compare/    a <span> "Swap sides"                   ink on ink,  68x16

   Setting the colour on the SURFACE means a new child element cannot be missed,
   which an allowlist of descendants can never guarantee. The existing per-child
   rules still win where they want a different tone (muted labels, amber links);
   this is only the floor beneath them. */
.bb-app .bb-page-header,
.bb-app .bb-page-header.bb-page-header-dark,
.bb-app .bb-page-header.bb-page-header--dark,
.bb-athlete-profile-page .bb-profile-header,
.bb-app .bb-hero,
.bb-app .bb-rto-cta-card,
.bb-app .bb-featured-card {
    color: var(--bb-bone);
}

/* ---- A surface that owns a background owns its text colour ----------------
   Found by walking every element with an OPAQUE background and comparing it to
   its own computed colour, so these are not guesses:

     .bb-footer                    ink on ink, 1.0  - on all ten routes checked
     .bb-page-hero--goat           ink on ink, 1.0
     .bb-share-dropdown            bone on bone, 1.0
     .bb-compare-selector-card     bone on bone, 1.0
     .bb-compare-selected          bone on #f6f3ed, 1.03
     .bb-compare-selected-avatar   bone on #dfd7cb, 1.32

   The dark ones were invisible before this pass. The light ones are LIGHT CARDS
   NESTED INSIDE THE DARK HERO: giving the dark surfaces an inherited bone (just
   above) fixed the text that sat directly on them and pushed bone into these
   cards, which own a pale background of their own. That is the lesson - setting a
   colour on a surface only works if every nested surface also declares one, so
   both directions are stated here rather than one. */
.bb-app .bb-footer,
.bb-app .bb-page-hero {
    color: var(--bb-bone);
}

.bb-app .bb-share-dropdown,
.bb-app .bb-share-menu,
.bb-app .bb-compare-selector-card,
.bb-app .bb-compare-selected,
.bb-app .bb-compare-selected-avatar {
    color: var(--bb-text-primary);
}

/* .bb-answer-block inside a dark band.
   The block declares a translucent oxblood wash and --bb-text-primary, which is
   right on the four routes where it sits on paper (countries, divisions x2,
   stats). On /rivalries/ it renders inside the dark page header, where that ink
   text over an 8% oxblood tint on ink measured 1.1:1 - the answer sentence the
   section exists to deliver was invisible. Scoped to the dark contexts so the
   light ones keep their own treatment. */
.bb-app .bb-page-header .bb-answer-block,
.bb-app .bb-page-header .bb-answer-block strong,
.bb-app .bb-hero .bb-answer-block,
.bb-app .bb-hero .bb-answer-block strong {
    color: var(--bb-bone);
}

/* ---- Compare: classes for what used to be inline style attributes -------- */

/* Five static inline declarations lived on these elements. An inline declaration
   outranks every class rule, so none of them could be restyled from here - which
   is how a component ends up immune to its own design system. The ONE inline style
   left in compare/index.php is the head-to-head bar's width, which is computed
   from the record and genuinely cannot live in a stylesheet. */

.bb-app .bb-profile-photo-fallback--compare {
    width: calc(var(--bb-space-16) - var(--bb-space-1));
    height: calc(var(--bb-space-16) - var(--bb-space-1));
    font-size: var(--bb-fs-md);
}

.bb-app .bb-form-error--flush {
    margin: 0;
}

/* Not an overlay in this context: it sits in normal flow where the results will
   appear, so it holds the layout instead of floating over it. */
.bb-app .bb-loading-overlay--inline {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: calc(var(--bb-space-16) - var(--bb-space-1));
}

.bb-app .bb-loading-overlay__label {
    margin-top: var(--bb-space-3);
}

/* Timeline legend: three DISTINCT accents.
   The third dot was var(--bb-accent), which resolves to the same oxblood as
   var(--bb-primary) on the first, so "Shared Contest" and athlete A were
   indistinguishable in a legend whose only job is to distinguish them. A/B is the
   oxblood-vs-charcoal pairing the owner settled on; shared takes amber. */
.bb-app .bb-timeline-legend-dot--a      { background: var(--bb-chart-series-1); }
.bb-app .bb-timeline-legend-dot--b      { background: var(--bb-chart-series-2); }
.bb-app .bb-timeline-legend-dot--shared { background: var(--bb-amber-on-light); }

/* ---- Sortable table headers are links now -------------------------------- */

/* Each sortable <th> holds a real <a href> to the server-sorted URL. Previously
   the <th> itself carried tabindex="0" with a click handler - focusable but with
   no role and no keyboard activation, so Enter and Space did nothing and sorting
   was mouse-only even with JavaScript running. The link fills the cell so the
   whole header stays the target it always looked like. */
.bb-app .bb-th-sort-link {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    color: inherit;
    text-decoration: none;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
}

.bb-app .bb-th-num .bb-th-sort-link {
    justify-content: flex-end;
}

.bb-app .bb-th-sort-link:hover {
    color: var(--bb-primary);
}

.bb-app .bb-th-sort-link:focus-visible {
    outline: 2px solid var(--bb-ink);
    outline-offset: 2px;
}

/* The active column reads as active without relying on the arrow glyph alone. */
.bb-app th[aria-sort="ascending"] .bb-th-sort-link,
.bb-app th[aria-sort="descending"] .bb-th-sort-link {
    color: var(--bb-ink);
    font-weight: 700;
}

.bb-app .bb-toolbar-search__submit {
    flex-shrink: 0;
}

/* Rankings filter form: was an inline style attribute on the <form>, so the one
   control bar on that page could not be restyled from here. */
.bb-app .bb-filter-form--inline {
    display: flex;
    gap: var(--bb-space-2);
    align-items: center;
    flex-wrap: wrap;
}

/* ---- Segmented control (two-state toggle) -------------------------------- */

/* Both states are declared here, keyed on aria-pressed, which these buttons
   already carry for assistive tech - so the visual state and the announced state
   cannot drift apart.

   The bug this replaces: only the SELECTED button set a background (inline), so
   the unselected one inherited the parent theme's button style - a bright pink
   rgb(255,24,78) that exists nowhere in this palette, white text on it measuring
   3.82:1. Styling one state and leaving the other to inherit is how a colour
   nobody chose ends up on the page. */
.bb-app .bb-segmented {
    display: flex;
    gap: var(--bb-space-2);
}

.bb-app .bb-segmented__btn {
    flex: 1;
    border-radius: var(--bb-radius);
}

.bb-app .bb-segmented__btn[aria-pressed="false"] {
    background: var(--bb-surface-raised);
    color: var(--bb-text-primary);
    border: 1px solid var(--bb-border-strong);
}

.bb-app .bb-segmented__btn[aria-pressed="false"]:hover {
    background: var(--bb-surface-sunken);
}

.bb-app .bb-segmented__btn[aria-pressed="true"] {
    background: var(--bb-primary);
    color: var(--bb-on-dark);
    border: 1px solid var(--bb-primary);
}

/* Predictions contest tabs: the ACTIVE tab must win against the theme.
   .bb-predictions-contest-tab--active already declared color:#fff, but it is a
   single class (0,1,0) and both `.bb-app a` and the parent theme's
   `.rbct a:where(...)` are (0,1,1). The theme's rule loads later and resolves to
   `inherit`, so the tab inherited page ink and sat at 2.6:1 on its own oxblood
   background - a selected tab that was harder to read than the unselected ones.
   Scoping to .bb-app makes it (0,2,1). */
.bb-app .bb-predictions-contest-tab--active,
.bb-app .bb-predictions-contest-tab--active:hover,
.bb-app .bb-predictions-contest-tab--active:focus-visible {
    color: var(--bb-on-dark);
}

/* ==========================================================================
   Athlete profile sections: open on the bone page, per claude-design
   --------------------------------------------------------------------------
   The prototype does not wrap sections in cards. Each section sits directly on
   the bone background and gets its structure from the ruled heading; only
   specific modules inside them are cards (the championship record, the
   timeline canvas, rival and related cards, tables). The live page wrapped
   every section in a white rounded panel with a hover shadow, which is why it
   read as a stack of boxes instead of the prototype's page rhythm.

   One authoritative block, last in the file, because the card look was applied
   across four earlier layers (base rule, hover-shadow pass, spacing pass,
   surface-flattening pass) and unpicking each would leave the next session
   guessing which layer won.

   .bb-stats-box (the championship record) deliberately stays a card - it is
   one in the prototype too.
   ========================================================================== */
.bb-app .bb-athlete-profile-page .bb-profile-section {
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0;
    box-shadow: none;
    margin-bottom: var(--bb-space-8);
}
.bb-app .bb-athlete-profile-page .bb-profile-section:hover {
    border-color: transparent;
    box-shadow: none;
}

/* claude-design rival card: name, AHEAD/BEHIND split, oxblood share bar, shared
   count. Replaces the one-line "33 meetings, 14-19 head to head" sentence. The
   card itself stays a card - it is one in the prototype. */
.bb-app .bb-rival-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--bb-space-2);
}
.bb-app .bb-rival-card-name {
    font-weight: 700;
    font-size: var(--bb-fs-base);
    color: var(--bb-ink);
}
.bb-app .bb-rival-split {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-family: var(--bb-font-mono);
}
.bb-app .bb-rival-split__num {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--bb-accent);
    font-variant-numeric: tabular-nums;
}
.bb-app .bb-rival-split__num--behind {
    color: var(--bb-ink);
    margin-left: auto;
}
.bb-app .bb-rival-split__label {
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-warm-grey-2);
}
.bb-app .bb-rival-bar {
    height: 5px;
    background: var(--bb-tint);
    border-radius: var(--bb-radius-full);
    overflow: hidden;
}
.bb-app .bb-rival-bar__fill {
    display: block;
    height: 100%;
    background: var(--bb-accent);
    border-radius: inherit;
}
.bb-app .bb-rival-meta {
    margin: 0;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-xs);
    color: var(--bb-warm-grey-2);
}
.bb-app .bb-rival-card .bb-btn {
    align-self: flex-start;
}

/* --- claude-design profile sections: heads, record card, missing band, filters --- */

/* Heading row: title left, mono meta or action link right, one 2px rule under
   BOTH. The rule moves to the wrapper, so the inner h2 border is zeroed - the
   GOAT phase documented what happens when wrapper and element each keep a
   spine: two rules per section. */
.bb-app .bb-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
    border-bottom: 2px solid var(--bb-ink);
    margin: 0 0 var(--bb-space-5);
}
.bb-app .bb-section-head .bb-section-title {
    border-bottom: none;
    margin-bottom: 0;
    padding-bottom: var(--bb-space-2);
}
.bb-app .bb-section-head__meta {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-xs);
    color: var(--bb-warm-grey-2);
    padding-bottom: var(--bb-space-2);
    font-variant-numeric: tabular-nums;
}
.bb-app .bb-section-head__link {
    font-size: var(--bb-fs-sm);
    font-weight: 600;
    color: var(--bb-accent);
    text-decoration: none;
    padding-bottom: var(--bb-space-2);
}
.bb-app .bb-section-head__link:hover,
.bb-app .bb-section-head__link:focus-visible {
    text-decoration: underline;
}
.bb-app .bb-section-sub {
    margin: calc(-1 * var(--bb-space-3)) 0 var(--bb-space-4);
    color: var(--bb-warm-grey);
    font-size: var(--bb-fs-sm);
}

/* Championship record card: kicker + editorial title, then one bordered row per
   series with three mono figures - the title figure in oxblood. */
.bb-app .bb-stats-box__head {
    padding-bottom: var(--bb-space-3);
    border-bottom: 1px solid var(--bb-border);
    margin-bottom: 0;
}
.bb-app .bb-stats-box-kicker {
    display: block;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--bb-warm-grey-2);
    margin-bottom: 4px;
}
.bb-app .bb-stats-box .bb-stats-box-title {
    /* Was 1.5rem, which is 22.5px against a 15px root, not the 24 it meant. */
    font-size: var(--bb-fs-xl);
    margin: 0;
}
.bb-app .bb-record-row {
    padding: var(--bb-space-4) 0;
    border-bottom: 1px solid var(--bb-border-soft, var(--bb-border));
}
.bb-app .bb-record-row:last-child {
    border-bottom: none;
    padding-bottom: 0;
}
.bb-app .bb-record-row__series {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--bb-ink);
    margin: 0 0 var(--bb-space-2);
}
.bb-app .bb-record-row__stats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--bb-space-4);
}
.bb-app .bb-record-stat__num {
    display: block;
    font-family: var(--bb-font-mono);
    font-size: 1.75rem;
    font-weight: 500;
    line-height: 1.1;
    color: var(--bb-ink);
    font-variant-numeric: tabular-nums;
}
.bb-app .bb-record-stat__num--title {
    color: var(--bb-accent);
    font-weight: 600;
}
.bb-app .bb-record-stat__label {
    display: block;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--bb-warm-grey-2);
    margin-top: 4px;
}

/* Missing-from-this-profile band: absence gets its own honest surface. */
.bb-app .bb-missing-band {
    display: flex;
    align-items: center;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
    padding: var(--bb-space-3) var(--bb-space-4);
    margin: 0 0 var(--bb-space-6);
}
.bb-app .bb-missing-band__kicker {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--bb-warm-grey-2);
    white-space: nowrap;
}
.bb-app .bb-missing-band__text {
    margin: 0;
    font-size: var(--bb-fs-sm);
    color: var(--bb-ink);
    flex: 1 1 auto;
}
.bb-app .bb-missing-band__actions {
    display: flex;
    gap: var(--bb-space-2);
    flex-wrap: wrap;
    margin-left: auto;
}
.bb-app .bb-missing-band__actions .bb-athlete-bio-trigger {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 6px 14px;
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-ink);
    border-radius: var(--bb-radius);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: var(--bb-ink);
    cursor: pointer;
}
.bb-app .bb-missing-band__actions .bb-athlete-bio-trigger:hover,
.bb-app .bb-missing-band__actions .bb-athlete-bio-trigger:focus-visible {
    background: var(--bb-tint);
}

/* Result filters: three SSR views. Active = solid ink, per the prototype. */
.bb-app .bb-results-filter {
    display: flex;
    gap: var(--bb-space-2);
    padding-bottom: var(--bb-space-2);
}
.bb-app .bb-results-filter__btn {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 6px 14px;
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    color: var(--bb-ink);
    text-decoration: none;
    white-space: nowrap;
}
.bb-app .bb-results-filter__btn:hover,
.bb-app .bb-results-filter__btn:focus-visible {
    border-color: var(--bb-ink);
}
/* .bb-results-filter__btn--active is gone: the active view is now whichever
   radio is :checked, so a PHP-stamped class would be a second owner of the same
   state and would go stale the moment the user changed views without a reload. */

/* Related (same-era) cards: left-aligned like the prototype, not centered. */
.bb-app .bb-related-card--athlete {
    text-align: left;
    align-items: flex-start;
}

@media (max-width: 640px) {
    .bb-app .bb-record-row__stats { gap: var(--bb-space-3); }
    .bb-app .bb-record-stat__num { font-size: 1.4rem; }
    .bb-app .bb-missing-band__actions { margin-left: 0; }
}

/* The timeline canvas keeps its own white card. Flattening the section wrappers
   took the surface from under the dots, and the prototype draws exactly this
   module - not the section - as a card.

   Surface properties ONLY - no padding. This element is also the horizontal
   scroller, and its base rule's space-8 TOP padding is the headroom that keeps
   dot tooltips inside the scrollport. A uniform card padding here shrank that
   headroom by 12px and clipped the first-row tooltips at 768 - caught by
   test-athlete-timeline-layout across six athletes. */
.bb-app .bb-career-timeline {
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
}

/* Career milestones row: moved out of the timeline strip, which now carries
   years and result dots only, as claude-design does. Inside the columns these
   were ~100px pills in 36px slots - they overlapped each other on consecutive
   seasons and covered result dots on short careers. Nothing is lost: the same
   label/year pairs read better as a row, and the strip got its clarity back. */
.bb-app .bb-career-milestones {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-3) var(--bb-space-6);
    margin: var(--bb-space-4) 0 0;
    padding: var(--bb-space-3) var(--bb-space-4);
    background: var(--bb-tint);
    border-radius: var(--bb-radius);
}
.bb-app .bb-career-milestone {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    min-width: 0;
}
.bb-app .bb-career-milestone__label {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--bb-warm-grey-2);
    margin: 0;
    white-space: nowrap;
}
.bb-app .bb-career-milestone__year {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-base);
    font-weight: 600;
    color: var(--bb-ink);
    margin: 0;
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Full-bleed page width
   --------------------------------------------------------------------------
   The plugin's routes were boxed by the parent theme, not by anything here:
   .rb-container caps at max-width 1280px with 80px side margins, so at 1440 the
   app rendered 1240px wide inset 100px a side. claude-design runs its pages
   near the full viewport with a ~40px gutter.

   Unclamping the ancestors with :has() rather than a 100vw breakout on .bb-app.
   The usual `margin-inline: calc(50% - 50vw)` trick measures 100vw INCLUDING the
   vertical scrollbar, so it hands back exactly the 15px of horizontal overflow
   this plugin has spent a whole audit driving to zero. Releasing the cap has no
   such side effect, and it only fires on pages that actually contain .bb-app -
   the theme's own header, footer and non-plugin pages keep their layout.
   ========================================================================== */
/* The theme's own width is respected: .rb-container, .grid-container and .s-ct
   are left exactly as the theme sets them. An earlier attempt released those
   caps to reach the viewport edge, which is not what "full width" meant - the
   page should fill the column the theme hands it, not escape it.

   What is corrected is the plugin narrowing itself INSIDE that column: the app
   received 1240px at a 1440 viewport and then .bb-app .bb-container re-boxed it
   to 1192 with 84px of its own margin, so the design ran ~116px narrower than
   the space available. That cap is removed above; no gutter is added here,
   because the theme already supplies one. */

/* ==========================================================================
   Section heading tiers, measured off claude-design
   --------------------------------------------------------------------------
   The prototype runs three tiers, not one:

     32px + 2px rule   a primary section standing over a table or strip
     28px, no rule     a secondary section
     22-24px, no rule  a title INSIDE a card, where the card edge already
                       does the separating and a rule would double it

   Everything here was 32px with a 2px rule, so a card title shouted as loudly
   as the page's main sections and every block carried the same spine. Matching
   the tiers is most of what makes the prototype read as composed rather than
   as a stack of equal-weight boxes.
   ========================================================================== */

/* Secondary section: related athletes. These two headings are bare
   .bb-section-title with no .bb-section-head wrapper, so the 2px spine comes
   from the title rule itself and has to be cleared on the heading. */
.bb-app .bb-athlete-profile-page #bb-related-heading {
    /* Was 1.75rem (28px), which I picked by eye during the profile pass before
       measuring the prototypes. 28 is on no tier; the secondary tier is 26. */
    font-size: var(--bb-fs-26);
    border-bottom: none;
    padding-bottom: 0;
}

/* Division breakdown is a CARD in the prototype, with a quiet title inside it.
   The section flatten took every profile section down to bare page; this one
   the prototype keeps boxed. */
.bb-app .bb-athlete-profile-page .bb-profile-section--divisions {
    background: var(--bb-paper, #ffffff);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
    padding: var(--bb-space-5);
}
.bb-app .bb-athlete-profile-page #bb-divisions-heading {
    /* Same rem trap: 1.375rem is 20.6px against a 15px root, so this ID rule
       pulled the profile's section heading a pixel under the 22 tier. */
    font-size: var(--bb-fs-22);
    border-bottom: none;
    padding-bottom: 0;
    margin-bottom: var(--bb-space-4);
}

/* "Showing 15 of 71 recorded results. Load full history" - the prototype's own
   footer under a truncated table. Mono count, oxblood action, hairline above. */
.bb-app .bb-results-more {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
    margin: 0;
    padding: var(--bb-space-3) var(--bb-space-4);
    border-top: 1px solid var(--bb-border);
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-xs);
    color: var(--bb-warm-grey-2);
}
.bb-app .bb-results-more__link {
    color: var(--bb-accent);
    font-weight: 600;
    text-decoration: none;
}
.bb-app .bb-results-more__link:hover,
.bb-app .bb-results-more__link:focus-visible { text-decoration: underline; }
.bb-app .bb-results-more__link { cursor: pointer; }

/* ==========================================================================
   Results view + disclosure, driven by CSS instead of by page loads
   --------------------------------------------------------------------------
   Every row of the career is in the canonical HTML. What used to be three link
   variants (?results=wins, ?results=olympia, ?full=1) is now a radio group and
   a checkbox reaching the table through the sibling combinator.

   Why not JavaScript: filters and pagination have to work with JS disabled, and
   a scripted control would look right and fail that. Why it matters beyond the
   URL: the old ?full=1 canonicals back to the clean URL, so the indexed page
   held 15 of 71 results and the rest lived where nothing could index them.
   ========================================================================== */

/* Focusable but not visible. display:none would drop them from the tab order
   and the accessibility tree, which would make the whole control keyboard-dead. */
.bb-app .bb-results-state {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* The label carries the checked and focus styling, since the input it belongs
   to is the thing that actually holds state but is not the thing on screen. */
.bb-app #bb-view-all:checked     ~ .bb-section-head label[for="bb-view-all"],
.bb-app #bb-view-wins:checked    ~ .bb-section-head label[for="bb-view-wins"],
.bb-app #bb-view-olympia:checked ~ .bb-section-head label[for="bb-view-olympia"] {
    background: var(--bb-ink);
    border-color: var(--bb-ink);
    color: var(--bb-on-dark);
}
.bb-app #bb-view-all:focus-visible     ~ .bb-section-head label[for="bb-view-all"],
.bb-app #bb-view-wins:focus-visible    ~ .bb-section-head label[for="bb-view-wins"],
.bb-app #bb-view-olympia:focus-visible ~ .bb-section-head label[for="bb-view-olympia"],
.bb-app #bb-results-expand:focus-visible ~ .bb-results-more .bb-results-more__link {
    outline: 2px solid var(--bb-accent);
    outline-offset: 2px;
}

/* Truncation, per view. The rank is precomputed in PHP: once the non-wins are
   hidden, no selector can work out which row is the 16th win. */
.bb-app #bb-view-all:checked     ~ .bb-results-body tbody tr.bb-over-all,
.bb-app #bb-view-wins:checked    ~ .bb-results-body tbody tr.bb-over-wins,
.bb-app #bb-view-olympia:checked ~ .bb-results-body tbody tr.bb-over-olympia {
    display: none;
}
/* Expanded. Each rule is gated on its own view, and .bb-over-{view} is only ever
   set on rows that belong to that view, so re-showing them can never leak a row
   the active filter excludes. */
.bb-app #bb-view-all:checked     ~ #bb-results-expand:checked ~ .bb-results-body tbody tr.bb-over-all,
.bb-app #bb-view-wins:checked    ~ #bb-results-expand:checked ~ .bb-results-body tbody tr.bb-over-wins,
.bb-app #bb-view-olympia:checked ~ #bb-results-expand:checked ~ .bb-results-body tbody tr.bb-over-olympia {
    display: table-row;
}

/* The view filter itself. Lower specificity than the expand rules above, which
   is harmless: those only ever match rows already inside the active view. */
.bb-app #bb-view-wins:checked    ~ .bb-results-body tbody tr:not(.bb-r--wins),
.bb-app #bb-view-olympia:checked ~ .bb-results-body tbody tr:not(.bb-r--olympia) {
    display: none;
}

/* One count line per view; the active one is revealed. A shared line could not
   be honest - "15 of 71" is right for the career and wrong for the Olympia tab. */
.bb-app .bb-results-more { display: none; }
.bb-app #bb-view-all:checked     ~ .bb-results-more--all,
.bb-app #bb-view-wins:checked    ~ .bb-results-more--wins,
.bb-app #bb-view-olympia:checked ~ .bb-results-more--olympia {
    display: flex;
}
.bb-app .bb-results-more__count--expanded,
.bb-app .bb-results-more__link--collapse { display: none; }
.bb-app #bb-results-expand:checked ~ .bb-results-more .bb-results-more__count--collapsed,
.bb-app #bb-results-expand:checked ~ .bb-results-more .bb-results-more__link--expand { display: none; }
.bb-app #bb-results-expand:checked ~ .bb-results-more .bb-results-more__count--expanded,
.bb-app #bb-results-expand:checked ~ .bb-results-more .bb-results-more__link--collapse { display: inline; }

/* ==========================================================================
   Profile polish pass: hero+nav as one unit, results table, section rhythm
   Values measured off claude-design, not chosen.
   ========================================================================== */

/* --- Hero and jump nav are one object ------------------------------------
   The nav is the hero's bottom edge in the prototype. It had a bottom margin
   and the confidence bar was printed between the two, so the dark band read as
   a detached toolbar. The bar now follows the nav (see profile.php) and the
   seam is closed here. */
.bb-app .bb-athlete-profile-page .bb-profile-header {
    margin-bottom: 0;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}
.bb-app .bb-athlete-profile-page .bb-section-nav {
    margin-top: 0;
    margin-bottom: var(--bb-space-5);
    border-top: none;
    border-radius: 0 0 var(--bb-radius-md) var(--bb-radius-md);
}
/* Sits under the joined block, not between its halves. */
.bb-app .bb-athlete-profile-page .bb-data-trust-bar {
    margin-top: 0;
    margin-bottom: var(--bb-space-6);
}

/* --- Results table ------------------------------------------------------
   proto: header band on tint, 10px mono uppercase at 1.6px tracking;
   rows 55px on a 64px / 1fr / auto / 92px grid, 14px 20px padding, hairline
   rule; year 13px mono 500, contest 15.5px Archivo 600, division 13px 400. */
.bb-app .bb-profile-section--results .bb-content-table {
    border-collapse: collapse;
    width: 100%;
}
/* The profile-only header override is gone. It existed solely to out-!important
   a global rule that painted the wrong colour; that global now carries the right
   one, so this table gets the house spec like every other. What remains here is
   only the alignment and the transparent cell background, which are genuinely
   local to a results table. */
.bb-app .bb-profile-section--results thead th {
    text-align: left;
    border-bottom: none;
}
.bb-app .bb-profile-section--results tbody td {
    vertical-align: middle;
    background: transparent;
}
.bb-app .bb-profile-section--results tbody tr:last-child td { border-bottom: none; }

.bb-app .bb-results-cell--year {
    width: 84px;
    font-family: var(--bb-font-mono);
    font-size: 13px;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    color: var(--bb-warm-grey);
}
.bb-app .bb-results-cell--contest,
.bb-app .bb-results-cell--contest a {
    font-size: 0.97rem;
    font-weight: 600;
    color: var(--bb-ink);
    text-decoration: none;
}
.bb-app .bb-results-cell--contest a:hover,
.bb-app .bb-results-cell--contest a:focus-visible { text-decoration: underline; }
.bb-app .bb-results-cell--division,
.bb-app .bb-results-cell--division a {
    font-size: 13px;
    font-weight: 400;
    color: var(--bb-warm-grey);
    text-decoration: none;
}
.bb-app .bb-results-cell--division a:hover,
.bb-app .bb-results-cell--division a:focus-visible { text-decoration: underline; }
.bb-app .bb-results-cell--place {
    width: 96px;
    text-align: left;
    white-space: nowrap;
}

/* A win gets the oxblood chip; 2nd and 3rd a quiet one; everything else stays
   plain text so the podium reads at a glance. */
.bb-app .bb-place-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    padding: 6px 10px;
    border-radius: var(--bb-radius-sm);
    font-family: var(--bb-font-mono);
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.bb-app .bb-place-chip--win {
    background: var(--bb-accent);
    color: var(--bb-on-dark);
}
.bb-app .bb-place-chip--podium {
    background: var(--bb-tint);
    color: var(--bb-ink);
}
.bb-app .bb-place-plain {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--bb-warm-grey-2);
    padding-left: 10px;
}
/* The winner row previously took a tinted background; the chip now carries that
   signal, and two cues on one row made the table look striped at random. */
.bb-app .bb-profile-section--results tr.bb-winner-row td { background: transparent; }

/* Section rhythm on the 48px step, matching the neighbouring hub sections
   rather than inheriting whatever the previous block left behind. */
.bb-app .bb-reigning-section {
    margin: 48px 0;
}

/* --- Reigning champions strip (hub) -------------------------------------
   Eleven current title holders as a plain ledger: division label in mono
   above the name, no cards and no avatars. The GOAT board below it already
   carries portrait weight, and two photo grids in one column would read as
   the same module twice. */
.bb-app .bb-reigning-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
    gap: 2px 32px;
    margin: 0;
    padding: 0;
    list-style: none;
}
.bb-app .bb-reigning-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 0;
    border-bottom: 1px solid var(--bb-border);
}
/* 11px / 400 / 0.16em mono is the plugin's one eyebrow spec, enforced by
   test-type-scale-conformance. This shipped at 500 / 0.06em and was the only
   eyebrow on the hub that did not match the other four. */
.bb-app .bb-reigning-division {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-warm-grey-2);
}
/* min-height, not padding: the row already has its own vertical padding, and the
   LINK is the tap target. At 22px it failed the 24px floor on eleven controls. */
.bb-app .bb-reigning-name {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    gap: 8px;
    font-size: 0.97rem;
    font-weight: 600;
    color: var(--bb-ink);
    text-decoration: none;
    text-align: right;
}
.bb-app .bb-reigning-name:hover,
.bb-app .bb-reigning-name:focus-visible {
    color: var(--bb-accent);
    text-decoration: underline;
}
.bb-app .bb-reigning-flag {
    flex: 0 0 auto;
    border-radius: 2px;
}

/* Who won the division. Sits at the same weight as the division cell, not the
   contest cell: it is context for the placing, and a column of bold athlete
   names would compete with the contest column for the row's focus. */
.bb-app .bb-results-cell--wonby,
.bb-app .bb-results-cell--wonby a {
    font-size: 13px;
    font-weight: 400;
    color: var(--bb-warm-grey);
    text-decoration: none;
}
.bb-app .bb-results-cell--wonby a:hover,
.bb-app .bb-results-cell--wonby a:focus-visible {
    color: var(--bb-accent);
    text-decoration: underline;
}
/* The athlete's own win. Mono and quiet: the oxblood chip in the Place cell
   already carries the signal, so repeating the emphasis here would say the
   same thing twice on one row. */
.bb-app .bb-wonby-self {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-warm-grey-2);
}

/* --- Section rhythm -----------------------------------------------------
   One spacing value between sections instead of each block bringing its own,
   and one gap under a ruled heading. */
.bb-app .bb-athlete-profile-page .bb-profile-section,
.bb-app .bb-athlete-profile-page .bb-stats-box,
.bb-app .bb-athlete-profile-page .bb-community-bio-band {
    margin-bottom: var(--bb-space-10);
}
.bb-app .bb-athlete-profile-page .bb-section-head { margin-bottom: var(--bb-space-5); }
.bb-app .bb-athlete-profile-page .bb-section-title { margin-top: 0; }

/* --- Every season on record --------------------------------------------- */
/* The peak-year pill is a caption for the strip, not a control: quiet it and
   tie it to the card below rather than floating it as a button. */
.bb-app .bb-athlete-profile-page .bb-timeline-peak {
    display: inline-flex;
    align-items: baseline;
    gap: var(--bb-space-2);
    margin: 0 0 var(--bb-space-3);
    padding: 0;
    background: transparent;
    border: none;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--bb-warm-grey-2);
}
/* Legend sits INSIDE the timeline card, under the strip it explains, separated
   by a hairline - a key to the dots above it rather than loose page content.
   Metrics are claude-design's: gap 12/20, 22px above the rule, 16px below it,
   12px mono on #5a524a, 11px swatches. It stays in the card's content box, so
   the rule is inset by the card padding exactly as the prototype draws it - an
   earlier negative margin bled it to the card edges and read as a divider
   between two blocks rather than a key attached to the strip. */
.bb-app .bb-career-timeline-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-3) var(--bb-space-5);
    margin: var(--bb-space-5) 0 0;
    padding: var(--bb-space-4) 0 0;
    border-top: 1px solid var(--bb-border);
    font-family: var(--bb-font-mono);
    letter-spacing: 0.06em;
    color: var(--bb-warm-grey);
}
.bb-app .bb-career-timeline-legend-item {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-warm-grey);
}
.bb-app .bb-career-timeline-legend-dot {
    width: 11px;
    height: 11px;
}

@media (max-width: 640px) {
    .bb-app .bb-profile-section--results thead th,
    .bb-app .bb-profile-section--results tbody td { padding: 10px 12px; }
    .bb-app .bb-results-cell--year { width: 62px; }
    .bb-app .bb-results-cell--place { width: 76px; }
}

/* The profile-scoped padding-top override is gone. It existed to claw back the
   80px of tooltip headroom the base rule reserved; the base rule now carries
   claude-design's own 26px and the tooltip flips instead of reserving, so a
   second owner for this one value would only drift from the first. */

/* ==========================================================================
   ONE EYEBROW SPEC
   --------------------------------------------------------------------------
   Measured 2026-08-01 across 14 live routes: 136 mono-uppercase labels were
   off spec against 29 on it - 82% drift - spread over 25 class/spec pairs.
   Weights ran 400/500/600/700 and tracking 0.88 / 1.1 / 1.32 / 1.76 / 1.98 /
   2.42px for what is one thing: a small tracked label above a value.

   .bb-eyebrow already carried the right spec. The drift came from each new
   component declaring its own label from scratch instead of reaching for it,
   so this folds them onto the single definition rather than adding a 26th.

   11px where claude-design measures 10: the plugin's own type-scale floor gate
   rejects anything under 11, and shipping text the project calls too small to
   read is not worth matching a mockup exactly. Tracking is 0.16em, which is
   what keeps it legible once the size is fixed.

   Deliberately NOT folded in, because they are not labels: .bb-section-nav__link
   and .bb-tabs__tab are navigation controls, .bb-sort-icon is an icon, and
   .bb-record-row__series / .bb-olympia-hub-year are data values.
   ========================================================================== */
.bb-app .bb-olympia-hero-stat-label,
.bb-app .bb-olympia-hero-eyebrow,
.bb-app .bb-olympia-hub-unit-label,
.bb-app .bb-olympia-hub-pill-label,
.bb-app .bb-rival-split__label,
.bb-app .bb-data-category,
.bb-app .bb-method-card__label,
.bb-app .bb-record-stat__label,
.bb-app .bb-profile-glance-label,
.bb-app .bb-profile-glance-title,
.bb-app .bb-profile-detail-label,
.bb-app .bb-career-milestone__label,
.bb-app .bb-status-bar__label,
.bb-app .bb-timeline-peak-label,
.bb-app .bb-timeline-peak-value,
/* The SSR fact lists mark their term up as a bare <dt>. Contest detail gives it
   .bb-eyebrow and Olympia detail does not, so the same row read at two weights
   on two pages. */
.bb-app .bb-stats-box-kicker,
/* Beats the later .bb-settle-fact dt rule on specificity; a bare .bb-app dt
   ties with it and loses on source order. */
.bb-app .bb-settle-fact dt,
/* Every <dt> inside the app is a label by definition - that is what the element
   means - so scope it to the app rather than naming each fact list and missing
   the next one. */
.bb-app dt {
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 400;
    line-height: 1.3;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}

/* ==========================================================================
   SECTION HEADING TIERS
   --------------------------------------------------------------------------
   claude-design runs four, measured across all 15 prototypes:

     32px  -0.02em   primary section heading, standing over a table or strip
     26px  -0.018em  secondary section ("How these titles are counted")
     24px  normal    a repeated card/row heading inside a list
     22px  -0.016em  minor block

   The plugin had twelve distinct H2 sizes. Most of the count came from two
   places, not from broad drift:

   - .bb-olympia-year-heading rendered at 30px x61 on the Olympia index. The
     prototype sets those year rows at 24 - they are card headings repeated down
     a list, and at 30 each one shouted as loudly as the page's own H2.
   - .bb-seo-heading at 20px and the two card titles at 16px sat below every
     tier the prototype has.

   Set here rather than at each definition because these are scattered across
   the file and the point is that they now share one source; fixing them in
   place would have left four more values free to drift apart again.
   ========================================================================== */
.bb-app .bb-olympia-year-heading {
    font-size: var(--bb-fs-xl);
    letter-spacing: normal;
}
.bb-app .bb-seo-heading,
.bb-app .bb-see-also-title {
    font-size: var(--bb-fs-26);
    letter-spacing: -0.018em;
}
.bb-app .bb-embed-kit__title,
.bb-app .bb-methodology-title {
    font-size: var(--bb-fs-22);
    letter-spacing: -0.016em;
}

/* An H2 the plugin never classed fell through to the parent theme's 1.6rem
   (25.6px) or 1.75rem (28px) - neither of which is a tier. Landing them on the
   secondary tier means new markup is on the scale by default instead of
   inheriting whatever the theme happens to set. Every classed heading above has
   higher specificity, so this only catches what nothing else claims. */
.bb-app h2 {
    font-size: var(--bb-fs-26);
    letter-spacing: -0.018em;
}

/* ==========================================================================
   ONE TABLE SPEC
   --------------------------------------------------------------------------
   Measured 2026-08-01 across 12 routes: 8 visible tables on 3 distinct specs.
   Two of those were the same table drawn twice - a house spec at 12/18 padding
   and the profile results table at 12/20 - because the profile had to fork to
   escape an !important on the global header colour.

   claude-design contains no <table> at all; it builds these lists with grid. So
   the reference is the profile results table, whose values were measured off the
   prototype's rendered rhythm: 12/20 header, 14/20 cell, hairline rows, 11px
   mono at 0.16em on --bb-tint.

   .bb-chart__table is deliberately excluded: it is the 0x0 no-JS and
   screen-reader fallback inside .bb-chart__fallback, not a table anyone sees.
   ========================================================================== */
.bb-app .bb-table thead th,
.bb-app .bb-content-table thead th,
.bb-app .bb-rankings-table thead th,
.bb-app .bb-data-table thead th,
.bb-app .bb-results-table thead th {
    padding: 12px 20px;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    text-align: left;
}
.bb-app .bb-table tbody td,
.bb-app .bb-content-table tbody td,
.bb-app .bb-rankings-table tbody td,
.bb-app .bb-data-table tbody td,
.bb-app .bb-results-table tbody td {
    padding: 14px 20px;
    border-bottom: 1px solid rgba(34, 28, 24, 0.1);
}

@media (max-width: 640px) {
    .bb-app .bb-table thead th,
    .bb-app .bb-content-table thead th,
    .bb-app .bb-rankings-table thead th,
    .bb-app .bb-data-table thead th,
    .bb-app .bb-results-table thead th,
    .bb-app .bb-table tbody td,
    .bb-app .bb-content-table tbody td,
    .bb-app .bb-rankings-table tbody td,
    .bb-app .bb-data-table tbody td,
    .bb-app .bb-results-table tbody td { padding: 10px 12px; }
}

/* ==========================================================================
   FOLLOW BUTTON STATE
   --------------------------------------------------------------------------
   Reported as: clicking it gives no idea whether it worked. It didn't. The
   controller set aria-pressed and nothing else, and the only visible difference
   between the two states was the outline button's own hover tint - an 8% alpha
   shift on a dark hero. Screen readers got the state; eyes did not.

   The label now says "Follow" / "Following" (bb-ui.js), and the followed state
   fills rather than outlines, so the two read as different objects at a glance
   instead of the same object slightly lighter.
   ========================================================================== */
.bb-app .bb-btn--follow {
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
/* Four classes deep because the hero styles its outline buttons at three, and a
   two-class rule lost the fill silently - the label and icon changed while the
   button stayed the same colour. Specificity, not !important: the hero rule is
   correct for every OTHER button in that row, so it should keep winning there. */
/* Scoped through .bb-action-row because that is the rule being answered: the
   hero's action row paints every button in it a 6%-alpha bone, which is correct
   for Share and Compare and wrong for a Follow button that is switched on. The
   colour !important matches the one already on that rule - it is the only way to
   answer an existing !important, and the action row set colour that way first. */
.bb-app .bb-action-row .bb-btn--follow.is-following,
.bb-app .bb-btn--follow.is-following {
    background: var(--bb-accent);
    border-color: var(--bb-accent);
    color: var(--bb-on-dark) !important;
}
/* Hovering a FOLLOWED button used to hand it back to the action row's generic
   hover, which lightens to a 14% bone tint - so pointing at it made it look
   unfollowed. Specificity has to clear .bb-app .bb-action-row .bb-btn:hover
   :not(:disabled), which is five. Deepens rather than lightens, so the button
   stays obviously "on" while offering the click that turns it off. */
.bb-app .bb-action-row .bb-btn--follow.is-following:hover:not(:disabled),
.bb-app .bb-action-row .bb-btn--follow.is-following:focus-visible:not(:disabled) {
    background: var(--bb-oxblood, #8f2d23);
    border-color: var(--bb-oxblood, #8f2d23);
    color: var(--bb-on-dark) !important;
}
.bb-app .bb-btn--follow.is-following svg {
    /* A filled heart for a followed athlete: the outline/fill pair carries the
       state even where colour alone would not, which is the point of not
       leaning on colour for meaning. */
    fill: currentColor;
}
.bb-app .bb-btn--follow:active {
    transform: translateY(1px);
}
/* In flight. The control is disabled during the write, so it must not simply
   look broken while it waits. */
.bb-app .bb-btn--follow[aria-busy="true"] {
    opacity: 0.7;
    cursor: progress;
}
@media (prefers-reduced-motion: reduce) {
    .bb-app .bb-btn--follow { transition: none; }
    .bb-app .bb-btn--follow:active { transform: none; }
}

/* ==========================================================================
   AUTOCOMPLETE RESULT ROWS
   --------------------------------------------------------------------------
   The combobox semantics were already right - role, aria-expanded,
   aria-controls, aria-activedescendant, 44px rows. What was missing was the
   ability to TELL THE ROWS APART: searching "coleman" returned ten rows reading
   only "... Coleman", and the active row was marked by text colour alone, which
   is a colour-only affordance and the one thing the state rules say not to do.
   ========================================================================== */
/* Stacked, not side by side. The header dropdown is only as wide as the search
   field (~215px), so a right-aligned meta column had nowhere to go: it wrapped
   under the name anyway and then clipped mid-word because it was nowrap. One
   column truncates predictably at any width. */
.bb-app .bb-search-result__link,
.bb-app .bb-search-result {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
}
.bb-app .bb-search-result__link {
    width: 100%;
    text-decoration: none;
    color: inherit;
}
.bb-app .bb-search-result__name {
    font-weight: 600;
    color: var(--bb-ink);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Mono so the meta reads as data beside a name set in Archivo. */
.bb-app .bb-search-result__meta {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    letter-spacing: 0.04em;
    color: var(--bb-warm-grey-2);
}
/* The active row gets a tint AND an oxblood edge, so it is not carried by
   colour alone. aria-selected is the source of truth rather than a class, since
   the controller already maintains it for assistive tech. */
.bb-app .bb-search-result[aria-selected="true"],
.bb-app .bb-search-result:hover {
    background: var(--bb-tint);
    box-shadow: inset 3px 0 0 0 var(--bb-accent);
}
.bb-app .bb-search-result[aria-selected="true"] .bb-search-result__name,
.bb-app .bb-search-result:hover .bb-search-result__name {
    color: var(--bb-accent);
}

/* ==========================================================================
   DIVISIONS: gender filter without a page load
   --------------------------------------------------------------------------
   The Men/Women tabs were <a href="?gender=M"> links, so filtering TWELVE cards
   that are already on the page cost a full round trip and put in-page state
   into the URL. Radios now drive it; ?gender= is still honoured server-side and
   only decides which radio starts checked, so existing links still work.
   ========================================================================== */
.bb-app .bb-division-gender-state {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}
.bb-app #bb-div-gender-m:checked ~ * .bb-division-card[data-gender="F"],
.bb-app #bb-div-gender-f:checked ~ * .bb-division-card[data-gender="M"] {
    display: none;
}
/* The active tab is whichever radio is checked, so no PHP-stamped class can go
   stale the moment a user switches without a reload. */
.bb-app #bb-div-gender-all:checked ~ .bb-tabs label[for="bb-div-gender-all"],
.bb-app #bb-div-gender-m:checked   ~ .bb-tabs label[for="bb-div-gender-m"],
.bb-app #bb-div-gender-f:checked   ~ .bb-tabs label[for="bb-div-gender-f"] {
    background: var(--bb-ink);
    border-color: var(--bb-ink);
    color: var(--bb-on-dark);
}
.bb-app #bb-div-gender-all:focus-visible ~ .bb-tabs label[for="bb-div-gender-all"],
.bb-app #bb-div-gender-m:focus-visible   ~ .bb-tabs label[for="bb-div-gender-m"],
.bb-app #bb-div-gender-f:focus-visible   ~ .bb-tabs label[for="bb-div-gender-f"] {
    outline: 2px solid var(--bb-accent);
    outline-offset: 2px;
}
.bb-app .bb-tabs label.bb-tab { cursor: pointer; }

/* ==========================================================================
   BACKGROUND-PAINTING SECTIONS: separation and edge alignment
   --------------------------------------------------------------------------
   Two defects, both visible on the hub, both measured 2026-08-02:

   1. WIDTH - investigated and NOT a defect. The tinted bands render 1240px
      against their neighbours' 1192 because they carry margin-left/right:-24px,
      deliberately bleeding to the edges of .bb-container, then pad 24px back in
      so their TEXT still aligns with every other section. Removing that padding
      to "fix" the width was an over-correction: it left the bleed in place and
      pushed the band's text 24px out of alignment with the rest of the page.
      The band being wider than the content column is the design; only its
      spacing was wrong.

   2. GAP - the real defect. Separation between sections is now the NEXT section's top padding
      ("one gap per boundary"). That works for a transparent section, where the
      padding is empty space. It fails for a section that paints, because the
      padding sits INSIDE the paint - so the tint starts flush against the
      previous section's last line and the 64px of air appears inside the colour
      instead of before it. Margin sits outside the paint, so it is what a
      painted section needs. This one was introduced by the rhythm change in
      13d7cc4f; before that the predecessor's bottom padding was doing the job.
   ========================================================================== */
.bb-app .bb-data-section,
.bb-app .bb-seo-section,
.bb-app .bb-about-section {
    /* Separation from the section above, OUTSIDE the paint. */
    margin-top: clamp(32px, 6vw, var(--bb-space-16));
    /*
     * Breathing room INSIDE the paint. The one-gap-per-boundary change set
     * padding-bottom to 0 everywhere, which is right for a transparent section -
     * there the padding is just empty space and the next section's top padding
     * supplies the gap. On a painted section the bottom padding is the only
     * thing between the last line of text and the edge of the colour, so zeroing
     * it made the tint stop flush against the descenders and read as clipped
     * text. Measured before this: 0px of gap under the last line, against 20-28px
     * on every tinted block that was not caught by that change.
     */
    padding-bottom: clamp(24px, 3vw, var(--bb-space-10));
    /*
     * Edges line up with the sections above and below. These bands carried
     * margin-left/right:-24px with 24px of padding back in, so the tint sat 24px
     * proud of the content column on each side - 1240px against everything
     * else's 1192. Their TEXT aligned, so it was not a text bug, but a 24px
     * overhang reads as a misaligned block rather than as a deliberate band,
     * which is exactly how it was reported. A band that is not full-bleed should
     * share an edge with its neighbours.
     */
    margin-left: 0;
    margin-right: 0;
    padding-left: 0;
    padding-right: 0;
}

/* ==========================================================================
   CARD TEXT MUST STAY INSIDE ITS CARD
   --------------------------------------------------------------------------
   On the hub's GOAT cards a division badge rendered 162px wide inside an 84px
   parent and simply hung out of the card - "Men's Open Bodybu" with the rest
   over the neighbouring card. The badge is white-space:nowrap and its container
   is a flex item with min-width:0, so the container shrinks and the badge, which
   cannot, overflows by up to 79px. Athlete names did the same by up to 21px.

   No document overflow is produced by any of this, which is why every earlier
   sweep reported these routes clean: a child spilling out of its PARENT is
   invisible to a documentElement.scrollWidth check.

   Truncation rather than wrapping: these sit in fixed-height card rows, so
   wrapping a long division name would push the card's own layout instead.
   ========================================================================== */
.bb-app .bb-athlete-meta,
.bb-app .bb-athlete-info {
    min-width: 0;
    max-width: 100%;
}
.bb-app .bb-athlete-meta .bb-badge,
.bb-app .bb-athlete-info .bb-athlete-name {
    display: inline-block;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

/* ==========================================================================
   SECTIONS THAT NEVER JOINED THE RHYTHM
   --------------------------------------------------------------------------
   Measured across nine routes: these five carry under 8px of combined top
   padding and margin, so each one starts flush against whatever precedes it.
   On the hub, .bb-settle-section's "SETTLED BY THE RECORD" eyebrow sat 0px
   below the last row of GOAT cards and read as a collision.

   They were simply never added to the shared rhythm selector list, so every
   pass that fixed section spacing fixed it around them.
   ========================================================================== */
.bb-app .bb-settle-section,
.bb-app .bb-odds-board,
.bb-app .bb-odds-movers,
.bb-app .bb-rto-panel,
.bb-app .bb-rto-division-block {
    margin-top: clamp(32px, 6vw, var(--bb-space-16));
}

/* A long unbroken token - an API header name, a query string, a slug - has no
   break opportunity, so the line box grows past its container and the list item
   renders wider than the list. Measured on /api/: an <li> 838px wide inside a
   487px <ul>, overflowing by 351px. Breaking anywhere is correct for technical
   strings; normal prose still breaks on spaces first. */
.bb-app .bb-starter-list li,
.bb-app .bb-starter-list code,
.bb-app .bb-api-endpoint code {
    min-width: 0;
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* ==========================================================================
   NARROW-VIEWPORT CONTAINMENT
   --------------------------------------------------------------------------
   The remaining bleeds from the 49-route sweep were all at 390px and all the
   same shape: a flex or grid item defaults to min-width:auto, which is
   min-content, so it refuses to shrink below its widest unbreakable run and
   pushes past its container instead. None produced document overflow, which is
   why five widths of responsive checking called every one of these clean.
   ========================================================================== */
.bb-app .bb-table__col-place,
.bb-app .bb-table__col-country,
.bb-app .bb-timeline-labels,
.bb-app .bb-methodology-toggle,
.bb-app .bb-compare-selectors,
.bb-app .bb-cat-hero__top {
    min-width: 0;
    flex-wrap: wrap;
}
.bb-app .bb-table__col-place > *,
.bb-app .bb-table__col-country > *,
.bb-app .bb-methodology-toggle > *,
.bb-app .bb-compare-selectors > *,
.bb-app .bb-cat-hero__top > * {
    min-width: 0;
    max-width: 100%;
}
/* The year labels under the compare timeline are a fixed-pitch row; let it
   scroll rather than spill, the way the career strip already does. */
.bb-app .bb-timeline-labels {
    overflow-x: auto;
    scrollbar-width: thin;
}

@media (max-width: 480px) {
    /* The profile hero and its sticky nav are full-bleed by design on desktop.
       At 390 the bleed exceeded the viewport by up to 17px, so it is released
       here rather than removed. */
    .bb-app .bb-athlete-profile-page .bb-profile-header,
    .bb-app .bb-athlete-profile-page .bb-section-nav {
        margin-left: 0;
        margin-right: 0;
        max-width: 100%;
    }
}

/* Section header action, on the rule beside the heading.
 *
 * The prototype (Hub.dc.html:563-567) makes the header row a flex line with
 * align-items: flex-end and pushes the action with margin-left: auto, so the
 * link sits on the 2px ink rule level with the heading's baseline.
 *
 * float: right cannot reach that position. The action is out of flow, so the
 * block after it starts at the same y and the link lands beside the first card
 * instead of in the header - measured on the hub, the contests list rendered
 * 116px narrower with the button level with row one.
 *
 * Scoped with :has() so it only applies to the two headers that carry an
 * action. Every other .bb-section-header stays display: block, which is what
 * keeps the eyebrow on the heading's left edge (see the note at the
 * .bb-app .bb-section-header block above).
 */
.bb-app .bb-section-header:has(.bb-section-header-action) {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 20px;
}
.bb-app .bb-section-header:has(.bb-section-header-action) > * + * {
    margin-top: 0;
}
.bb-app .bb-section-header-text {
    flex: 1 1 auto;
    min-width: 0;
}
.bb-app .bb-section-header-text > * + * {
    margin-top: 8px;
}
.bb-app .bb-section-header .bb-section-header-action {
    flex: 0 0 auto;
    margin-left: auto;
}

/* ---- Dark band width ----------------------------------------------------
 * claude-design outdents its ink band 32px past the text column (content 1240,
 * ink section x=68 w=1304 via margin: 0 -32px). That bleed is NOT carried here,
 * by owner decision 2026-08-02, and the reason is that it does not transfer:
 * in the prototype -32px exactly consumes the shell's clamp(18px,4vw,32px)
 * padding, so the band lands flush with the shell edge. Foxiz gives .bb-app a
 * 100px gutter at 1440, so the same -32px ends at x=68 and aligns with nothing -
 * it reads as an overhang, which is how it was reported.
 *
 * Every band therefore sits at 1240. The 48px narrowing that this section
 * originally fixed (bands were 1192 inside a 1240 .bb-app) stays fixed; only
 * the outdent is dropped.
 */

/* ---- Controls inherit the brand face -----------------------------------
 * claude-design carries `input, button, select { font-family: inherit }` in its
 * global block. The plugin had no equivalent, so any control it did not style
 * explicitly fell through to Foxiz's Encode Sans Condensed. Measured
 * 2026-08-02: 103 of 207 visible buttons across the 13 routes rendered the
 * theme face, 75 of them on the athlete profile alone. Inputs and selects were
 * already covered by their own component rules; buttons were not.
 */
.bb-app input,
.bb-app button,
.bb-app select,
.bb-app textarea,
.rbct .bb-app button,
.entry-content .bb-app button {
    font-family: inherit;
}

/* ---- Dark band width ----------------------------------------------------
 * claude-design outdents its ink band 32px past the text column (content 1240,
 * ink section x=68 w=1304 via margin: 0 -32px). That bleed is NOT carried here,
 * by owner decision 2026-08-02, and the reason is that it does not transfer:
 * in the prototype -32px exactly consumes the shell's clamp(18px,4vw,32px)
 * padding, so the band lands flush with the shell edge. Foxiz gives .bb-app a
 * 100px gutter at 1440, so the same -32px ends at x=68 and aligns with nothing -
 * it reads as an overhang, which is how it was reported.
 *
 * Every band therefore sits at 1240. The 48px narrowing that this section
 * originally fixed (bands were 1192 inside a 1240 .bb-app) stays fixed; only
 * the outdent is dropped.
 */

/* ---- Controls inherit the brand face -----------------------------------
 * claude-design carries `input, button, select { font-family: inherit }` in its
 * global block. The plugin had no equivalent, so any control it did not style
 * explicitly fell through to Foxiz's Encode Sans Condensed. Measured
 * 2026-08-02: 103 of 207 visible buttons across the 13 routes rendered the
 * theme face, 75 of them on the athlete profile alone. Inputs and selects were
 * already covered by their own component rules; buttons were not.
 */
.bb-app input,
.bb-app button,
.bb-app select,
.bb-app textarea,
.rbct .bb-app button,
.entry-content .bb-app button {
    font-family: inherit;
}

/* ---- Page title: a second tier, not thirteen ---------------------------
 * claude-design sizes the page title by the page's RANK: 74 on the hub, 68 on
 * Olympia, 58-64 on entity and detail pages, and 46 on the index and utility
 * pages. Live pinned every route to 64, so /contests/, /odds/, /rankings/ and
 * /tools/ rendered their title 18px (39%) larger than designed.
 *
 * This does NOT reopen the per-hero sizing that test-page-title-scale.mjs
 * guards. That test exists because thirteen h1 classes rendered the same role
 * at 32.8 / 60.5 / 72px depending on which ancestor won the cascade - accidental
 * variation. This is deliberate variation: ONE modifier, one token, applied by
 * the template that knows it is an index. Everything still resolves through a
 * --bb-fs-page-title* token, so the guard's premise holds.
 */
.bb-app .bb-page-header--compact .bb-page-title,
.bb-app .bb-page-header--compact.bb-page-header .bb-page-title {
    font-size: var(--bb-fs-page-title-compact);
}

/* The share-card preview frame is now portrait (1080x1350 poster, not the
 * landscape OG render). Scoped under .bb-app because Foxiz sets max-width on a
 * bare `figure` at (0,1,1), which beats a lone .bb-sharecard-figure at (0,1,0) -
 * measured: max-width computed to 100%, so the card rendered 1196x1495 and
 * swallowed the page. */
.bb-app .bb-sharecard-figure {
    max-width: 400px;
    aspect-ratio: 1080 / 1350;
}

/* ---- Global element layer: two gaps found by the parity audit ------------
 *
 * D1. Headings computed overflow-wrap: break-word, inherited from the theme -
 * the plugin declared nothing, and claude-design's global block says `anywhere`.
 * Not cosmetic: `anywhere` creates a soft wrap opportunity that counts toward
 * min-content, so a long unbroken heading can shrink its column; `break-word`
 * does not, and the column keeps its widest word as a floor. That is exactly the
 * mechanism behind the narrow-viewport work, so this is load-bearing.
 * Measured 2026-08-02: 222 of 223 visible headings across the 13 routes.
 *
 * D2. There was no .bb-app button:hover rule anywhere in the file, so buttons
 * the plugin had not styled individually had no hover feedback at all. The
 * pressed state at :19167 already exists and already uses an ink tint rather
 * than the prototype's neutral grey - the brief's §3 permits real CSS in place
 * of the inline-style workaround the mockups had to use - so hover matches it at
 * a lighter weight and the two now read as one progression.
 */
.bb-app h1,
.bb-app h2,
.bb-app h3 {
    overflow-wrap: anywhere;
    min-width: 0;
}

.bb-app button:hover:not(:disabled),
.bb-app select:hover:not(:disabled),
.bb-app summary:hover,
.bb-app [role="button"]:hover:not([aria-disabled="true"]) {
    box-shadow: inset 0 0 0 999px rgba(34, 28, 24, 0.06);
    cursor: pointer;
}

/* ---- Page-title tiers, set in context ----------------------------------
 * The tier redefines --bb-fs-page-title on the hero container rather than
 * targeting the h1. Thirteen different h1 classes exist across the templates
 * (bb-heading-hero, bb-profile-name, bb-event-hero__title, bb-cat-hero__title,
 * bb-vs-hero__h1, ...) and they all already read that token, so overriding it
 * one level up reaches every one of them without adding a selector per hero -
 * which is precisely the drift test-page-title-scale.mjs exists to catch.
 */
.bb-app .bb-hero,
.bb-app .bb-olympia-hero {
    --bb-fs-page-title: var(--bb-fs-page-title-hero);
}
.bb-app .bb-profile-header,
.bb-app .bb-page-header--entity {
    --bb-fs-page-title: var(--bb-fs-page-title-entity);
}
.bb-app .bb-cat-hero,
.bb-app .bb-event-hero,
.bb-app .bb-page-header--detail {
    --bb-fs-page-title: var(--bb-fs-page-title-detail);
}
.bb-app .bb-page-header--compact {
    --bb-fs-page-title: var(--bb-fs-page-title-compact);
}

/* ---- D6: the small-label roles that lost mono ---------------------------
 * The audit reported mono at 12.1% of live rendered type against the
 * prototype's 28.9% and read it as systemic. Re-measuring per ROLE rather than
 * in aggregate cut that down: the hub has no lost-mono role at all, and the
 * gap is confined to 12px meta labels on the profile and Olympia. Most of the
 * aggregate difference is content volume - live pages carry far more body prose
 * than a mockup - which is the same confound the palette layer was careful about
 * and the type layer was not.
 *
 * Only labels are listed. bb-related-desc is 12px sans and stays sans: it is a
 * sentence, and setting prose in mono is not what the prototype does either.
 */
.bb-app .bb-confidence__label,
.bb-app .bb-confidence__tip,
.bb-app .bb-data-trust-bar__date,
.bb-app .bb-data-trust-bar__report,
.bb-app .bb-state-action,
.bb-app .bb-rating__count {
    font-family: var(--bb-font-mono);
}

/* The chart's own table was the one table outside the shared table spec: its
   headers rendered 14px sans (and 12px sans uppercase for the scoped variant)
   where every other thead th in the plugin is 11px mono at 0.16em. 16 headers
   across the 13 routes. */
/* thead ONLY. Targeting every `th` also caught the chart's row headers, which
   hold athlete NAMES ("RONNIE COLEMAN") - a name is not an eyebrow, and setting
   it 11px mono uppercase both looked wrong and dragged those cells into the
   eyebrow assertion in test-type-scale-conformance, where the existing
   tbody th[scope="row"] weight of 500 then failed it. */
.bb-app .bb-chart__table thead th {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}

/* ---- Three overflows found by the verification sweep --------------------
 *
 * All three are the same mechanism as the narrow-viewport work: an element
 * that cannot shrink or wrap, inside a parent that can.
 *
 * 1. .bb-toolbar-tabs carried flex-shrink: 0, so at 390px the contests filter
 *    row kept its full width and bled 15px past its form on the left while the
 *    right edge stayed put - asymmetric, which is what separates it from a
 *    deliberate full-bleed.
 * 2. .bb-methodology-title is an h2 inside a flex button; a nowrap reaching it
 *    clipped about 15px of "How We Calculate GOAT Rankings" at 390px, measured
 *    clientWidth 315 against scrollWidth 349.
 * 3. .bb-odds-history__weeks is handled at its source in odds/index.php - the
 *    nowrap lived in that template's own style block, and the week string
 *    measured 223px against a 97px cell at 1440 as well as 390, so it was
 *    spilling on desktop too.
 */
.bb-app .bb-toolbar-tabs,
.bb-app .bb-filter-tabs {
    flex-shrink: 1;
    flex-wrap: wrap;
    min-width: 0;
    /* width: auto is the actual fix for the 15px left-only bleed. The tab rail
       wants an edge-to-edge bleed and sets margin-inline to -(--bb-space-4),
       but `.bb-app .bb-filter-bar > *` also forces width: 100%. A fixed width
       plus negative margins does not widen the element - it just slides it left
       by one margin - so the rail bled 15px on the left and sat 15px INSIDE on
       the right. Letting the width resolve from the margins restores the
       symmetric bleed the rule was written for. */
    width: auto;
}

.bb-app .bb-methodology-title {
    white-space: normal;
    overflow-wrap: anywhere;
    min-width: 0;
}
.bb-app .bb-methodology-toggle {
    min-width: 0;
    gap: var(--bb-space-3);
}

/* The /tools/ intro. Its heading and lede used to sit as two bare band-level
   siblings, so the paragraph became a 601px band among 1240px ones - the single
   route where the band sequence was not uniform. Sectioned in the template; the
   measure constraint moves here so it still reads at a comfortable width. */
.bb-app .bb-tools-intro {
    margin: var(--bb-space-2) 0 var(--bb-space-5);
}
.bb-app .bb-tools-intro > p {
    max-width: 70ch;
    margin: 0;
    font-size: var(--bb-fs-15);
    color: var(--bb-text-secondary);
}

/* Event podium heading. The podium is the top 3 of ONE division, so it has to
   say which - it previously rendered three different divisions' winners as
   gold/silver/bronze with nothing naming any of them. */
.bb-app .bb-event-podium-title {
    display: flex;
    align-items: baseline;
    gap: var(--bb-space-3);
    margin: 0 0 var(--bb-space-4);
    font-size: var(--bb-fs-22);
    color: var(--bb-ink);
}
.bb-app .bb-event-podium-eyebrow {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}

/* The Masters boundary. Age-graded classes are a separate competition and at a
   large show they outnumber the pro divisions (Tampa Pro: 10 open, 34 Masters),
   so the reader needs to be told where one ends and the other begins. Sorting
   them last was never enough on its own. */
.bb-app .bb-event-masters-break {
    margin: clamp(32px, 5vw, 56px) 0 var(--bb-space-6);
    padding-top: var(--bb-space-6);
    border-top: 2px solid var(--bb-ink);
}
.bb-app .bb-event-masters-break__title {
    margin: 0 0 var(--bb-space-2);
    font-size: var(--bb-fs-26);
    color: var(--bb-ink);
}
.bb-app .bb-event-masters-break__note {
    margin: 0;
    max-width: 68ch;
    font-family: var(--bb-font-body);
    font-size: 15px;
    color: var(--bb-text-secondary);
}

/* ---- Division index at scale -------------------------------------------
 * The flat chip list is fine to about seven divisions. Tampa Pro fields 48 and
 * rendered eleven rows of pills, roughly 800px, before the first result - the
 * reader scrolled past the whole index to reach the contest. The 34 age-graded
 * ones now fold away behind a disclosure and the open card keeps its ten.
 */
.bb-app .bb-event-tabs-masters {
    margin: var(--bb-space-3) 0 var(--bb-space-5);
    border-top: 1px solid var(--bb-border);
    padding-top: var(--bb-space-3);
}
.bb-app .bb-event-tabs-masters__summary {
    display: inline-flex;
    align-items: center;
    gap: var(--bb-space-2);
    cursor: pointer;
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
    list-style: none;
}
.bb-app .bb-event-tabs-masters__summary::-webkit-details-marker { display: none; }
.bb-app .bb-event-tabs-masters__summary::after {
    content: "+";
    font-size: 14px;
    line-height: 1;
}
.bb-app .bb-event-tabs-masters[open] .bb-event-tabs-masters__summary::after { content: "\2212"; }
.bb-app .bb-event-tabs-masters__summary:hover { color: var(--bb-ink); }
.bb-app .bb-event-tabs-masters__count {
    padding: 2px 8px;
    border: 1px solid var(--bb-border);
    border-radius: 999px;
    color: var(--bb-ink);
}
.bb-app .bb-event-tabs--masters { margin-top: var(--bb-space-3); }

/* Past editions of the same show. contest_series linked them all along; nothing
   on the page read it, so a reader on a 2026 contest had no route to 2025. */
.bb-app .bb-event-editions {
    margin-top: var(--bb-space-5);
    padding-top: var(--bb-space-4);
    border-top: 1px solid var(--bb-border);
}
.bb-app .bb-event-editions__title {
    margin: 0 0 var(--bb-space-3);
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}
.bb-app .bb-event-editions__list { margin: 0; padding: 0; list-style: none; }
.bb-app .bb-event-editions__item + .bb-event-editions__item { border-top: 1px solid var(--bb-border); }
.bb-app .bb-event-editions__item a {
    display: flex;
    align-items: baseline;
    gap: var(--bb-space-3);
    padding: 8px 0;
    min-width: 0;
}
.bb-app .bb-event-editions__year {
    flex: 0 0 auto;
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-text-muted);
    font-variant-numeric: tabular-nums;
}
.bb-app .bb-event-editions__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
}

/* Multi-class division notice (UI-91).
 * A division holding several athletes at placement 1 is almost never a tie -
 * the weight classes were lost on ingest, so each of them won a different
 * class. Division 45185, the 2012 IFBB Amateur Mr Olympia, shows four at first
 * with places 2-6 also occupied. Removing the old T-N tie labels took away the
 * false "tied for 1st" wording but left the data asserting four outright
 * winners, which reads worse. Until the classes are restored the page says so
 * plainly and drops the medal styling. */
.bb-app .bb-multiclass-note {
    margin: 0 0 var(--bb-space-4);
    padding: var(--bb-space-3) var(--bb-space-4);
    border-left: 3px solid var(--bb-amber, #d98b4a);
    background: var(--bb-tint);
    font-family: var(--bb-font-body);
    font-size: 14px;
    line-height: 1.5;
    color: var(--bb-text-secondary);
    max-width: 72ch;
}
.bb-app .bb-multiclass-note strong { color: var(--bb-ink); }

/* ---- Event profile + judging pointer ------------------------------------
 * The generic judging explainer used to render above the results on every
 * contest page - identical text on thousands of URLs, competing with itself in
 * search and pushing the results down. It now lives once at /judging/ and this
 * space carries facts about THIS event instead, computed from its own rows.
 */
.bb-app .bb-event-profile {
    margin: var(--bb-space-5) 0 var(--bb-space-6);
    padding: var(--bb-space-4) 0;
    border-top: 1px solid var(--bb-border);
    border-bottom: 1px solid var(--bb-border);
}
.bb-app .bb-event-profile__lede {
    margin: 0;
    max-width: 74ch;
    font-family: var(--bb-font-body);
    font-size: 16px;
    line-height: 1.6;
    color: var(--bb-text-primary);
}
.bb-app .bb-event-profile__meta {
    margin: var(--bb-space-3) 0 0;
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-text-muted);
}
.bb-app .bb-event-profile__label {
    margin-right: var(--bb-space-2);
    font-size: 11px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}

.bb-app .bb-judging-pointer {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--bb-space-2) var(--bb-space-3);
    margin: clamp(28px, 4vw, 44px) 0 var(--bb-space-4);
    padding-top: var(--bb-space-4);
    border-top: 1px solid var(--bb-border);
    min-width: 0;
}
.bb-app .bb-judging-pointer__link {
    font-size: 16px;
    font-weight: 600;
}
.bb-app .bb-judging-pointer__note {
    min-width: 0;
    font-family: var(--bb-font-body);
    font-size: 14px;
    color: var(--bb-text-muted);
}

/*
 * The judging guide is long-form reference prose, so it needs a measure.
 * Measured at 1440px before this rule: five paragraphs of 191-342 characters
 * ran the full 1240px container while the definition list beside them was
 * already capped at 678px, so the page disagreed with itself. 74ch is not a new
 * number - it is the cap the dd rule below already sets, applied to the rest.
 */
.bb-app .bb-judging-guide p,
.bb-app .bb-judging-guide li {
    max-width: 74ch;
}

/* The judging guide's own definition list. */
.bb-app .bb-judging-defs { margin: 0; }
.bb-app .bb-judging-defs dt {
    margin-top: var(--bb-space-4);
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}
.bb-app .bb-judging-defs dd {
    margin: var(--bb-space-2) 0 0;
    max-width: 74ch;
    font-family: var(--bb-font-body);
    font-size: 16px;
    line-height: 1.6;
}

/* ==========================================================================
   Contest-value pass, 2026-08-04. Merged from the five build lanes.
   Each block keeps its own measurement notes; they record how the number was
   obtained, not what someone expected it to be.
   ========================================================================== */

/* ==========================================================================
   Upcoming contest modules + pro-chip cap
   Lane file. Merge into bodybuilding.css; every selector below is new, none
   redeclares a rule that already exists there.
   ========================================================================== */

/* ---- Pro division chip bar cap ------------------------------------------
   Measured on /contests/north-american-championships-2017/ at 1718px: 49
   chips, 15 rows, 750px of index before the first result. The Masters fold
   already exists; this caps what is left. Scoped to its own modifier so the
   rule wins regardless of where it lands relative to .bb-app .bb-event-tabs.
   4 rows at 1718px keeps the active first chip and the flagship divisions in
   view; the rest scroll. */
.bb-app .bb-event-tabs--capped {
    max-height: 176px;
    overflow-y: auto;
    overscroll-behavior: contain;
}
@media (max-width: 640px) {
    .bb-app .bb-event-tabs--capped { max-height: 148px; }
}
.bb-app .bb-event-tabs__note {
    margin: calc(var(--bb-space-2) * -1) 0 var(--bb-space-4);
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-muted, var(--bb-text-secondary));
}

/* ---- Defending champions ------------------------------------------------ */
.bb-app .bb-defending {
    margin-bottom: var(--bb-space-6);
}
.bb-app .bb-defending__title {
    font-size: var(--bb-fs-xl);
    margin: 0 0 var(--bb-space-1);
}
.bb-app .bb-defending__note {
    margin: 0 0 var(--bb-space-4);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
}
.bb-app .bb-defending__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
    gap: var(--bb-space-3);
}
.bb-app .bb-defending__card {
    display: flex;
    align-items: center;
    gap: var(--bb-space-3);
    padding: var(--bb-space-3);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
    background: var(--bb-surface);
    min-width: 0;
}
.bb-app .bb-defending__portrait {
    flex: 0 0 56px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bb-gray-100, rgba(0, 0, 0, 0.05));
    display: flex;
    align-items: center;
    justify-content: center;
}
.bb-app .bb-defending__portrait img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.bb-app .bb-defending__initials {
    font-family: var(--bb-font-mono, monospace);
    font-size: var(--bb-fs-base);
    font-weight: 700;
    color: var(--bb-text-secondary);
    letter-spacing: 0.04em;
}
.bb-app .bb-defending__body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.bb-app .bb-defending__division {
    font-family: var(--bb-font-mono, monospace);
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-secondary);
}
.bb-app .bb-defending__name {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--bb-fs-base);
    font-weight: 600;
    min-width: 0;
}
.bb-app .bb-defending__name img {
    flex: 0 0 auto;
}
.bb-app .bb-defending__meta {
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-secondary);
}
.bb-app .bb-defending__more {
    margin: var(--bb-space-3) 0 0;
    font-size: var(--bb-fs-sm);
}

/* ---- Who has won here --------------------------------------------------- */
.bb-app .bb-series-record {
    margin-bottom: var(--bb-space-6);
    padding: var(--bb-space-4);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
    background: var(--bb-surface);
}
.bb-app .bb-series-record__title {
    font-size: var(--bb-fs-lg);
    margin: 0 0 var(--bb-space-2);
}
.bb-app .bb-series-record__lede {
    margin: 0 0 var(--bb-space-3);
    font-size: var(--bb-fs-sm);
    color: var(--bb-text-secondary);
}
.bb-app .bb-series-record__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}
.bb-app .bb-series-record__item {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 10px;
    padding: 8px 0;
    border-top: 1px solid var(--bb-border);
}
.bb-app .bb-series-record__item:first-child {
    border-top: none;
}
.bb-app .bb-series-record__athlete {
    font-weight: 600;
}
.bb-app .bb-series-record__wins {
    font-family: var(--bb-font-mono, monospace);
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-secondary);
}
.bb-app .bb-series-record__detail {
    flex: 1 1 100%;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-secondary);
}

/* ---- Past editions ledger: winner line ---------------------------------- */
/* The rows carried a year and a name only, so a reader had to open five pages
   to learn who had won five editions. */
.bb-app .bb-event-editions__winner {
    display: block;
    padding: 0 10px 6px;
    font-size: var(--bb-fs-xs);
    color: var(--bb-text-secondary);
}
.bb-app .bb-event-editions__winner-div::before {
    content: " \00B7 ";
}

/* ==========================================================================
   Lane: rankings + GOAT sticky table headers
   Merge target: public/css/bodybuilding.css (section 27, near line 6124)
   ==========================================================================

   PROBLEM (measured, not read off the source)

   .bb-content-table thead th already declares `position: sticky; top: 0`
   (bodybuilding.css:9681) and the computed position on the rendered page IS
   `sticky`. It still never sticks. Probe at 1440x900 on /rankings/:

       th top before scroll = 2211
       window.scrollTo(0, 3000) -> scrollY 1928
       th top after scroll     = 283      (= 2211 - 1928, i.e. it just moved)

   Sticky positions against the nearest ancestor SCROLL CONTAINER, not the
   viewport, and every one of these tables sits inside one:

       /rankings/       .bb-rankings-table-scroll  ox=auto   oy=auto
                        .bb-rankings-table-wrap    ox=hidden oy=hidden
       /rankings/goat/  .bb-rankings-table-wrap.bb-table-scroll-wrapper
                                                   ox=auto   oy=hidden

   `overflow: hidden` and `overflow: auto` both establish a scroll container.
   Those boxes are exactly as tall as the table, so there is nothing to scroll
   inside them and the header has nowhere to stick to. (.site-outer is
   `overflow: clip`, which does NOT establish a scroll container, so the theme
   wrapper was never the culprit.)

   FIX

   Hand the header back to the viewport by removing the scroll container on the
   axis that matters, without giving up the two things those rules were bought
   for: the rounded-corner clip, and horizontal scroll on narrow screens.

   1. `overflow: clip` on the radius container. It clips identically to
      `hidden` but is not a scroll container, so sticky passes through it.
   2. The horizontal scroller only exists because a wide table has to be
      reachable on a narrow screen. Where the table already fits, the scroller
      is dropped and the header goes viewport-sticky. Below that width
      horizontal scroll is kept and the header does not stick, which is the
      right trade: an unreachable table is worse than a scrolling header.

      The breakpoint is 1280px because that is where the measurement flips, not
      because it is a round number. GOAT table content needs 1230px, and the
      page container is narrower than that until 1280px:

          viewport  container  table content
            1024       934        1230   overflows
            1180      1090        1230   overflows
            1240      1150        1230   overflows
            1280      1238        1238   fits

      A first attempt used 1024px and clipped the two GOAT tables at 1024-1240
      with no way to reach the missing 296px. 1280px is also the width at which
      the container itself stops growing, so the two thresholds fire together
      instead of drifting apart on a real browser whose layout viewport is a
      scrollbar narrower than the window.

      Checked at 1024/1280/1440 across every route that uses
      .bb-rankings-table-wrap (/stats/ 8 wrappers, /rankings/, /rankings/goat/,
      /rankings/goat/era-adjusted/; /top-lists/, /best/, /olympia-winners/,
      /records/, /countries/, /seasons/ render none). Nothing else overflows at
      any of those widths, so nothing else is clipped by this rule.

   A max-height scrollport was rejected. It would stick the header inside its
   own box and leave the page-level scroll, which is the scroll a reader
   actually performs, still headerless.

   Every selector is scoped to the rankings/GOAT wrappers. `.bb-content-table`
   is shared by a large number of templates in this plugin and an unscoped
   override would change all of them.
   -------------------------------------------------------------------------- */

/* 1. Radius container stops being a scrollport.
      The :not() matters. On /rankings/ the radius container and the horizontal
      scroller are two nested elements, so this is free. On the GOAT pages they
      are ONE element carrying both classes, and clipping it here killed the
      phone-width horizontal scroll: measured at 700px the table still overflowed
      its box (scrollWidth > clientWidth) with no way to reach the overflow.
      That element is handled inside the media query instead. */
.bb-app .bb-rankings-table-wrap:not(.bb-table-scroll-wrapper) {
    overflow: clip;
}

/* 2. Drop the horizontal scroller where the table already fits.
      /rankings/ nests the scroller; /rankings/goat/ and
      /rankings/goat/era-adjusted/ put both classes on the same element. */
@media (min-width: 1280px) {
    .bb-app .bb-rankings-table-wrap > .bb-rankings-table-scroll {
        overflow: clip;
    }

    .bb-app .bb-rankings-table-wrap.bb-table-scroll-wrapper {
        overflow: clip;
    }

    /* .bb-nav is `position: sticky; top: 0; z-index: 50` (bodybuilding.css:1135)
       and measures 58px tall on the rendered page at 1024, 1280 and 1440, so
       the offset is not viewport-dependent. `top: 0` would park the header
       underneath the nav, so it stops at the nav's lower edge and stays below
       it in the stack.

       58px accounts for the nav ONLY. If a sticky filter bar ever lands on
       these routes (.bb-toolbar--sticky is `top: 0; z-index: 10`,
       bodybuilding.css:9189) this offset and the z-index both have to move,
       or the table header will slide under it. */
    .bb-app .bb-rankings-table-wrap .bb-content-table thead th {
        top: 58px;
        z-index: 2;
    }
}

/*
 * Divisions lane. Merge into public/css/bodybuilding.css.
 */

/*
 * Filter bar on /divisions/{slug}/: five controls stacked onto three rows.
 *
 * Measured at 1440px: the form was 152px tall (44 + 44 + 44 plus two 10px gaps),
 * with the search box and the select each reporting a computed width of 1240px,
 * the full column. The same .bb-filter-bar .bb-toolbar class pair measures 44px
 * on /countries/.
 *
 * Cause is a bare <select class="bb-select"> as a direct child of the bar.
 * ".bb-input, .bb-select, .bb-filter-input" sets width: 100%, and the bar only
 * overrides its wrapper classes: rules exist for "> .bb-filter-select" and
 * "> .bb-toolbar-filter" but not for a plain select. So the select claimed the
 * whole row, the flex line wrapped, and the search box grew to fill the row it
 * was pushed onto. /countries/ escapes it by wrapping its select in one of the
 * classes that is covered.
 *
 * This mirrors the existing "> .bb-filter-select" rule rather than inventing a
 * width, and carries the .bb-app prefix because the .bb-app control block is
 * what sets the width these selectors have to beat.
 */
.bb-app .bb-filter-bar > .bb-select,
.bb-app .bb-toolbar > .bb-select,
.bb-app .bb-filter-bar > select,
.bb-app .bb-toolbar > select {
    width: auto;
    min-width: 160px;
    max-width: 220px;
    flex: 0 1 auto;
}

/*
 * Lane: about-the-database / compare / fantasy.
 * Merge into public/css/bodybuilding.css.
 */

/* ------------------------------------------------------------------
 * Fantasy contest grid: collapse at 24 cards.
 *
 * Measured before: #bb-fantasy-contests-grid rendered 100 cards, 5605px tall,
 * 34 rows, no pagination. 24 is a multiple of every column count this auto-fill
 * grid resolves to (1 on phone through 4 on wide desktop), so the cut lands on
 * a row boundary instead of mid-row.
 *
 * The cap is CSS rather than JS because fantasy.js owns this grid's innerHTML
 * and replaces it on every season change; a class on the grid element survives
 * that (it never touches className or classList on the grid), a class on the
 * cards would not.
 * ------------------------------------------------------------------ */
.bb-fantasy-contest-grid > *:nth-child(n + 25) {
    display: none;
}

.bb-fantasy-contest-grid--expanded > *:nth-child(n + 25) {
    display: flex;
}

/* Hidden by default: the button only earns its place once something is behind it. */
.bb-fantasy-contests-more {
    display: none;
    justify-content: center;
    margin-top: var(--bb-space-4);
}

.bb-fantasy-contests-wrap:has(> .bb-fantasy-contest-grid > *:nth-child(25)) .bb-fantasy-contests-more {
    display: flex;
}

/*
 * ...and it goes away entirely while the grid itself is hidden. fantasy.js sets
 * style.display = 'none' during load and on the empty state, then clears it back
 * to '' when there are cards, so matching the inline value is reliable. Last in
 * the file so it beats the :has() rule above at equal specificity.
 */
.bb-fantasy-contests-wrap:has(> .bb-fantasy-contest-grid[style*="none"]) .bb-fantasy-contests-more {
    display: none;
}

/* ------------------------------------------------------------------
 * Compare: the trust bar now renders below the head-to-head summary rather
 * than flush under the hero, so it needs its own separation from the block
 * above it instead of inheriting the hero's bottom edge.
 * ------------------------------------------------------------------ */
.bb-h2h-summary + .bb-data-trust-bar {
    margin-top: var(--bb-space-4);
}

/*
 * Contest provenance line - what replaced the removed source panel.
 *
 * Three signals the panel deletion took with it: show state, results-updated
 * date, source attribution. One row below the results instead of a boxed panel
 * above them. Wraps rather than scrolls, because on a phone it is three short
 * phrases and a link, not a table.
 */
.bb-app .bb-event-provenance {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 16px;
    margin: var(--bb-space-4) 0 0;
    padding-top: var(--bb-space-3);
    border-top: 1px solid var(--bb-border);
    font-family: var(--bb-font-mono);
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
}
.bb-app .bb-event-provenance__state {
    font-weight: 600;
    color: var(--bb-text-secondary);
}
/*
 * The date carries the same mono/uppercase treatment as the state beside it,
 * declared rather than inherited: the ratchet counts a class used in markup with
 * no rule of its own as a defect, and it is right to - a sibling that only looks
 * correct because of its parent breaks the moment the parent moves.
 */
.bb-app .bb-event-provenance__updated {
    font-variant-numeric: tabular-nums;
}

.bb-app .bb-event-provenance__source {
    text-transform: none;
    letter-spacing: 0;
}

/*
 * Scorecard citations under the provenance line. A list because it is a list of
 * sources, but it carries no bullets or box - the removed panel's weight was the
 * problem, not its content.
 */
.bb-app .bb-event-provenance__scorecards {
    list-style: none;
    margin: var(--bb-space-2) 0 0;
    padding: 0;
    font-size: 12px;
    line-height: 1.6;
    color: var(--bb-text-muted);
}
.bb-app .bb-event-provenance__scorecards li + li {
    margin-top: 2px;
}

/*
 * Winner badge on a results row.
 *
 * Sits beside the name rather than in its own column: it applies to at most a
 * handful of rows per table, and an extra column would be mostly empty and
 * would cost every row width on a phone. Inline-block so it wraps under a long
 * name instead of stretching the cell.
 */
.bb-app .bb-winner-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 7px;
    border: 1px solid var(--bb-border);
    border-radius: 999px;
    background: var(--bb-surface);
    font-family: var(--bb-font-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--bb-text-secondary);
    vertical-align: middle;
}
@media (max-width: 640px) {
    .bb-app .bb-winner-badge {
        margin-left: 0;
        margin-top: 4px;
    }
}

/*
 * "Where last year's winners went next" on upcoming contest pages.
 *
 * A list of outcomes, so it reads as one column of division-then-sentence
 * rather than a grid of cards; the sentences vary in length and cards would
 * leave ragged whitespace.
 */
.bb-app .bb-oly-follow {
    margin-bottom: var(--bb-space-6);
    padding: var(--bb-space-4);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
    background: var(--bb-surface);
}
.bb-app .bb-oly-follow__title {
    font-size: var(--bb-fs-lg);
    margin: 0 0 var(--bb-space-3);
}
.bb-app .bb-oly-follow__list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.bb-app .bb-oly-follow__item {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 12px;
    padding: 8px 0;
    border-top: 1px solid var(--bb-border);
}
.bb-app .bb-oly-follow__item:first-child {
    border-top: none;
}
.bb-app .bb-oly-follow__division {
    flex: 0 0 auto;
    min-width: 9rem;
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-text-secondary);
}
.bb-app .bb-oly-follow__body {
    flex: 1 1 16rem;
}

/*
 * Schedule table: month heading rows and secondary hints.
 *
 * The month row is a th/colgroup inside the same table rather than a separate
 * table per month, so column widths stay aligned down the page and the whole
 * thing remains one scroll region for assistive tech.
 */
.bb-app .bb-schedule-month th {
    padding: var(--bb-space-4) var(--bb-space-2) var(--bb-space-2);
    border-bottom: 1px solid var(--bb-border);
    background: var(--bb-surface);
    font-family: var(--bb-font-mono);
    font-size: 11px;
    /*
     * 400, not the 600 this shipped with. 11px mono at 0.16em IS the house
     * eyebrow, and the eyebrow is 400 everywhere else - test-type-scale-
     * conformance caught the mismatch. The month row does not need weight to
     * read as a separator: it already has uppercase, letter-spacing, a rule
     * beneath it and a full-width span.
     */
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    text-align: left;
    color: var(--bb-text-secondary);
}
.bb-app .bb-schedule-hint {
    display: block;
    font-size: 11px;
    line-height: 1.5;
    color: var(--bb-text-muted);
}

/*
 * A cell with nothing in it should not announce itself.
 *
 * The stacked card view prints `content: attr(data-label)` on every cell, so an
 * empty one still renders its label as a line. On /schedule/, 93 of 137 shows
 * have no prior edition, so the majority of cards carried two dead labelled
 * lines on a phone. :empty cannot be used - PHP leaves whitespace inside the
 * element - so the template decides emptiness and marks it.
 *
 * Only in the stacked view: in the desktop table the cell must keep its place
 * or the columns stop lining up.
 */
/* 768, matching the breakpoint at which the table actually stacks (:1871). At
   767 the two disagreed by one pixel and every dead label returned at exactly
   768 - iPad portrait, a real device width, not a theoretical one. */
@media (max-width: 768px) {
    .bb-app .bb-table--responsive td.bb-cell-empty,
    .bb-app .bb-data-table--responsive td.bb-cell-empty {
        display: none;
    }
}

/* ==========================================================================
   ROW CAP - long tables show 25 rows and a control for the rest
   ========================================================================== */

/*
 * The owner's call on the six tables that scrolled sideways on a phone: show
 * the first 25 rows, a button reveals the rest, and EVERY row still ships in
 * the server-rendered HTML. Nothing leaves the index; the hidden rows simply
 * have no height until the reader asks for them.
 *
 * `is-capped` is rendered by the server, not added by JavaScript. Adding it on
 * load would paint 140 rows and then collapse them, which is a visible jump on
 * the exact pages this was meant to make calmer. The partial's <noscript>
 * block un-caps for a reader without JavaScript, who then gets the whole
 * table, which is what they had before any of this.
 *
 * nth-child(n+26) rather than a class on each row: the cap is a property of
 * the table, and the server should not have to count while it renders.
 *
 * The hidden value is indirected through a custom property so that <noscript>
 * block can un-cap without out-specifying this selector. It could not: at
 * (0,4,2) it beat the restore rule the partial used to ship, so a reader with
 * JavaScript off got 25 rows AND a hidden button, which is worse than the dead
 * button the block was written to prevent. Winning that on specificity means
 * another compound selector or an !important, which is the arms race this
 * stylesheet is on record for. A property moves it out of the cascade: the
 * row never declares --bb-rowcap-row-display itself, so it inherits whatever
 * the partial set on the TABLE, and this rule keeps matching either way. Set
 * nowhere, which is every reader with JavaScript, it falls back to none.
 */
.bb-app .bb-rowcap.is-capped tbody tr:nth-child(n+26) {
    display: var(--bb-rowcap-row-display, none);
}

.bb-app .bb-rowcap__btn {
    display: block;
    width: 100%;
    min-height: var(--bb-touch-min);
    margin: 10px 0 0;
    padding: 12px 16px;
    background: var(--bb-surface);
    border: 1px solid var(--bb-ink);
    border-radius: var(--bb-radius-sm);
    /*
     * 400 weight at 0.16em, which is the plugin's eyebrow spec rather than a
     * button voice. test-type-scale-conformance checks every mono uppercase
     * leaf against that spec, and a 600-weight control here would read to it
     * as an off-spec label. Matching the spec is cheaper than an exemption,
     * and it is what the rest of the page's small caps already do.
     */
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-ink);
    cursor: pointer;
    transition: background-color var(--bb-transition), color var(--bb-transition);
}

.bb-app .bb-rowcap__btn:hover {
    background: var(--bb-ink);
    color: var(--bb-paper);
}

/* ==========================================================================
   EVENT COVERAGE - editorial notes an admin or editor writes on a show
   ========================================================================== */

/*
 * A show can be covered from the venue before any result exists. While it is
 * live this block sits above the results area and is the page; once results
 * land it moves below them and reads as the archive of that night. The move
 * lives in the template, driven by whether results exist, so nobody has to
 * remember to demote it.
 */
/*
 * Byline for a covered show. Same information architecture as the theme's post
 * meta - avatar, author, date, "Updated" - in plugin-owned classes, because
 * inheriting Foxiz's `single-meta` cascade onto a plugin route is how a theme
 * update changes a plugin page silently, and this product is light-theme only.
 *
 * No new custom properties: every value here is an existing token.
 */
.bb-app .bb-event-byline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    margin: 0 0 var(--bb-space-5);
    color: var(--bb-text-secondary);
    font-size: 0.875rem;
    line-height: 1.4;
}

.bb-app .bb-event-byline__avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    flex: 0 0 auto;
}

.bb-app .bb-event-byline__author {
    font-weight: 600;
    color: var(--bb-text-primary);
}

.bb-app .bb-event-byline__author a {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid var(--bb-border);
}

.bb-app .bb-event-byline__author a:hover,
.bb-app .bb-event-byline__author a:focus-visible {
    border-bottom-color: currentColor;
}

/*
 * "Updated" only prints on a different day (see bb_event_byline), so when it is
 * here it is genuinely new information and earns the separator.
 */
.bb-app .bb-event-byline__updated::before {
    content: "";
    display: inline-block;
    width: 3px;
    height: 3px;
    margin-right: 8px;
    border-radius: 50%;
    background: currentColor;
    vertical-align: middle;
    opacity: 0.6;
}

.bb-app .bb-event-byline__live {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: var(--bb-radius-sm);
    background: var(--bb-primary);
    /* --bb-on-dark, not #fff: this is the one literal the token ratchet caught being added
       this session, and there is already a token for text sitting on a dark fill. */
    color: var(--bb-on-dark);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.bb-app .bb-event-coverage {
    margin: 0 0 var(--bb-space-6);
    padding: var(--bb-space-5);
    background: var(--bb-paper);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-md);
}

/*
 * The intro is the lead of an article, so it reads at article measure rather than
 * as a boxed aside. The panel treatment stays on the other two zones, which are a
 * provisional table and an embed-heavy analysis.
 */
.bb-app .bb-event-coverage--intro {
    padding: 0;
    background: none;
    border: 0;
}

.bb-app .bb-event-coverage--intro .bb-event-coverage__body {
    font-size: 1.0625rem;
    line-height: 1.7;
}

.bb-app .bb-event-coverage__provenance {
    margin: 0 0 var(--bb-space-3);
    color: var(--bb-text-secondary);
    font-size: 0.8125rem;
}

/*
 * Editor-only prompt, shown when official placings have landed but nobody has
 * approved them yet, so the provisional block and the official table are both up.
 * Deliberately loud: it is the one state where the page shows two answers, and the
 * fix is one click.
 */
.bb-app .bb-event-coverage__review {
    margin: 0 0 var(--bb-space-3);
    padding: var(--bb-space-3);
    border-left: 3px solid var(--bb-primary);
    background: var(--bb-paper);
    color: var(--bb-text-primary);
    font-size: 0.875rem;
}

/*
 * Live gets an accent rule along the top and nothing else. The content is
 * photographs and embeds from a stage, and a coloured panel behind them fights
 * every one of them.
 */
.bb-app .bb-event-coverage--live {
    border-top: 3px solid var(--bb-primary);
}

.bb-app .bb-event-coverage__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 14px;
    margin: 0 0 var(--bb-space-4);
}

.bb-app .bb-event-coverage__body > *:first-child { margin-top: 0; }
.bb-app .bb-event-coverage__body > *:last-child { margin-bottom: 0; }

/*
 * Pasted embeds arrive at their own intrinsic width and will happily run past
 * a 345px column. An iframe carries no intrinsic ratio to fall back on, so its
 * width has to be stated rather than inherited from whatever governs images.
 */
.bb-app .bb-event-coverage__body img,
.bb-app .bb-event-coverage__body iframe,
.bb-app .bb-event-coverage__body video,
.bb-app .bb-event-coverage__body blockquote {
    max-width: 100%;
}

.bb-app .bb-event-coverage__body iframe {
    width: 100%;
    border: 0;
}

.bb-app .bb-event-coverage__body figure {
    margin: var(--bb-space-4) 0;
}

/*
 * The Edit control is for two people on the whole internet. It sits at the end
 * of the block header rather than beside the show name, because a reader
 * should never have to look past an editorial affordance to reach the story.
 */
.bb-app .bb-event-coverage__edit {
    margin-left: auto;
    padding: 5px 11px;
    background: transparent;
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-sm);
    font-family: var(--bb-font-mono);
    font-size: var(--bb-fs-2xs);
    font-weight: 400;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
    text-decoration: none;
}

.bb-app .bb-event-coverage__edit:hover {
    border-color: var(--bb-ink);
    color: var(--bb-ink);
}

/*
 * The live dot pulses, which is the one place in this plugin where motion
 * carries meaning: it is the difference between "this happened" and "this is
 * happening". It still stops for anyone who asked it to.
 */
.bb-app .bb-event-status--live {
    display: inline-flex;
    align-items: center;
    gap: 7px;
}

.bb-app .bb-event-status--live::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--bb-primary);
    animation: bb-live-pulse 2s ease-in-out infinite;
}

@keyframes bb-live-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
    .bb-app .bb-event-status--live::before {
        animation: none;
    }
}

@media (max-width: 600px) {
    .bb-app .bb-event-coverage {
        padding: var(--bb-space-4);
    }
}

/*
 * The coverage block's own heading. It carries the note title, which is what
 * the editor typed, so it is a card heading and takes the 22 tier rather than
 * the 26 a section heading gets. The ratchet caught it as an orphan: the block
 * shipped with a class the stylesheet had never heard of.
 */
.bb-app .bb-event-coverage__title {
    margin: 0;
    font-family: var(--bb-font-heading);
    font-size: var(--bb-fs-22);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.016em;
    color: var(--bb-ink);
    border-bottom: 0;
    padding-bottom: 0;
}

/*
 * "Only the winner was recorded" note on a division that holds one row.
 *
 * Quiet on purpose. It explains a gap rather than announcing a problem, and it
 * sits on 319 contests, so anything louder would make a third of the archive
 * look broken when it is merely incomplete and saying so.
 */
.bb-app .bb-note--partial {
    margin: 0 0 var(--bb-space-3);
    padding: 9px 12px;
    background: var(--bb-surface-sunken, var(--bb-tint));
    border-left: 3px solid var(--bb-warm-grey-2);
    border-radius: var(--bb-radius-sm);
    font-size: var(--bb-fs-xs);
    line-height: 1.5;
    color: var(--bb-text-secondary);
}

/*
 * Five classes the markup emitted with no rule at all.
 *
 * Found by tests/test-design-token-ratchet.php, which is exactly what it is for: a bb- class in
 * markup with no declaration is either a styling gap nobody noticed or a leftover, and both look
 * identical until something asserts on it. These are the first kind - each is a real element that
 * was inheriting whatever the theme happened to give it.
 *
 * .bb-route carries no declarations on purpose and is NOT in this list: it was a marker class on
 * the page shell that styled nothing, so it is removed from the markup rather than given a rule to
 * satisfy a test.
 */
/*
 * The label and the name it labels are adjacent inline spans built with no whitespace between them,
 * so the strip rendered "ChampionDerek Lunsford" as one word. The gap belongs here rather than as a
 * space character in the markup: a literal space between two inline elements collapses the moment
 * anyone reformats that PHP, and it would be invisible to read back.
 */
.bb-app .bb-embed-strip__label {
    color: var(--bb-text-muted);
    margin-right: 0.4em;
}

.bb-app .bb-embed-strip__champion {
    font-weight: 600;
    color: var(--bb-text-primary);
}

/* A fact that is not a link: same chip shape, none of the affordance. */
.bb-app .bb-embed-chip--plain {
    display: inline-block;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--bb-text-muted);
    background: var(--bb-surface-sunken);
    border: 1px solid var(--bb-border-soft);
    border-radius: 2px;
    padding: 5px 9px;
    cursor: default;
}

/*
 * "You are here" in the divisions list.
 *
 * A division article now lists every division at the event so the reader can reach the other ten,
 * which means one chip in that list is the page being read. It is rendered as a span rather than a
 * link, and this is what makes that legible instead of looking like a chip that failed to link:
 * the accent border and ink text mark it as current, and it deliberately reads heavier than the
 * plain variant above, which means the opposite thing (no destination exists at all).
 */
.bb-app .bb-embed-chip--current {
    display: inline-block;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--bb-text-primary);
    background: var(--bb-surface);
    border: 1px solid var(--bb-accent);
    border-radius: 2px;
    padding: 5px 9px;
    cursor: default;
}

.bb-app .bb-event-byline__date {
    color: var(--bb-text-muted);
    font-size: 13.5px;
    white-space: nowrap;
}

/* ---- the collapse ------------------------------------------------------ */

@media (max-width: 940px) {
}

/* ==========================================================================
   BOUND EDITORIAL POST, ON THE THEME'S OWN LAYOUT (.bb-editorial-post)

   Markup owner: public/templates/bb_template.php, which is the theme's Layout 8
   with three edits. These rules are the second and third of them.

   EVERY SELECTOR HERE IS SCOPED UNDER .bb-editorial-post ON PURPOSE. .s-title,
   .s-feat-outer and .single-header are the theme's global classes, used by every
   post on this site. Unscoped, a hero tweak for 170 event reports would restyle
   every article fitnessvolt.com has ever published. The marker class is added in
   bb_template.php for exactly this reason.

   The hero is compacted in CSS rather than by removing markup, because the brief
   was that everything other than the header, hero and sidebar stays as it is -
   and a caption, a category link or a tagline removed from the markup is not
   something CSS can give back.
   ========================================================================== */

/*
 * The plugin section nav, and the requirement is simply that it MATCHES a plugin
 * route's nav. Not a variation on it.
 *
 * How a plugin route builds it: bb_header() puts .bb-nav inside .bb-app, and
 * .bb-app is the container - max-width calc(var(--bb-container) + 40px) with 20px
 * of inline padding. So .bb-nav itself measures 1240 starting at x=100 on a
 * 1440 viewport. The nav element is CONSTRAINED; there is no full-bleed band
 * anywhere in the plugin.
 *
 * What went wrong here: this wrapper carries .bb-embed, which exists to stop an
 * embedded plugin block behaving like a page - and part of that is setting
 * max-width:none, margin-inline:0 and padding-inline:0. So .bb-app's container
 * was switched off and the nav ran the full 1440, which is the full-bleed band.
 * Diffing the two navs property by property is what showed it: .bb-nav w=1240
 * left=100 on a route against w=1440 left=0 here.
 *
 * So the container properties .bb-embed removes are put back on this one element,
 * and the overrides that were compensating for the band are gone: no width:100%,
 * no band border (the nav has its own), and no max-width on the inner
 * .bb-container, which computes max-width:none on a route and must here too.
 */
.bb-editorial-navbar {
    /*
     * Sticky, to match the route, AND the stacking context the dropdowns need.
     *
     * It has to be the WRAPPER that sticks, not .bb-nav inside it. On a route
     * .bb-nav's containing block is .bb-app, which wraps the whole page, so it has
     * somewhere to travel. Here the wrapper is nav-height, and a sticky element
     * cannot leave its containing block - so sticky on .bb-nav resolved to nothing
     * and the bar just scrolled away, which is what it did before this line.
     *
     * z-index 200 is measured against the page, not picked for roominess: it has
     * to clear the theme's header.single-header at z-index 109, which was painting
     * over open dropdowns, and stay under the theme's lightbox at 1000 and its own
     * sticky site header, both of which SHOULD cover this nav.
     */
    position: sticky;
    top: 0;
    z-index: 200;
}

/*
 * The nav's surface, and it needs the weight.
 *
 * A route gets this for free: .bb-app::before paints a fixed full-viewport page
 * ground, so the nav always has something opaque behind it even while sticky.
 * That mechanism is exactly what must NOT happen on a theme page - a fixed
 * full-viewport layer covers the article, which is the blank-page failure - so
 * .bb-embed removes it and sets background:transparent !important. A sticky bar
 * with no background lets the article scroll visibly through the nav links, so
 * the same visual result is reached with an ordinary background instead.
 *
 * Beating an !important needs specificity: (0,3,0) against that rule's (0,2,0).
 * As a bare class it computed to rgba(0,0,0,0) and read like a failed token.
 */
.bb-app.bb-embed.bb-editorial-navbar {
    background: var(--bb-surface) !important;

    /*
     * The container box, and it lives HERE rather than on the bare class for the
     * same specificity reason as the background above. .bb-app.bb-embed sets
     * max-width:none / margin-inline:0 / padding-inline:0 at (0,2,0); a bare
     * .bb-editorial-navbar is (0,1,0) and loses, so the nav stayed 1440 wide at
     * left 0 with the declarations sitting right there in the stylesheet looking
     * applied. Same shape of failure as the background reading rgba(0,0,0,0).
     *
     * These three values are .bb-app's own container, so the nav lands on 1240 at
     * x=100 exactly as it does on a plugin route.
     */
    max-width: calc(var(--bb-container) + 40px);
    padding-inline: 20px;
    margin-inline: auto;
    box-sizing: border-box;
}

/*
 * MOBILE: the nav goes edge to edge.
 *
 * On a phone the 20px of container padding leaves the bar floating inside the article's gutter with
 * a strip of page either side, which reads as a card rather than as site chrome. Full-bleed makes it
 * a band under the site header, which is the point of putting the plugin nav there.
 *
 * Same (0,3,0) selector as the rules above, for the same reason: .bb-app.bb-embed is (0,2,0) and a
 * bare class silently loses to it. Everything inside still lines up, because bb_nav()'s own
 * .bb-container keeps its padding.
 */
@media (max-width: 767px) {
    .bb-app.bb-embed.bb-editorial-navbar {
        max-width: none;
        padding-inline: 0;
    }
}

/* ---- the compact hero -------------------------------------------------- */

/*
 * The headline. 40px is what the theme Layout 8 measured at 1440, and it is
 * built for a news lede of eight or ten words. These titles run long - the
 * Olympia one reaches "Complete Scorecards For Every Division" - and wrap to
 * three lines before the reader has reached a single fact. 34px holds two.
 *
 * THE :not(.fw-headline) IS LOAD-BEARING, NOT COPIED DECORATION. The theme sizes
 * this element with `.s-title:not(.fw-headline)`, which is (0,2,0) - the same
 * specificity as a plain `.bb-editorial-post .s-title`. On a tie the later rule
 * wins, the theme's is later, and the first version of this block computed 40px
 * with every declaration in it applying except the one that mattered. Matching
 * the negation takes it to (0,3,0) and it lands. Verified from the engine's own
 * matched-rule list, not by reading the stylesheet.
 */
.bb-editorial-post .s-title:not(.fw-headline) {
    font-size: 34px;
    line-height: 1.18;
    letter-spacing: -0.015em;
    text-wrap: balance;
}

/*
 * Pull the header block in, since a shorter headline leaves the old rhythm
 * reading as a gap rather than as breathing room.
 */
.bb-editorial-post .single-header {
    margin-bottom: var(--bb-space-3);
}

/*
 * The featured image measured 807x503 - half a laptop viewport gone before the
 * first placing. Capped and cropped from slightly above centre, which keeps the
 * subject on a posed physique shot. Width is untouched: that is the content
 * column, and column widths do not move.
 */
.bb-editorial-post .s-feat-outer img {
    max-height: 380px;
    object-fit: cover;
    object-position: center 30%;
}

.bb-editorial-post .s-feat-outer {
    margin-bottom: var(--bb-space-3);
}

/* ---- division sections in the article body ----------------------------- */

/*
 * Each division gets a rule under its heading.
 *
 * This is a restore, not a new idea. The retired template wrapped the_content()
 * in .bb-editorial__body and hung this treatment off it; the theme's own content
 * wrapper does not match those selectors, so the swap left eleven consecutive
 * division headings at an identical 22px with no separation - measured, and the
 * kind of loss that a screenshot of the top of the page cannot show.
 *
 * THE CHILD SELECTOR IS LOAD-BEARING. A descendant selector also reaches the
 * injected newsletter block's "Get Fitter, Faster" h3, which sets its own colour
 * and size inline but no border, so it would pick up the rule and nothing else -
 * a heading with a stray line under it. Measured on this page: 13 direct
 * children of .entry-content, being 2 h2 and the 11 division h3, and exactly 2
 * nested h3, both inside div.fv-newsletter. The `>` is what separates them.
 *
 * Font size is deliberately left at the theme's, so this adds hierarchy without
 * touching the type scale the conformance test asserts on.
 */
.bb-editorial-post .entry-content > h3 {
    margin-top: var(--bb-space-6);
    padding-bottom: var(--bb-space-2);
    border-bottom: 2px solid var(--bb-accent);
    letter-spacing: -0.01em;
}

@media (max-width: 767px) {
    /*
     * Mobile is where the oversized headline actually hurt: a 40px H1 on a 390px
     * screen is a wall of text before any information. The image gets a harder
     * cap for the same reason - on a phone it is the only thing on screen until
     * the reader scrolls past it.
     */
    /* Same negation as above, for the same specificity reason. */
    .bb-editorial-post .s-title:not(.fw-headline) {
        font-size: 26px;
        line-height: 1.22;
    }

    .bb-editorial-post .s-feat-outer img {
        max-height: 220px;
    }
}

/* ==========================================================================
   THE OLYMPIA WINNERS REPORT (.bb-oly-*)

   Markup owner: includes/class-bodybuilding-olympia-report-shortcode.php, placed in the eleven
   editorial winners articles as [bb_olympia_report].

   These blocks render INSIDE a post, on the theme's own layout, so every rule is scoped under
   .bb-oly-report and uses the plugin's tokens. The scope matters: .bb-app hosts the token block, and
   this wrapper carries .bb-app bb-embed so the tokens resolve without the full-viewport page ground.

   No inner scrolling anywhere. The winners table renders all 61 rows in the document, because the
   list IS the answer to the query and a scroll container hides it from a reader skimming the page.
   ========================================================================== */

.bb-oly-report {
    margin: 0 0 var(--bb-space-5);
}

/* ---- portraits ---------------------------------------------------------- */

.bb-oly-report .bb-oly-face {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    flex: none;
    object-fit: cover;
    background: var(--bb-surface-sunken);
    border: 1px solid var(--bb-border-soft);
}

.bb-oly-report .bb-oly-face--sm {
    width: 26px;
    height: 26px;
}

/*
 * The fallback when an athlete has no photo. It is a real state, not decoration: an <img> with an
 * empty src re-requests the current page, so the renderer prints initials instead.
 */
.bb-oly-report .bb-oly-face--initials {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--bb-font-mono);
    font-size: 11px;
    font-weight: 700;
    color: var(--bb-on-dark);
    background: var(--bb-warm-grey);
    border-color: transparent;
    letter-spacing: 0.02em;
}

.bb-oly-report .bb-oly-face--sm.bb-oly-face--initials {
    font-size: 9.5px;
}

/* ---- the answer block: the winners table -------------------------------- */

.bb-oly-answer {
    border: 2px solid var(--bb-text-primary);
    margin: 0 0 var(--bb-space-2);
}

/*
 * The .bb-oly-report prefix is load-bearing on this one rule.
 *
 * This wrapper carries .bb-app, and the plugin's own `.bb-app h1, .bb-app h2, ...` rule is (0,1,1)
 * against a bare .bb-oly-answer__head at (0,1,0). It won, and it sets --bb-text-primary - which is
 * exactly the colour of the bar behind this heading. The result was a solid dark block with the
 * heading invisible inside it, and nothing in the markup or the rule looked wrong.
 */
.bb-oly-report .bb-oly-answer__head {
    margin: 0;
    padding: 12px 16px;
    background: var(--bb-text-primary);
    color: var(--bb-on-dark);
    font-size: 15px;
    font-weight: 700;
    line-height: 1.3;
}

.bb-oly-answer__sub {
    margin: 0;
    padding: 10px 16px;
    background: var(--bb-surface-sunken);
    border-bottom: 1px solid var(--bb-border);
    font-size: 13px;
    color: var(--bb-text-secondary);
}

/* The wrap exists for narrow screens only; it never scrolls vertically. */
.bb-oly-tablewrap {
    overflow-x: auto;
}

.bb-oly-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14.5px;
    margin: 0;
}

.bb-oly-table thead th {
    text-align: left;
    font-family: var(--bb-font-mono);
    font-size: 10px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bb-text-muted);
    background: var(--bb-surface);
    padding: 9px 16px;
    border-bottom: 1px solid var(--bb-border);
}

.bb-oly-table td {
    padding: 6px 16px;
    border-bottom: 1px solid var(--bb-border-soft);
    vertical-align: middle;
}

.bb-oly-table tbody tr:last-child td {
    border-bottom: 0;
}

.bb-oly-table tbody tr:hover td {
    background: var(--bb-surface);
}

.bb-oly-yr {
    font-family: var(--bb-font-mono);
    font-size: 13px;
    color: var(--bb-text-secondary);
    width: 62px;
    font-variant-numeric: tabular-nums;
}

.bb-oly-champ-in {
    display: flex;
    align-items: center;
    gap: 10px;
}

.bb-oly-champ a {
    color: var(--bb-text-primary);
    text-decoration: none;
    font-weight: 600;
}

.bb-oly-champ a:hover {
    color: var(--bb-accent);
    text-decoration: underline;
}

.bb-oly-count {
    font-family: var(--bb-font-mono);
    font-size: 10.5px;
    color: var(--bb-accent);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border-soft);
    border-radius: 2px;
    padding: 1px 4px;
}

.bb-oly-country,
.bb-oly-runner {
    color: var(--bb-text-secondary);
    font-size: 13.5px;
}

/*
 * "Unopposed" is a fact, not a blank. In 1968 and 1971 nobody else entered the Mr. Olympia, so the
 * runner-up cell says so rather than printing the same em-dash used for genuinely missing data.
 */
.bb-oly-solo {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--bb-accent);
}

.bb-oly-none {
    color: var(--bb-text-muted);
}

.bb-oly-src {
    font-family: var(--bb-font-mono);
    font-size: 11px;
    color: var(--bb-text-muted);
    margin: 10px 0 0;
}

/* ---- the numbered champion index ---------------------------------------- */

/*
 * Prefixed for the same reason as the answer heading: a bare .bb-oly-champs is (0,1,0) and the theme's
 * own `.entry-content ol` is (0,1,1), so list-style:none lost and the browser painted its decimal
 * marker as well as this counter - the same nineteen names numbered twice.
 */
.bb-oly-report .bb-oly-champs {
    list-style: none;
    counter-reset: bb-oly-champ;
    padding: 0;
    margin: 0 0 var(--bb-space-3);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 26px;
}

.bb-oly-report .bb-oly-champ-item {
    counter-increment: bb-oly-champ;
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 7px 0;
    margin: 0;
    border-bottom: 1px solid var(--bb-border-soft);
}

/*
 * The number is the point of this list - nineteen men in sixty-one years - so it is rendered from the
 * counter rather than left to a browser default that a theme list-style could remove.
 */
.bb-oly-report .bb-oly-champ-item::before {
    content: counter(bb-oly-champ);
    font-family: var(--bb-font-mono);
    font-size: 12px;
    font-weight: 700;
    color: var(--bb-accent);
    width: 20px;
    text-align: right;
    flex: none;
}

.bb-oly-champ-name {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    min-width: 0;
}

.bb-oly-champ-name b {
    font-size: 14.5px;
    font-weight: 600;
}

.bb-oly-champ-name a {
    color: var(--bb-text-primary);
    text-decoration: none;
}

.bb-oly-champ-name a:hover {
    color: var(--bb-accent);
    text-decoration: underline;
}

.bb-oly-champ-name small {
    color: var(--bb-text-muted);
    font-size: 11.5px;
}

/* ---- findings ----------------------------------------------------------- */

.bb-oly-find {
    border: 1px solid var(--bb-border);
    background: var(--bb-surface);
    padding: 20px 22px;
    margin: 0 0 var(--bb-space-4);
}

.bb-oly-find__head {
    margin: 0 0 4px;
    font-size: 18px;
    font-weight: 800;
    line-height: 1.25;
}

.bb-oly-find__lead {
    margin: 0 0 16px;
    font-size: 14.5px;
    color: var(--bb-text-secondary);
}

/* ---- ranked bars (two findings use these) -------------------------------- */

.bb-oly-bar {
    display: grid;
    grid-template-columns: 210px 1fr 26px 82px;
    gap: 10px;
    align-items: center;
    padding: 3px 0;
    font-size: 13.5px;
}

.bb-oly-bar__label {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--bb-text-secondary);
}

.bb-oly-bar__track {
    background: var(--bb-surface-sunken);
    height: 13px;
    position: relative;
}

.bb-oly-bar__fill {
    position: absolute;
    inset: 0 auto 0 0;
    background: var(--bb-warm-grey);
    opacity: 0.5;
}

.bb-oly-bar.is-dynasty .bb-oly-bar__fill {
    background: var(--bb-accent);
    opacity: 0.9;
}

.bb-oly-bar.is-dynasty .bb-oly-bar__label,
.bb-oly-bar.is-debut .bb-oly-bar__label {
    font-weight: 700;
    color: var(--bb-text-primary);
}

/*
 * The debut winner has a zero-length bar, so the row needs a mark of its own or it reads as missing
 * data. The hatched track says "nothing to measure here" rather than "no value recorded".
 */
.bb-oly-bar.is-debut .bb-oly-bar__track {
    background: repeating-linear-gradient(
        45deg,
        var(--bb-tint-2),
        var(--bb-tint-2) 3px,
        transparent 3px,
        transparent 7px
    );
}

.bb-oly-bar.is-debut .bb-oly-bar__value {
    color: var(--bb-amber-dark);
    font-weight: 700;
}

.bb-oly-bar__value,
.bb-oly-bar__trail {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-text-secondary);
    font-variant-numeric: tabular-nums;
}

.bb-oly-bar__trail {
    text-align: right;
    white-space: nowrap;
}

/* ---- podium columns ------------------------------------------------------ */

.bb-oly-pods {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 14px;
    padding: 6px 0 0;
}

.bb-oly-pod {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    flex: 1;
    min-width: 0;
}

.bb-oly-pod__stack {
    display: flex;
    flex-direction: column-reverse;
    gap: 3px;
}

.bb-oly-pod__blk {
    width: 26px;
    height: 11px;
    background: var(--bb-border);
    border-radius: 1px;
    display: block;
}

.bb-oly-pod__blk.is-second {
    background: var(--bb-accent);
    opacity: 0.85;
}

.bb-oly-pod__n {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    font-weight: 700;
    color: var(--bb-text-primary);
}

.bb-oly-pod__name {
    font-size: 11px;
    color: var(--bb-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* ---- the area chart ------------------------------------------------------ */

.bb-oly-chart {
    width: 100%;
    height: auto;
    display: block;
}

.bb-oly-chart__fill {
    fill: var(--bb-tint);
}

.bb-oly-chart__line {
    fill: none;
    stroke: var(--bb-accent);
    stroke-width: 2;
}

.bb-oly-chart circle {
    fill: var(--bb-accent);
}

.bb-oly-chart text {
    font-family: var(--bb-font-mono);
    font-size: 10px;
    fill: var(--bb-text-muted);
}

.bb-oly-chart__v {
    fill: var(--bb-text-primary);
    font-weight: 700;
    font-size: 11px;
}

/* ---- nationality --------------------------------------------------------- */

.bb-oly-nat {
    display: grid;
    grid-template-columns: 56px 200px 1fr;
    gap: 12px;
    align-items: center;
    padding: 5px 0;
    font-size: 13px;
}

.bb-oly-nat__dec {
    font-family: var(--bb-font-mono);
    font-size: 12px;
    color: var(--bb-text-secondary);
}

.bb-oly-nat__bar {
    display: flex;
    height: 16px;
    background: var(--bb-surface-sunken);
}

.bb-oly-nat__seg {
    background: var(--bb-warm-grey);
    border-right: 1px solid var(--bb-surface);
    color: var(--bb-on-dark);
    font-family: var(--bb-font-mono);
    font-size: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bb-oly-nat__seg.is-intl {
    background: var(--bb-accent);
}

.bb-oly-nat__names {
    font-family: var(--bb-font-mono);
    font-size: 10.5px;
    color: var(--bb-text-muted);
}

/* ---- narrow screens ------------------------------------------------------ */

@media (max-width: 640px) {
    .bb-oly-champs {
        grid-template-columns: 1fr;
    }

    .bb-oly-bar {
        grid-template-columns: 132px 1fr 22px 66px;
        gap: 7px;
    }

    .bb-oly-bar__label {
        gap: 6px;
    }

    .bb-oly-nat {
        grid-template-columns: 46px 1fr;
    }

    .bb-oly-nat__names {
        grid-column: 1 / -1;
    }

    .bb-oly-pods {
        gap: 7px;
    }

    .bb-oly-pod__blk {
        width: 17px;
    }

    .bb-oly-table td,
    .bb-oly-table thead th {
        padding-left: 10px;
        padding-right: 10px;
    }
}

/* ==========================================================================
   Event data blocks: roll of honour + this-edition-in-context
   Rendered by public/templates/partials/event-data-blocks.php on contest pages.
   The archive is the part of a contest page nobody else can publish, so it is
   styled as a first-class section rather than a footnote under the scorecard.
   ========================================================================== */

.bb-event-scale,
.bb-roll-of-honour {
    margin: 2.5rem 0;
}

.bb-event-scale__heading,
.bb-roll-of-honour__heading {
    font-size: 1.125rem;
    letter-spacing: .02em;
    margin: 0 0 .85rem;
    color: var(--bb-text-primary);
}

/* Auto-fit rather than a fixed column count: this block sits inside the article
   column on desktop and full-bleed on phones, and a 3-column grid at 320px
   crushes the numbers to two characters wide. */
.bb-event-scale__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: .75rem;
    margin: 0;
}

.bb-event-scale__stat {
    background: var(--bb-surface-raised);
    border: 1px solid var(--bb-border-soft);
    border-radius: 6px;
    padding: .7rem .85rem;
}

.bb-event-scale__stat dt {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--bb-text-muted);
    margin: 0 0 .2rem;
}

.bb-event-scale__stat dd {
    margin: 0;
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--bb-text-primary);
    /* Digits in adjacent cards must line up; without this the 1 in "1 of 38"
       is visibly narrower than the 3 beside it. */
    font-variant-numeric: tabular-nums;
}

.bb-event-scale__note {
    margin: .7rem 0 0;
    font-size: .9rem;
    color: var(--bb-text-muted);
}

/* The table can outgrow a phone at three columns of names. It scrolls inside
   its own container so the PAGE never scrolls sideways. */
.bb-roll-of-honour__scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--bb-border-soft);
    border-radius: 6px;
}

.bb-roll-of-honour__table {
    width: 100%;
    border-collapse: collapse;
    font-size: .95rem;
}

.bb-roll-of-honour__table th,
.bb-roll-of-honour__table td {
    padding: .55rem .8rem;
    text-align: left;
    border-bottom: 1px solid var(--bb-border-soft);
}

.bb-roll-of-honour__table thead th {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--bb-text-muted);
    background: var(--bb-surface-sunken);
    white-space: nowrap;
}

.bb-roll-of-honour__table tbody th[scope="row"] {
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.bb-roll-of-honour__table tbody tr:last-child th,
.bb-roll-of-honour__table tbody tr:last-child td {
    border-bottom: 0;
}

/* The edition being read. Marked with a left rule and weight rather than colour
   alone, so it survives a greyscale print and does not depend on hue. */
.bb-roll-of-honour__table tbody tr.is-current {
    background: var(--bb-surface-hover);
    box-shadow: inset 3px 0 0 var(--bb-accent);
}

.bb-roll-of-honour__table tbody tr.is-current th,
.bb-roll-of-honour__table tbody tr.is-current td {
    font-weight: 700;
}

/* --------------------------------------------------------------------------
   Embed context modifiers.

   .bb-app carries the tokens and .bb-embed the shared embed reset; these two
   modifiers say WHERE the embed sits, and each needs different spacing because
   an article body and a sidebar column have different rhythm. Both existed as
   markup hooks with no rule, which is how they showed up in the orphan ratchet:
   a modifier with no declarations is indistinguishable from a typo.
   -------------------------------------------------------------------------- */

/* Appended after an article body. It needs a clear break from the prose above
   it - the reader has finished the report and is now looking at the archive,
   and without separation the table reads as part of the closing paragraph. */
.bb-app.bb-embed--archive {
    margin-top: 2.75rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--bb-border-soft);
}

/* Inside a theme sidebar column, which is narrower and already has its own
   widget spacing, so it takes the separation without the top margin. */
.bb-app.bb-embed--sidebar {
    margin-top: 0;
}

/* --------------------------------------------------------------------------
   Hero search field.

   The containing block for the hero combobox. .bb-search-dropdown and
   .bb-search-spinner are both position:absolute and resolve against the nearest
   positioned ancestor; with the form static they escaped to a distant one and the
   dropdown opened 220px below the input at full container width, sitting under the
   stat row and clipped by the section that follows.

   flex:1 so the field takes the row and the submit button keeps its intrinsic
   width - the dropdown then matches the input rather than spanning the button.
   -------------------------------------------------------------------------- */
.bb-app .bb-hero-search-field {
    position: relative;
    display: block;
    flex: 1 1 auto;
    min-width: 0;
}

.bb-app .bb-hero-search-field > input {
    width: 100%;
}

/* The dropdown has to clear the hero's own stacking neighbours. .bb-search-dropdown
   ships z-index:100, which is enough inside the nav but not against the hero ledger
   and the section below it. Left-aligned because the hero centres its text and the
   options inherited that. */
.bb-app .bb-hero-search-field > .bb-search-dropdown {
    z-index: 300;
    text-align: left;
}

/* --------------------------------------------------------------------------
   The hero has to out-stack the sections below it, because its search dropdown
   overflows into them.

   .bb-hero-content carries z-index:1, which creates a stacking context - so the
   dropdown's own z-index:300 only orders things INSIDE the hero. Against the
   Olympia card that follows, the hero was competing at 1, and that card's static
   children painted straight over the bottom of the open dropdown. Visible as
   "UPCOMING / MR. OLYMPIA 2026" cutting through the last suggestion.

   Raising the hero itself is safe: it does not overflow anything except this
   dropdown, so nothing else of its box can cover the page below.
   -------------------------------------------------------------------------- */
.bb-app .bb-hero {
    z-index: 20;
}

/* =============================================================================
   OLYMPIA HUB (/bodybuilding/olympia/)
   Added 2026-08-13 with the hub rebuild. Every selector is scoped under .bb-app
   and namespaced bb-oly-*: the hub reuses .bb-card, .bb-btn and the dark hero from
   the shared layer and adds only what those do not already cover.
   ========================================================================== */

.bb-app .bb-oly-section {
    padding: var(--bb-space-8) 0 0;
}

.bb-app .bb-oly-section__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--bb-space-4);
    flex-wrap: wrap;
}

.bb-app .bb-oly-section__link {
    font-weight: 600;
    font-size: var(--bb-fs-sm);
    white-space: nowrap;
}

.bb-app .bb-oly-eyebrow {
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-size: var(--bb-fs-xs);
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--bb-amber-deep, #8f5a1e);
    margin: 0 0 var(--bb-space-1);
}

/*
 * Hero height. Measured before touching it: 507px, 56% of a 900px viewport, with the
 * first real section starting at y=856. The approved design puts the hub's content
 * near the top, so this trims the block rather than letting the shared hero's
 * generous spacing decide the page.
 */
.bb-app .bb-olympia-hero {
    padding: 26px clamp(18px, 4.4vw, 34px) 24px;
}

.bb-app .bb-olympia-hero .bb-page-title {
    margin-bottom: var(--bb-space-2);
}

.bb-app .bb-olympia-hero .bb-page-subtitle {
    max-width: 52ch;
    margin-bottom: 0;
}

/* Copy left, the champion faces right, as approved. */
.bb-app .bb-oly-hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    gap: var(--bb-space-8);
    align-items: center;
}

/* ---- hero additions: champion faces + the four-stat row ----------------- */
.bb-app .bb-oly-faces {
    margin-top: 0;
}

.bb-app .bb-oly-faces__row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    row-gap: var(--bb-space-2);
}

.bb-app .bb-oly-face {
    width: 46px;
    height: 46px;
    flex: 0 0 46px;
    border-radius: 50%;
    overflow: hidden;
    border: 2.5px solid rgba(250, 246, 239, 0.35);
    background: rgba(250, 246, 239, 0.12);
    margin-left: -12px;
}

.bb-app .bb-oly-faces__row .bb-oly-face:first-child {
    margin-left: 0;
}

.bb-app .bb-oly-face img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* An athlete with no portrait on file gets initials, never a broken frame. */
.bb-app .bb-oly-face--initials {
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-size: 14px;
    font-weight: 600;
    color: var(--bb-amber-bright, #d98b4a);
}

.bb-app .bb-oly-portrait.bb-oly-face--initials {
    color: var(--bb-amber-deep, #8f5a1e);
    font-size: 16px;
}

.bb-app .bb-oly-faces__caption {
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.68);
    margin: var(--bb-space-2) 0 0;
    max-width: 560px;
    line-height: 1.45;
}

.bb-app .bb-oly-faces__caption strong {
    color: rgba(255, 253, 248, 0.92);
}

/* Four stats do not fit the three-stat divider row at tablet width. */
.bb-app .bb-oly-authority {
    flex-wrap: wrap;
    row-gap: var(--bb-space-3);
    margin-top: var(--bb-space-5);
    padding: 10px 16px;
}

/*
 * The freshness line closes the stats bar: four counts say how much is here, this
 * says it is still being kept. Pushed to the trailing edge of the grid row.
 */
.bb-app .bb-oly-fresh {
    grid-column: -2 / -1;
    justify-self: end;
    align-self: center;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding-right: 6px;
    font-size: 12.5px;
    font-weight: 600;
    color: #8fbd86;
    white-space: nowrap;
}

.bb-app .bb-oly-fresh::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #8fbd86;
    flex: 0 0 8px;
}

/* The shared stat number is sized for a three-stat hero; four of them at that size
   wrapped the labels and added ~50px of hero for no extra information. */
.bb-app .bb-oly-authority .bb-olympia-hero-stat-num {
    font-size: 22px;
}

.bb-app .bb-oly-authority .bb-olympia-hero-stat-label {
    font-size: 11.5px;
}

/*
 * The height was never the type: each .bb-olympia-hero-stat carries 24px of padding
 * top and bottom, so four of them made a 128px band on their own. Measured, not
 * guessed - shrinking the numbers alone moved the hero by 4px.
 */
.bb-app .bb-oly-authority .bb-olympia-hero-stat {
    padding: 6px 18px;
}

/*
 * The shared stats row is a grid sized for THREE stats plus dividers. With four it
 * lays out 4 real columns and gives the three dividers 0px, so they render as
 * nothing anyway; and because one label wraps to a second line the stats sat 8px
 * out of alignment with each other. Drop the dividers on this variant and align to
 * the top so four uneven labels still read as one row.
 */
.bb-app .bb-oly-authority {
    align-items: start;
}

.bb-app .bb-oly-authority .bb-olympia-hero-stat-divider {
    display: none;
}

/* ---- on-this-page jump chips ------------------------------------------- */
.bb-app .bb-oly-jump {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bb-space-2);
    margin-top: var(--bb-space-5);
}

.bb-app .bb-oly-jump a {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: 999px;
    padding: 7px 14px;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--bb-text-primary);
    text-decoration: none;
}

.bb-app .bb-oly-jump a:hover,
.bb-app .bb-oly-jump a:focus-visible {
    border-color: var(--bb-primary);
    color: var(--bb-primary);
}

/* ---- upcoming ----------------------------------------------------------- */
.bb-app .bb-oly-next-grid {
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-5);
}

.bb-app .bb-oly-next-card {
    padding: var(--bb-space-6);
}

.bb-app .bb-oly-card-title {
    font-size: 18px;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 var(--bb-space-2);
}

.bb-app .bb-oly-card-sub {
    color: var(--bb-text-muted);
    font-size: var(--bb-fs-sm);
    margin: 0 0 var(--bb-space-2);
}

.bb-app .bb-oly-badge {
    display: inline-block;
    background: rgba(69, 114, 63, 0.12);
    color: #45723f;
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 3px 8px;
    border-radius: var(--bb-radius-sm);
    margin-bottom: var(--bb-space-3);
}

.bb-app .bb-oly-qual-list {
    list-style: none;
    margin: 0 0 var(--bb-space-4);
    padding: 0;
    font-size: var(--bb-fs-sm);
}

.bb-app .bb-oly-qual-list li {
    display: flex;
    align-items: baseline;
    gap: var(--bb-space-2);
    padding: 6px 0;
    border-bottom: 1px solid var(--bb-gray-100);
}

.bb-app .bb-oly-qual-list li:last-child {
    border-bottom: none;
}

.bb-app .bb-oly-qual-list__meta {
    margin-left: auto;
    color: var(--bb-text-muted);
    font-size: 12.5px;
    white-space: nowrap;
}

/* ---- division podium cards --------------------------------------------- */
.bb-app .bb-oly-div-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-5);
}

.bb-app .bb-oly-div-card {
    padding: var(--bb-space-4) var(--bb-space-5);
}

/* The Mr. Olympia card spans the row: it is the title the page is named for. */
.bb-app .bb-oly-div-card--lead {
    grid-column: 1 / -1;
}

.bb-app .bb-oly-div-card__head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--bb-space-2);
    margin-bottom: var(--bb-space-3);
}

.bb-app .bb-oly-div-card__division {
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--bb-amber-deep, #8f5a1e);
}

.bb-app .bb-oly-div-card__more {
    font-size: 12px;
    font-weight: 600;
}

.bb-app .bb-oly-div-card__champ {
    display: flex;
    gap: var(--bb-space-3);
    align-items: center;
}

.bb-app .bb-oly-portrait {
    width: 56px;
    height: 56px;
    flex: 0 0 56px;
    border-radius: var(--bb-radius-md);
    overflow: hidden;
    background: var(--bb-gray-100);
    border: 1px solid var(--bb-border);
}

.bb-app .bb-oly-portrait img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.bb-app .bb-oly-div-card--lead .bb-oly-portrait {
    width: 88px;
    height: 88px;
    flex-basis: 88px;
}

.bb-app .bb-oly-div-card__tag {
    display: block;
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bb-primary);
}

.bb-app .bb-oly-div-card__who a,
.bb-app .bb-oly-div-card__name {
    font-weight: 700;
    font-size: 15.5px;
    line-height: 1.2;
    color: var(--bb-text-primary);
    text-decoration: none;
}

.bb-app .bb-oly-div-card--lead .bb-oly-div-card__who a,
.bb-app .bb-oly-div-card--lead .bb-oly-div-card__name {
    font-size: 22px;
    letter-spacing: -0.01em;
}

.bb-app .bb-oly-div-card__who a:hover {
    color: var(--bb-primary);
}

.bb-app .bb-oly-podium {
    list-style: none;
    margin: var(--bb-space-3) 0 0;
    padding: 0;
}

.bb-app .bb-oly-podium li {
    display: flex;
    gap: var(--bb-space-2);
    align-items: baseline;
    padding: 5px 0;
    border-top: 1px solid var(--bb-gray-100);
    font-size: 13.5px;
}

.bb-app .bb-oly-podium li a,
.bb-app .bb-oly-podium li > span + span {
    color: var(--bb-text-muted);
}

.bb-app .bb-oly-podium__place {
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-variant-numeric: tabular-nums;
    font-size: 12px;
    color: var(--bb-text-muted);
    flex: 0 0 14px;
}

/*
 * The lead card spans the full row, so stacking its runners-up under the champion
 * left the right half of a 1200px card empty. Three columns instead: portrait,
 * champion, runners-up pushed to the trailing edge.
 */
/*
 * The podium list is a SIBLING of the champion block, not a child of it, so the
 * columns have to be declared on the card. Placing them on __champ put the rule on
 * an element the podium is not inside and it silently did nothing.
 */
.bb-app .bb-oly-div-card--lead {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: var(--bb-space-6);
}

.bb-app .bb-oly-div-card--lead .bb-oly-div-card__head {
    grid-column: 1 / -1;
}

.bb-app .bb-oly-div-card--lead .bb-oly-podium {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    text-align: right;
    border-left: 1px solid var(--bb-gray-100);
    padding-left: var(--bb-space-6);
}

.bb-app .bb-oly-div-card--lead .bb-oly-podium li {
    border-top: none;
    padding: 0;
    justify-content: flex-end;
}

/* ---- year chips --------------------------------------------------------- */
.bb-app .bb-oly-years {
    display: grid;
    grid-template-columns: 64px 1fr;
    gap: var(--bb-space-3) var(--bb-space-4);
    align-items: baseline;
    margin-top: var(--bb-space-5);
}

.bb-app .bb-oly-years__decade {
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--bb-text-muted);
}

.bb-app .bb-oly-years__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.bb-app .bb-oly-chip {
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-variant-numeric: tabular-nums;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-sm);
    padding: 5px 9px;
    font-size: 13px;
    color: var(--bb-text-primary);
    text-decoration: none;
}

.bb-app .bb-oly-chip:hover,
.bb-app .bb-oly-chip:focus-visible {
    border-color: var(--bb-primary);
    color: var(--bb-primary);
}

.bb-app .bb-oly-chip--latest {
    background: var(--bb-primary);
    border-color: var(--bb-primary);
    color: #fff;
    font-weight: 600;
}

.bb-app .bb-oly-chip--latest:hover {
    color: #fff;
}

/* ---- history, winners and tools cards ----------------------------------- */
.bb-app .bb-oly-flag-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-5);
}

.bb-app .bb-oly-flag-card {
    padding: var(--bb-space-5);
    text-decoration: none;
    color: var(--bb-text-primary);
    display: block;
}

.bb-app .bb-oly-flag-card__title {
    display: block;
    font-weight: 800;
    font-size: 17px;
    letter-spacing: -0.01em;
    margin-bottom: var(--bb-space-1);
}

.bb-app .bb-oly-flag-card__desc {
    color: var(--bb-text-muted);
    font-size: 13.5px;
}

.bb-app .bb-oly-hist-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-3);
}

.bb-app .bb-oly-tools {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--bb-space-3);
    margin-top: var(--bb-space-5);
}

.bb-app .bb-oly-hist-card {
    padding: var(--bb-space-4);
    text-decoration: none;
    color: var(--bb-text-primary);
    display: block;
}

.bb-app .bb-oly-hist-card__title {
    display: block;
    font-weight: 700;
    font-size: 14.5px;
    margin-bottom: 2px;
}

.bb-app .bb-oly-hist-card__desc {
    color: var(--bb-text-muted);
    font-size: 12.5px;
}

.bb-app .bb-oly-tool {
    padding: var(--bb-space-4) var(--bb-space-5);
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--bb-space-2);
    text-decoration: none;
    color: var(--bb-text-primary);
}

.bb-app .bb-oly-tool__name {
    font-weight: 700;
    font-size: 15px;
}

.bb-app .bb-oly-tool__meta {
    font-family: var(--bb-font-mono, 'IBM Plex Mono', monospace);
    font-size: 11.5px;
    color: var(--bb-text-muted);
}

.bb-app .bb-oly-tool:hover .bb-oly-tool__name,
.bb-app .bb-oly-flag-card:hover .bb-oly-flag-card__title,
.bb-app .bb-oly-hist-card:hover .bb-oly-hist-card__title {
    color: var(--bb-primary);
}

/* ---- responsive --------------------------------------------------------- */
@media (max-width: 900px) {
    .bb-app .bb-oly-next-grid {
        grid-template-columns: 1fr;
    }

    .bb-app .bb-oly-div-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .bb-app .bb-oly-hist-grid,
    .bb-app .bb-oly-tools {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 560px) {
    .bb-app .bb-oly-div-grid,
    .bb-app .bb-oly-flag-grid,
    .bb-app .bb-oly-hist-grid,
    .bb-app .bb-oly-tools {
        grid-template-columns: 1fr;
    }

    .bb-app .bb-oly-years {
        grid-template-columns: 1fr;
        gap: var(--bb-space-1) 0;
    }

    .bb-app .bb-oly-face {
        width: 44px;
        height: 44px;
        flex-basis: 44px;
        margin-left: -10px;
    }

    /*
     * The lead card drops to one column too. Left as a two-column grid it gave the
     * champion 191px of a 390px screen and pushed his name onto three lines, with
     * the runners-up rail crushed beside him.
     */
    .bb-app .bb-oly-div-card--lead {
        grid-template-columns: 1fr;
        row-gap: var(--bb-space-3);
    }

    .bb-app .bb-oly-div-card--lead .bb-oly-podium {
        flex-direction: column;
        gap: var(--bb-space-1);
        text-align: left;
        border-left: none;
        border-top: 1px solid var(--bb-gray-100);
        padding-left: 0;
        padding-top: var(--bb-space-3);
    }

    .bb-app .bb-oly-div-card--lead .bb-oly-podium li {
        justify-content: flex-start;
    }

    /* The oversized lead portrait is desktop framing; 88px crowds a phone card. */
    .bb-app .bb-oly-div-card--lead .bb-oly-portrait {
        width: 64px;
        height: 64px;
        flex-basis: 64px;
    }

    .bb-app .bb-oly-div-card--lead .bb-oly-div-card__who a,
    .bb-app .bb-oly-div-card--lead .bb-oly-div-card__name {
        font-size: 19px;
    }
}

/*
 * One unbroken row of champions, but ONLY where there is room for it. Applied
 * unconditionally this forced 11 x 44px of faces into a ~330px phone column and
 * clipped both the faces and the subtitle beside them.
 */
@media (min-width: 901px) {
    .bb-app .bb-oly-hero-grid .bb-oly-faces__row {
        flex-wrap: nowrap;
    }
}

@media (max-width: 900px) {
    .bb-app .bb-oly-hero-grid {
        grid-template-columns: 1fr;
        gap: var(--bb-space-5);
    }

    .bb-app .bb-oly-fresh {
        grid-column: auto;
        justify-self: start;
    }
}

@media (max-width: 560px) {
    /*
     * One stat per row made a 342px band and a 637px hero, 75% of a phone screen.
     * Two by two, with the freshness line spanning the foot.
     */
    .bb-app .bb-oly-authority {
        grid-template-columns: 1fr 1fr;
        row-gap: var(--bb-space-2);
        padding: 12px 14px;
    }

    .bb-app .bb-oly-authority .bb-olympia-hero-stat {
        padding: 4px 0;
    }

    .bb-app .bb-oly-fresh {
        grid-column: 1 / -1;
        padding-top: var(--bb-space-2);
        border-top: 1px solid rgba(255, 255, 255, 0.12);
        width: 100%;
    }
}
